Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 96ae1e1320 | |||
| 88708eedb0 | |||
| 89435aa87f | |||
| 0cbb23abe1 | |||
| a2915f78c5 | |||
| 99cb17aed3 | |||
| 8fd8d0c24a | |||
| c57b0d28b0 | |||
| 523ee762f0 | |||
| feeed75cf1 | |||
| c7ee1a59eb | |||
| 2725202771 | |||
| 42fafdcdfe | |||
| c8de759cd6 | |||
| fb9d1cefcc | |||
| a9b1bd88d3 | |||
| 1ff096ac5c | |||
| 0ea757ed02 | |||
| cd4de34f5f | |||
| 42cbca0ff0 | |||
| 39c74498f7 | |||
| 5b26eac258 | |||
| dcd615ef2a | |||
| 98e8c2e06c | |||
| c1ed73126d | |||
| 01b1673c8a | |||
| d4dc297f75 | |||
| 9aaab7a53f | |||
| 1a6f4c44e7 | |||
| 163a2cfe3c | |||
| 667fd198ac | |||
| 3eaa676626 | |||
| 8b34d5b40c | |||
| 49cf294d2f | |||
| b7a990d0b5 | |||
| 8306ed8ae3 | |||
| 640df69aa1 | |||
| 8b48e2ccc6 | |||
| babdced52f | |||
| 21607e0cb2 | |||
| 24646aada9 | |||
| 51b74a99aa | |||
| ed5003b502 | |||
| 46dc660801 | |||
| 73fb53cf36 | |||
| efe6840d08 | |||
| 45f64e672f | |||
| 298a8e4d2f | |||
| a37f43bf3f | |||
| e562d34639 | |||
| e1d6a10fc6 | |||
| 6b4665c7b2 | |||
| 7e2fd63f0a | |||
| ee7dcbbb5b | |||
| 09211b76e0 | |||
| 8654b16d8b | |||
| edc4522f9b | |||
| 5d2cd4d0f2 | |||
| cd2178905f | |||
| aaf0c1ebb3 | |||
| d0ff3088e2 | |||
| 51e1cbc658 | |||
| 4cdfae0a80 | |||
| cc423f1de5 | |||
| d259848456 | |||
| 8a82d3929c | |||
| 89fce286a7 | |||
| 11c7ddc84d | |||
| 54e50a67a8 | |||
| c00c157479 | |||
| ee8e0f890a | |||
| 1e2ffee97c | |||
| ffc39b8ad2 | |||
| 70969186f6 | |||
| dff76d31d5 | |||
| 3254686933 | |||
| a6dfff725b | |||
| 10237b8761 | |||
| 79de092bb2 | |||
| 82aa369db3 | |||
| 0583582772 | |||
| 99809e105c | |||
| 6d361ced41 | |||
| 790fa901c7 | |||
| 7f9d591ab7 | |||
| b503e96a98 | |||
| d691af4860 | |||
| befd9dc5ae |
+11
-1
@@ -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: '*'
|
||||
|
||||
+294
-189
@@ -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,13 +29,12 @@ 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: 18
|
||||
- run: node --version
|
||||
@@ -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: 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,42 +164,42 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: gcc-9-debug-cov
|
||||
- name: gcc-13-debug-cov
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-20.04
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: gcc-9
|
||||
CCOMPILER: gcc-13
|
||||
CUCUMBER_TIMEOUT: 20000
|
||||
CXXCOMPILER: g++-9
|
||||
CXXCOMPILER: g++-13
|
||||
ENABLE_COVERAGE: ON
|
||||
|
||||
- name: gcc-9-debug-asan-ubsan
|
||||
- name: clang-15-debug-asan-ubsan
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-20.04
|
||||
node: 20
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: gcc-9
|
||||
CCOMPILER: clang-15
|
||||
CUCUMBER_TIMEOUT: 20000
|
||||
CXXCOMPILER: g++-9
|
||||
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
|
||||
- name: clang-15-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: clang-6.0
|
||||
CXXCOMPILER: clang++-6.0
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
|
||||
- name: clang-15.0-debug-clang-tidy
|
||||
- name: clang-15-debug
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -189,100 +208,98 @@ jobs:
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
|
||||
- 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-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-11
|
||||
CXXCOMPILER: clang++-11
|
||||
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-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-6.0
|
||||
CXXCOMPILER: clang++-6.0
|
||||
CCOMPILER: clang-15
|
||||
CXXCOMPILER: clang++-15
|
||||
ENABLE_CONAN: ON
|
||||
|
||||
- name: gcc-14-release
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-24.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-14
|
||||
CXXCOMPILER: g++-14
|
||||
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
|
||||
|
||||
- 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-12-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
node: 20
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-12
|
||||
CXXCOMPILER: g++-12
|
||||
ENABLE_BENCHMARKS: ON
|
||||
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
|
||||
|
||||
- name: gcc-11-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-20.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-11
|
||||
CXXCOMPILER: g++-11
|
||||
ENABLE_BENCHMARKS: ON
|
||||
|
||||
- name: gcc-10-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-20.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-10
|
||||
CXXCOMPILER: g++-10
|
||||
|
||||
- name: gcc-9-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
runs-on: ubuntu-20.04
|
||||
BUILD_TOOLS: ON
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: gcc-9
|
||||
CXXCOMPILER: g++-9
|
||||
CXXFLAGS: -Wno-cast-function-type
|
||||
|
||||
- name: gcc-9-conan-release-i686
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
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: gcc-8-release
|
||||
continue-on-error: false
|
||||
node: 18
|
||||
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: 20
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang-6.0
|
||||
CXXCOMPILER: clang++-6.0
|
||||
CCOMPILER: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
ENABLE_CONAN: ON
|
||||
NODE_PACKAGE_TESTS_ONLY: ON
|
||||
|
||||
@@ -290,10 +307,10 @@ jobs:
|
||||
build_node_package: true
|
||||
continue-on-error: false
|
||||
node: 20
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
BUILD_TYPE: Debug
|
||||
CCOMPILER: clang-6.0
|
||||
CXXCOMPILER: clang++-6.0
|
||||
CCOMPILER: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
ENABLE_CONAN: ON
|
||||
NODE_PACKAGE_TESTS_ONLY: ON
|
||||
|
||||
@@ -301,7 +318,7 @@ jobs:
|
||||
build_node_package: true
|
||||
continue-on-error: true
|
||||
node: 20
|
||||
runs-on: macos-11
|
||||
runs-on: macos-13 # x86_64
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang
|
||||
CXXCOMPILER: clang++
|
||||
@@ -313,14 +330,13 @@ jobs:
|
||||
build_node_package: true
|
||||
continue-on-error: true
|
||||
node: 20
|
||||
runs-on: macos-11
|
||||
runs-on: macos-14 # arm64
|
||||
BUILD_TYPE: Release
|
||||
CCOMPILER: clang
|
||||
CXXCOMPILER: clang++
|
||||
CUCUMBER_TIMEOUT: 60000
|
||||
ENABLE_ASSERTIONS: ON
|
||||
ENABLE_CONAN: ON
|
||||
ENABLE_APPLE_SILICON: ON
|
||||
|
||||
name: ${{ matrix.name}}
|
||||
continue-on-error: ${{ matrix.continue-on-error }}
|
||||
@@ -340,48 +356,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: v7-conan-${{ matrix.name }}-${{ github.sha }}
|
||||
key: v9-conan-${{ matrix.name }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
v7-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 +408,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 +416,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 +463,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
|
||||
@@ -473,18 +507,8 @@ jobs:
|
||||
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} \
|
||||
@@ -495,15 +519,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
|
||||
@@ -512,14 +534,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
|
||||
|
||||
@@ -530,86 +552,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 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' && 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: 20
|
||||
- name: Run Node package tests on Node 20
|
||||
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 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
|
||||
# - 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
|
||||
# uses: codecov/codecov-action@v4
|
||||
# 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: Build Node package
|
||||
if: ${{ matrix.build_node_package }}
|
||||
run: ./scripts/ci/node_package.sh
|
||||
@@ -626,9 +628,112 @@ 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: clang-13
|
||||
CXXCOMPILER: clang++-13
|
||||
CC: clang-13
|
||||
CXX: clang++-13
|
||||
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"
|
||||
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"
|
||||
|
||||
@@ -1,21 +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)
|
||||
@@ -41,6 +63,12 @@
|
||||
- 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)
|
||||
|
||||
|
||||
+8
-15
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -118,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)
|
||||
|
||||
@@ -226,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")
|
||||
@@ -270,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)
|
||||
@@ -312,7 +307,7 @@ 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})
|
||||
|
||||
@@ -333,7 +328,7 @@ if(ENABLE_CONAN)
|
||||
|
||||
conan_check(REQUIRED)
|
||||
|
||||
set(CONAN_BOOST_VERSION "1.79.0@#96e4902111a2e343a8ba0aa95391bb58")
|
||||
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")
|
||||
@@ -362,7 +357,7 @@ if(ENABLE_CONAN)
|
||||
KEEP_RPATHS
|
||||
NO_OUTPUT_DIRS
|
||||
OPTIONS boost:filesystem_version=3 # https://stackoverflow.com/questions/73392648/error-with-boost-filesystem-version-in-cmake
|
||||
onetbb:shared=${TBB_SHARED}
|
||||
# onetbb:shared=${TBB_SHARED}
|
||||
boost:without_stacktrace=True # Apple Silicon cross-compilation fails without it
|
||||
BUILD missing
|
||||
)
|
||||
@@ -610,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)
|
||||
@@ -630,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)
|
||||
|
||||
+1
-1
@@ -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`
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@ 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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
+7
-7
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,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,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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ struct MatchParameters : public RouteParameters
|
||||
MatchParameters(const std::vector<unsigned> ×tamps_,
|
||||
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_)
|
||||
|
||||
@@ -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});
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_},
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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_}
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -214,7 +214,7 @@ struct PhantomNode
|
||||
util::Coordinate input_location;
|
||||
unsigned short fwd_segment_position;
|
||||
// is phantom node valid to be used as source or target
|
||||
private:
|
||||
// private:
|
||||
unsigned short is_valid_forward_source : 1;
|
||||
unsigned short is_valid_forward_target : 1;
|
||||
unsigned short is_valid_reverse_source : 1;
|
||||
@@ -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
|
||||
|
||||
@@ -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 ¶ms,
|
||||
@@ -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 ") +
|
||||
|
||||
@@ -39,7 +39,8 @@ std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter
|
||||
begin,
|
||||
end,
|
||||
[&delta_numbers, ¤t_lat, ¤t_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,
|
||||
@@ -474,6 +471,23 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const PhantomNode &target_phantom,
|
||||
EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
inline double getNetworkDistanceOld(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const DataFacade<ch::Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
return getNetworkDistance(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
source_phantom,
|
||||
target_phantom,
|
||||
duration_upper_bound);
|
||||
}
|
||||
|
||||
template <typename EdgeMetric>
|
||||
std::tuple<EdgeMetric, EdgeDistance> getLoopMetric(const DataFacade<Algorithm> &facade, NodeID node)
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
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);
|
||||
|
||||
@@ -451,43 +510,73 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
EdgeWeight weight = weight_upper_bound;
|
||||
EdgeWeight forward_heap_min = forward_heap.MinKey();
|
||||
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
|
||||
// if (!reverse_heap.Empty())
|
||||
// reverse_heap_min = reverse_heap.MinKey();
|
||||
#if 0
|
||||
while (forward_heap.Size() + reverse_heap.Size() > 0 && (
|
||||
forward_heap_min < weight || reverse_heap_min < weight))
|
||||
#else
|
||||
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
||||
forward_heap_min + reverse_heap_min < weight)
|
||||
(forward_heap_min + reverse_heap_min < weight))
|
||||
#endif
|
||||
{
|
||||
// std::cerr << "F: " << forward_heap_min << " R: " << reverse_heap_min << " W: " << weight
|
||||
// << std::endl;
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
// while (!reverse_heap.Empty() && (reverse_heap_min < weight)) {
|
||||
// routingStep<REVERSE_DIRECTION>(
|
||||
// facade, reverse_heap, forward_heap, middle, weight, force_step_nodes, args...);
|
||||
// if (!reverse_heap.Empty())
|
||||
// reverse_heap_min = reverse_heap.MinKey();
|
||||
// }
|
||||
|
||||
// No path found for both target nodes?
|
||||
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::cerr << "MIDDLE = " << middle << std::endl;
|
||||
|
||||
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 +594,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 +614,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 +635,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, weight] = *searchResult;
|
||||
// std::cerr << "W: " << weight << std::endl;
|
||||
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 +668,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 +677,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 +704,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,40 +717,166 @@ 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)
|
||||
{
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
// forward_heap.Clear();
|
||||
|
||||
// if (forward_heap.Empty())
|
||||
// {
|
||||
// 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()});
|
||||
// }
|
||||
// } else {
|
||||
// const auto node =
|
||||
// forward_heap.GetHeapNodeIfWasInserted(target_phantom.forward_segment_id.id); if (node) {
|
||||
// std::cerr << "Found " << target_phantom.forward_segment_id.id << " in forward_heap "
|
||||
// << node->data.distance << std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// forward_heap.Clear();
|
||||
if (forward_heap.Empty())
|
||||
{
|
||||
if (source_phantom.IsValidForwardSource())
|
||||
{
|
||||
forward_heap.Insert(source_phantom.forward_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{source_phantom.forward_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
if (source_phantom.IsValidReverseSource())
|
||||
{
|
||||
forward_heap.Insert(source_phantom.reverse_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{source_phantom.reverse_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target_phantom.IsValidForwardTarget())
|
||||
{
|
||||
if (forward_heap.WasInserted(target_phantom.forward_segment_id.id))
|
||||
{
|
||||
std::cerr << "Found " << target_phantom.forward_segment_id.id << " in forward_heap"
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Not found " << target_phantom.forward_segment_id.id
|
||||
<< " in forward_heap" << std::endl;
|
||||
}
|
||||
}
|
||||
if (target_phantom.IsValidReverseTarget())
|
||||
{
|
||||
if (forward_heap.WasInserted(target_phantom.reverse_segment_id.id))
|
||||
{
|
||||
std::cerr << "Found " << target_phantom.reverse_segment_id.id << " in forward_heap"
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Not found " << target_phantom.reverse_segment_id.id
|
||||
<< " in forward_heap" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target_phantom.IsValidForwardTarget())
|
||||
{
|
||||
reverse_heap.Insert(target_phantom.forward_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{target_phantom.forward_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
if (target_phantom.IsValidReverseTarget())
|
||||
{
|
||||
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{target_phantom.reverse_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
return from_alias<double>(distance);
|
||||
}
|
||||
|
||||
std::vector<PathData> unpacked_path;
|
||||
template <typename Algorithm>
|
||||
double
|
||||
getNetworkDistanceOld(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const DataFacade<Algorithm> &facade,
|
||||
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)
|
||||
{
|
||||
reverse_heap.Clear();
|
||||
forward_heap.Clear();
|
||||
|
||||
annotatePath(facade, endpoints, unpacked_nodes, unpacked_edges, unpacked_path);
|
||||
if (source_phantom.IsValidForwardSource())
|
||||
{
|
||||
forward_heap.Insert(source_phantom.forward_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{source_phantom.forward_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
||||
if (source_phantom.IsValidReverseSource())
|
||||
{
|
||||
forward_heap.Insert(source_phantom.reverse_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{source_phantom.reverse_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
if (target_phantom.IsValidForwardTarget())
|
||||
{
|
||||
reverse_heap.Insert(target_phantom.forward_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{target_phantom.forward_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
if (target_phantom.IsValidReverseTarget())
|
||||
{
|
||||
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
|
||||
EdgeWeight{0},
|
||||
{target_phantom.reverse_segment_id.id, false, EdgeDistance{0}});
|
||||
}
|
||||
|
||||
const PhantomEndpoints endpoints{source_phantom, target_phantom};
|
||||
|
||||
auto distance = searchDistance(
|
||||
engine_working_data, facade, forward_heap, reverse_heap, {}, weight_upper_bound, endpoints);
|
||||
|
||||
if (distance == INVALID_EDGE_DISTANCE)
|
||||
{
|
||||
return std::numeric_limits<double>::max();
|
||||
}
|
||||
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]));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
|
||||
@@ -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 ¤t_node) {
|
||||
auto decode = [&](const auto ¤t_node)
|
||||
{
|
||||
coordinates[index].lon = current_node.lon;
|
||||
coordinates[index].lat = current_node.lat;
|
||||
osm_node_ids.push_back(current_node.node_id);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,23 +13,22 @@ 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.count({via, to}))
|
||||
if (unidirectional_segments.contains({via, to}))
|
||||
{
|
||||
unidirectional_segments.erase({via, to});
|
||||
unidirectional_segments.insert({from, to});
|
||||
}
|
||||
if (unidirectional_segments.count({via, from}))
|
||||
if (unidirectional_segments.contains({via, from}))
|
||||
{
|
||||
unidirectional_segments.erase({via, from});
|
||||
unidirectional_segments.insert({to, from});
|
||||
|
||||
@@ -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>>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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; },
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,7 +21,7 @@ template <typename Base> class NodeEntryWrapper : public Base
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
NodeEntryWrapper(std::size_t edges_begin_, std::size_t edges_end_, Args &&... args)
|
||||
NodeEntryWrapper(std::size_t edges_begin_, std::size_t edges_end_, Args &&...args)
|
||||
: Base(std::forward<Args>(args)...), edges_begin(edges_begin_), edges_end(edges_end_)
|
||||
{
|
||||
}
|
||||
@@ -41,7 +41,7 @@ template <typename Base> class GraphConstructionWrapper : public Base
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
GraphConstructionWrapper(const NodeID source_, Args &&... args)
|
||||
GraphConstructionWrapper(const NodeID source_, Args &&...args)
|
||||
: Base(std::forward<Args>(args)...), source(source_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,11 +59,13 @@ std::size_t removeUnconnectedBoundaryNodes(const GraphT &edge_based_graph,
|
||||
|
||||
if (level_index < static_cast<int>(partitions.size() - 1))
|
||||
{
|
||||
auto new_end = std::remove_if(
|
||||
witnesses.begin(), witnesses.end(), [&](const auto &witness) {
|
||||
return partitions[level_index + 1][node] !=
|
||||
partitions[level_index + 1][witness.id];
|
||||
});
|
||||
auto new_end =
|
||||
std::remove_if(witnesses.begin(),
|
||||
witnesses.end(),
|
||||
[&](const auto &witness) {
|
||||
return partitions[level_index + 1][node] !=
|
||||
partitions[level_index + 1][witness.id];
|
||||
});
|
||||
witnesses.resize(new_end - witnesses.begin());
|
||||
}
|
||||
if (witnesses.size() == 0)
|
||||
@@ -87,10 +89,12 @@ std::size_t removeUnconnectedBoundaryNodes(const GraphT &edge_based_graph,
|
||||
}
|
||||
}
|
||||
|
||||
auto best_witness = std::min_element(
|
||||
witnesses.begin(), witnesses.end(), [](const auto &lhs, const auto &rhs) {
|
||||
return lhs.induced_border_edges < rhs.induced_border_edges;
|
||||
});
|
||||
auto best_witness =
|
||||
std::min_element(witnesses.begin(),
|
||||
witnesses.end(),
|
||||
[](const auto &lhs, const auto &rhs) {
|
||||
return lhs.induced_border_edges < rhs.induced_border_edges;
|
||||
});
|
||||
BOOST_ASSERT(best_witness != witnesses.end());
|
||||
|
||||
// assign `node` to same subcells as `best_witness`
|
||||
|
||||
@@ -30,10 +30,10 @@ void reorderFirstLast(RandomIt first, RandomIt last, std::size_t n, Comparator c
|
||||
// requirements.
|
||||
std::reverse_iterator<RandomIt> rfirst{last}, rlast{first + n};
|
||||
|
||||
const auto flipped = [](auto fn) {
|
||||
return [fn](auto &&lhs, auto &&rhs) {
|
||||
return fn(std::forward<decltype(lhs)>(rhs), std::forward<decltype(rhs)>(lhs));
|
||||
};
|
||||
const auto flipped = [](auto fn)
|
||||
{
|
||||
return [fn](auto &&lhs, auto &&rhs)
|
||||
{ return fn(std::forward<decltype(lhs)>(rhs), std::forward<decltype(rhs)>(lhs)); };
|
||||
};
|
||||
|
||||
std::nth_element(rfirst, rfirst + (n - 1), rlast, flipped(comp));
|
||||
|
||||
@@ -74,16 +74,16 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
: BaseParametersGrammar::base_type(root_rule)
|
||||
{
|
||||
const auto add_hint = [](engine::api::BaseParameters &base_parameters,
|
||||
const std::vector<std::string> &hint_strings) {
|
||||
const std::vector<std::string> &hint_strings)
|
||||
{
|
||||
if (!hint_strings.empty())
|
||||
{
|
||||
std::vector<engine::SegmentHint> location_hints(hint_strings.size());
|
||||
std::transform(hint_strings.begin(),
|
||||
hint_strings.end(),
|
||||
location_hints.begin(),
|
||||
[](const auto &hint_string) {
|
||||
return engine::SegmentHint::FromBase64(hint_string);
|
||||
});
|
||||
[](const auto &hint_string)
|
||||
{ return engine::SegmentHint::FromBase64(hint_string); });
|
||||
base_parameters.hints.push_back(engine::Hint{std::move(location_hints)});
|
||||
}
|
||||
else
|
||||
@@ -94,15 +94,16 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
|
||||
const auto add_bearing =
|
||||
[](engine::api::BaseParameters &base_parameters,
|
||||
boost::optional<boost::fusion::vector2<short, short>> bearing_range) {
|
||||
boost::optional<engine::Bearing> bearing;
|
||||
if (bearing_range)
|
||||
{
|
||||
bearing = engine::Bearing{boost::fusion::at_c<0>(*bearing_range),
|
||||
boost::fusion::at_c<1>(*bearing_range)};
|
||||
}
|
||||
base_parameters.bearings.push_back(std::move(bearing));
|
||||
};
|
||||
boost::optional<boost::fusion::vector2<short, short>> bearing_range)
|
||||
{
|
||||
boost::optional<engine::Bearing> bearing;
|
||||
if (bearing_range)
|
||||
{
|
||||
bearing = engine::Bearing{boost::fusion::at_c<0>(*bearing_range),
|
||||
boost::fusion::at_c<1>(*bearing_range)};
|
||||
}
|
||||
base_parameters.bearings.push_back(std::move(bearing));
|
||||
};
|
||||
|
||||
polyline_chars = qi::char_("a-zA-Z0-9_.--[]{}@?|\\%~`^");
|
||||
base64_char = qi::char_("a-zA-Z0-9--_=");
|
||||
@@ -118,7 +119,8 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
|
||||
location_rule = (double_ > qi::lit(',') >
|
||||
double_)[qi::_val = ph::bind(
|
||||
[](double lon, double lat) {
|
||||
[](double lon, double lat)
|
||||
{
|
||||
return util::Coordinate(
|
||||
util::toFixed(util::UnsafeFloatLongitude{lon}),
|
||||
util::toFixed(util::UnsafeFloatLatitude{lat}));
|
||||
@@ -126,19 +128,17 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::_1,
|
||||
qi::_2)];
|
||||
|
||||
polyline_rule = qi::as_string[qi::lit("polyline(") > +polyline_chars > ')']
|
||||
[qi::_val = ph::bind(
|
||||
[](const std::string &polyline) {
|
||||
return engine::decodePolyline(polyline);
|
||||
},
|
||||
qi::_1)];
|
||||
polyline_rule =
|
||||
qi::as_string[qi::lit("polyline(") > +polyline_chars > ')']
|
||||
[qi::_val = ph::bind([](const std::string &polyline)
|
||||
{ return engine::decodePolyline(polyline); },
|
||||
qi::_1)];
|
||||
|
||||
polyline6_rule = qi::as_string[qi::lit("polyline6(") > +polyline_chars > ')']
|
||||
[qi::_val = ph::bind(
|
||||
[](const std::string &polyline) {
|
||||
return engine::decodePolyline<1000000>(polyline);
|
||||
},
|
||||
qi::_1)];
|
||||
polyline6_rule =
|
||||
qi::as_string[qi::lit("polyline6(") > +polyline_chars > ')']
|
||||
[qi::_val = ph::bind([](const std::string &polyline)
|
||||
{ return engine::decodePolyline<1000000>(polyline); },
|
||||
qi::_1)];
|
||||
|
||||
query_rule =
|
||||
((location_rule % ';') | polyline_rule |
|
||||
|
||||
@@ -54,8 +54,9 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
||||
#endif
|
||||
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
|
||||
|
||||
const auto add_annotation = [](engine::api::RouteParameters &route_parameters,
|
||||
AnnotationsType route_param) {
|
||||
const auto add_annotation =
|
||||
[](engine::api::RouteParameters &route_parameters, AnnotationsType route_param)
|
||||
{
|
||||
route_parameters.annotations_type = route_parameters.annotations_type | route_param;
|
||||
route_parameters.annotations =
|
||||
route_parameters.annotations_type != AnnotationsType::None;
|
||||
|
||||
@@ -14,18 +14,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// workaround for incomplete std::shared_ptr compatibility in old boost versions
|
||||
#if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T> const T *get_pointer(std::shared_ptr<T> const &p) { return p.get(); }
|
||||
|
||||
template <class T> T *get_pointer(std::shared_ptr<T> &p) { return p.get(); }
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
namespace osrm::server
|
||||
{
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ struct header
|
||||
// explicitly use default copy c'tor as adding move c'tor
|
||||
header &operator=(const header &other) = default;
|
||||
header(std::string name, std::string value) : name(std::move(name)), value(std::move(value)) {}
|
||||
header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {}
|
||||
header(header &&other) noexcept : name(std::move(other.name)), value(std::move(other.value)) {}
|
||||
|
||||
void clear()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "osrm/osrm.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
#include <variant>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@ void readBoolVector(tar::FileReader &reader, const std::string &name, VectorT &d
|
||||
using BlockType = std::uint64_t;
|
||||
constexpr std::uint64_t BLOCK_BITS = CHAR_BIT * sizeof(BlockType);
|
||||
|
||||
const auto decode = [&](const BlockType block) {
|
||||
const auto decode = [&](const BlockType block)
|
||||
{
|
||||
auto read_size = std::min<std::size_t>(count - index, BLOCK_BITS);
|
||||
unpackBits<VectorT, BlockType>(data, index, read_size, block);
|
||||
index += BLOCK_BITS;
|
||||
@@ -87,7 +88,8 @@ void writeBoolVector(tar::FileWriter &writer, const std::string &name, const Vec
|
||||
|
||||
// FIXME on old boost version the function_input_iterator does not work with lambdas
|
||||
// so we need to wrap it in a function here.
|
||||
const std::function<BlockType()> encode_function = [&]() -> BlockType {
|
||||
const std::function<BlockType()> encode_function = [&]() -> BlockType
|
||||
{
|
||||
auto write_size = std::min<std::size_t>(count - index, BLOCK_BITS);
|
||||
auto packed = packBits<VectorT, BlockType>(data, index, write_size);
|
||||
index += BLOCK_BITS;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user