Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ec2712fe1 | |||
| 8b806cb7bd | |||
| d259848456 | |||
| 8a82d3929c | |||
| 89fce286a7 | |||
| 11c7ddc84d | |||
| 54e50a67a8 | |||
| c00c157479 | |||
| ee8e0f890a | |||
| 1e2ffee97c | |||
| ffc39b8ad2 | |||
| 70969186f6 | |||
| dff76d31d5 | |||
| 3254686933 | |||
| a6dfff725b | |||
| 10237b8761 | |||
| 79de092bb2 | |||
| 82aa369db3 | |||
| 0583582772 | |||
| 99809e105c | |||
| 56d2d4dacd | |||
| 6d361ced41 | |||
| 790fa901c7 | |||
| 7f9d591ab7 | |||
| b503e96a98 | |||
| d691af4860 | |||
| befd9dc5ae | |||
| 1107a14a2c | |||
| 5b23b11129 | |||
| 23fb96c4f2 | |||
| 45bfe937aa |
+168
-151
@@ -19,6 +19,10 @@ env:
|
|||||||
CMAKE_VERSION: 3.21.2
|
CMAKE_VERSION: 3.21.2
|
||||||
ENABLE_NODE_BINDINGS: "ON"
|
ENABLE_NODE_BINDINGS: "ON"
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows-release-node:
|
windows-release-node:
|
||||||
needs: format-taginfo-docs
|
needs: format-taginfo-docs
|
||||||
@@ -26,7 +30,6 @@ jobs:
|
|||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
env:
|
env:
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
ENABLE_APPLE_SILICON: "OFF"
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: pip install "conan<2.0.0"
|
- run: pip install "conan<2.0.0"
|
||||||
@@ -71,7 +74,7 @@ jobs:
|
|||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
format-taginfo-docs:
|
format-taginfo-docs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
@@ -88,7 +91,7 @@ jobs:
|
|||||||
- name: Prepare environment
|
- name: Prepare environment
|
||||||
run: |
|
run: |
|
||||||
npm ci --ignore-scripts
|
npm ci --ignore-scripts
|
||||||
clang-format-10 --version
|
clang-format-15 --version
|
||||||
- name: Run checks
|
- name: Run checks
|
||||||
run: |
|
run: |
|
||||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||||
@@ -145,42 +148,52 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- name: gcc-9-debug-cov
|
- name: gcc-13-debug-cov
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 20
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Debug
|
||||||
CCOMPILER: gcc-9
|
CCOMPILER: gcc-13
|
||||||
CUCUMBER_TIMEOUT: 20000
|
CUCUMBER_TIMEOUT: 20000
|
||||||
CXXCOMPILER: g++-9
|
CXXCOMPILER: g++-13
|
||||||
ENABLE_COVERAGE: ON
|
ENABLE_COVERAGE: ON
|
||||||
|
|
||||||
- name: gcc-9-debug-asan-ubsan
|
- name: clang-15-debug-asan-ubsan
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 20
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Debug
|
||||||
CCOMPILER: gcc-9
|
CCOMPILER: clang-15
|
||||||
CUCUMBER_TIMEOUT: 20000
|
CUCUMBER_TIMEOUT: 20000
|
||||||
CXXCOMPILER: g++-9
|
CXXCOMPILER: clang++-15
|
||||||
ENABLE_SANITIZER: ON
|
ENABLE_SANITIZER: ON
|
||||||
TARGET_ARCH: x86_64-asan-ubsan
|
TARGET_ARCH: x86_64-asan-ubsan
|
||||||
OSRM_CONNECTION_RETRIES: 10
|
OSRM_CONNECTION_RETRIES: 10
|
||||||
OSRM_CONNECTION_EXP_BACKOFF_COEF: 1.5
|
OSRM_CONNECTION_EXP_BACKOFF_COEF: 1.5
|
||||||
|
|
||||||
- name: clang-6.0-debug
|
- name: clang-15-release
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 18
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: clang-6.0
|
CCOMPILER: clang-15
|
||||||
CXXCOMPILER: clang++-6.0
|
CXXCOMPILER: clang++-15
|
||||||
CUCUMBER_TIMEOUT: 60000
|
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
|
||||||
|
BUILD_TOOLS: ON
|
||||||
|
BUILD_TYPE: Debug
|
||||||
|
CCOMPILER: clang-15
|
||||||
|
CXXCOMPILER: clang++-15
|
||||||
|
CUCUMBER_TIMEOUT: 60000
|
||||||
|
|
||||||
|
- name: clang-15-debug-clang-tidy
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 18
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
@@ -191,98 +204,84 @@ jobs:
|
|||||||
CUCUMBER_TIMEOUT: 60000
|
CUCUMBER_TIMEOUT: 60000
|
||||||
ENABLE_CLANG_TIDY: ON
|
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
|
- name: conan-linux-debug-asan-ubsan
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 18
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: clang-11
|
CCOMPILER: clang-15
|
||||||
CXXCOMPILER: clang++-11
|
CXXCOMPILER: clang++-15
|
||||||
ENABLE_CONAN: ON
|
ENABLE_CONAN: ON
|
||||||
ENABLE_SANITIZER: ON
|
ENABLE_SANITIZER: ON
|
||||||
|
|
||||||
- name: conan-linux-release
|
- name: conan-linux-release
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 18
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: clang-6.0
|
CCOMPILER: clang-15
|
||||||
CXXCOMPILER: clang++-6.0
|
CXXCOMPILER: clang++-15
|
||||||
ENABLE_CONAN: ON
|
ENABLE_CONAN: ON
|
||||||
|
|
||||||
|
- name: gcc-13-release
|
||||||
|
continue-on-error: false
|
||||||
|
node: 20
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
BUILD_TOOLS: ON
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
CCOMPILER: gcc-13
|
||||||
|
CXXCOMPILER: g++-13
|
||||||
|
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
|
||||||
|
|
||||||
- name: gcc-12-release
|
- name: gcc-12-release
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 20
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: gcc-12
|
CCOMPILER: gcc-12
|
||||||
CXXCOMPILER: g++-12
|
CXXCOMPILER: g++-12
|
||||||
ENABLE_BENCHMARKS: ON
|
|
||||||
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
|
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
|
||||||
|
|
||||||
- name: gcc-11-release
|
- name: gcc-11-release
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 18
|
node: 20
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TOOLS: ON
|
BUILD_TOOLS: ON
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: gcc-11
|
CCOMPILER: gcc-11
|
||||||
CXXCOMPILER: g++-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
|
- name: conan-linux-release-node
|
||||||
build_node_package: true
|
build_node_package: true
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 20
|
node: 20
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: clang-6.0
|
CCOMPILER: clang-13
|
||||||
CXXCOMPILER: clang++-6.0
|
CXXCOMPILER: clang++-13
|
||||||
ENABLE_CONAN: ON
|
ENABLE_CONAN: ON
|
||||||
NODE_PACKAGE_TESTS_ONLY: ON
|
NODE_PACKAGE_TESTS_ONLY: ON
|
||||||
|
|
||||||
@@ -290,10 +289,10 @@ jobs:
|
|||||||
build_node_package: true
|
build_node_package: true
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
node: 20
|
node: 20
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
BUILD_TYPE: Debug
|
BUILD_TYPE: Debug
|
||||||
CCOMPILER: clang-6.0
|
CCOMPILER: clang-13
|
||||||
CXXCOMPILER: clang++-6.0
|
CXXCOMPILER: clang++-13
|
||||||
ENABLE_CONAN: ON
|
ENABLE_CONAN: ON
|
||||||
NODE_PACKAGE_TESTS_ONLY: ON
|
NODE_PACKAGE_TESTS_ONLY: ON
|
||||||
|
|
||||||
@@ -301,7 +300,7 @@ jobs:
|
|||||||
build_node_package: true
|
build_node_package: true
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
node: 20
|
node: 20
|
||||||
runs-on: macos-11
|
runs-on: macos-13 # x86_64
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: clang
|
CCOMPILER: clang
|
||||||
CXXCOMPILER: clang++
|
CXXCOMPILER: clang++
|
||||||
@@ -313,14 +312,13 @@ jobs:
|
|||||||
build_node_package: true
|
build_node_package: true
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
node: 20
|
node: 20
|
||||||
runs-on: macos-11
|
runs-on: macos-14 # arm64
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCOMPILER: clang
|
CCOMPILER: clang
|
||||||
CXXCOMPILER: clang++
|
CXXCOMPILER: clang++
|
||||||
CUCUMBER_TIMEOUT: 60000
|
CUCUMBER_TIMEOUT: 60000
|
||||||
ENABLE_ASSERTIONS: ON
|
ENABLE_ASSERTIONS: ON
|
||||||
ENABLE_CONAN: ON
|
ENABLE_CONAN: ON
|
||||||
ENABLE_APPLE_SILICON: ON
|
|
||||||
|
|
||||||
name: ${{ matrix.name}}
|
name: ${{ matrix.name}}
|
||||||
continue-on-error: ${{ matrix.continue-on-error }}
|
continue-on-error: ${{ matrix.continue-on-error }}
|
||||||
@@ -340,13 +338,13 @@ jobs:
|
|||||||
ENABLE_CONAN: ${{ matrix.ENABLE_CONAN }}
|
ENABLE_CONAN: ${{ matrix.ENABLE_CONAN }}
|
||||||
ENABLE_SANITIZER: ${{ matrix.ENABLE_SANITIZER }}
|
ENABLE_SANITIZER: ${{ matrix.ENABLE_SANITIZER }}
|
||||||
NODE_PACKAGE_TESTS_ONLY: ${{ matrix.NODE_PACKAGE_TESTS_ONLY }}
|
NODE_PACKAGE_TESTS_ONLY: ${{ matrix.NODE_PACKAGE_TESTS_ONLY }}
|
||||||
ENABLE_APPLE_SILICON: ${{ matrix.ENABLE_APPLE_SILICON }}
|
|
||||||
TARGET_ARCH: ${{ matrix.TARGET_ARCH }}
|
TARGET_ARCH: ${{ matrix.TARGET_ARCH }}
|
||||||
OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }}
|
OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }}
|
||||||
OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }}
|
OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
- name: Build machine architecture
|
||||||
|
run: uname -m
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
@@ -369,9 +367,9 @@ jobs:
|
|||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.conan
|
path: ~/.conan
|
||||||
key: v7-conan-${{ matrix.name }}-${{ github.sha }}
|
key: v9-conan-${{ matrix.name }}-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
v7-conan-${{ matrix.name }}-
|
v9-conan-${{ matrix.name }}-
|
||||||
- name: Enable test cache
|
- name: Enable test cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
@@ -390,6 +388,7 @@ jobs:
|
|||||||
# We can only set this after checkout once we know the workspace directory
|
# 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 "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 "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
|
fi
|
||||||
|
|
||||||
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
||||||
@@ -400,7 +399,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dev dependencies
|
- name: Install dev dependencies
|
||||||
run: |
|
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
|
# 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
|
# and that's why CI cannot find conan executable installed above
|
||||||
@@ -415,19 +414,8 @@ jobs:
|
|||||||
brew install ccache
|
brew install ccache
|
||||||
fi
|
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
|
# Linux dev packages
|
||||||
if [ "${TARGET_ARCH}" != "i686" ] && [ "${ENABLE_CONAN}" != "ON" ]; then
|
if [ "${ENABLE_CONAN}" != "ON" ]; then
|
||||||
sudo apt-get update -y
|
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 libboost-all-dev
|
||||||
if [[ "${CCOMPILER}" != clang-* ]]; then
|
if [[ "${CCOMPILER}" != clang-* ]]; then
|
||||||
@@ -436,9 +424,6 @@ jobs:
|
|||||||
if [[ "${ENABLE_COVERAGE}" == "ON" ]]; then
|
if [[ "${ENABLE_COVERAGE}" == "ON" ]]; then
|
||||||
sudo apt-get install -y lcov
|
sudo apt-get install -y lcov
|
||||||
fi
|
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
|
fi
|
||||||
|
|
||||||
# TBB
|
# TBB
|
||||||
@@ -474,16 +459,6 @@ jobs:
|
|||||||
echo "Using ${JOBS} jobs"
|
echo "Using ${JOBS} jobs"
|
||||||
pushd ${OSRM_BUILD_DIR}
|
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
|
|
||||||
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
-DENABLE_CONAN=${ENABLE_CONAN:-OFF} \
|
-DENABLE_CONAN=${ENABLE_CONAN:-OFF} \
|
||||||
@@ -495,12 +470,10 @@ jobs:
|
|||||||
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
||||||
-DBUILD_TOOLS=${BUILD_TOOLS:-OFF} \
|
-DBUILD_TOOLS=${BUILD_TOOLS:-OFF} \
|
||||||
-DENABLE_CCACHE=ON \
|
-DENABLE_CCACHE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||||
"${APPLE_SILICON_FLAGS[@]}"
|
|
||||||
|
|
||||||
make --jobs=${JOBS}
|
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 tests --jobs=${JOBS}
|
||||||
make benchmarks --jobs=${JOBS}
|
make benchmarks --jobs=${JOBS}
|
||||||
ccache -s
|
ccache -s
|
||||||
@@ -512,14 +485,14 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
- name: Build example
|
- name: Build example
|
||||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
|
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }}
|
||||||
run: |
|
run: |
|
||||||
mkdir example/build && pushd example/build
|
mkdir example/build && pushd example/build
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||||
make --jobs=${JOBS}
|
make --jobs=${JOBS}
|
||||||
popd
|
popd
|
||||||
- name: Run all tests
|
- name: Run all tests
|
||||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
|
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }}
|
||||||
run: |
|
run: |
|
||||||
make -C test/data benchmark
|
make -C test/data benchmark
|
||||||
|
|
||||||
@@ -530,50 +503,39 @@ jobs:
|
|||||||
# All tests assume to be run from the build directory
|
# All tests assume to be run from the build directory
|
||||||
pushd ${OSRM_BUILD_DIR}
|
pushd ${OSRM_BUILD_DIR}
|
||||||
for i in ./unit_tests/*-tests ; do echo Running $i ; $i ; done
|
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
|
npm run nodejs-tests
|
||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
npm test
|
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
|
- name: Use Node 18
|
||||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
|
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
- name: Run Node package tests on Node 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: |
|
run: |
|
||||||
node --version
|
node --version
|
||||||
npm run nodejs-tests
|
npm run nodejs-tests
|
||||||
- name: Use Node 20
|
- name: Use Node 20
|
||||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
|
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
- name: Run Node package tests on Node 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: |
|
run: |
|
||||||
node --version
|
node --version
|
||||||
npm run nodejs-tests
|
npm run nodejs-tests
|
||||||
- name: Use Node latest
|
- name: Use Node latest
|
||||||
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
|
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: latest
|
node-version: latest
|
||||||
- name: Run Node package tests on Node-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: |
|
run: |
|
||||||
node --version
|
node --version
|
||||||
npm run nodejs-tests
|
npm run nodejs-tests
|
||||||
@@ -585,12 +547,12 @@ jobs:
|
|||||||
name: logs
|
name: logs
|
||||||
path: test/logs/
|
path: test/logs/
|
||||||
|
|
||||||
- name: Generate code coverage
|
# - name: Generate code coverage
|
||||||
if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
|
# if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
|
||||||
run: |
|
# run: |
|
||||||
lcov --directory . --capture --output-file coverage.info # capture coverage info
|
# lcov --directory . --capture --output-file coverage.info # capture coverage info
|
||||||
lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter out system
|
# lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter out system
|
||||||
lcov --list coverage.info #debug info
|
# lcov --list coverage.info #debug info
|
||||||
|
|
||||||
# # Uploading report to CodeCov
|
# # Uploading report to CodeCov
|
||||||
# - name: Upload code coverage
|
# - name: Upload code coverage
|
||||||
@@ -601,15 +563,6 @@ jobs:
|
|||||||
# name: codecov-osrm-backend
|
# name: codecov-osrm-backend
|
||||||
# fail_ci_if_error: true
|
# fail_ci_if_error: true
|
||||||
# verbose: 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
|
- name: Build Node package
|
||||||
if: ${{ matrix.build_node_package }}
|
if: ${{ matrix.build_node_package }}
|
||||||
run: ./scripts/ci/node_package.sh
|
run: ./scripts/ci/node_package.sh
|
||||||
@@ -627,8 +580,72 @@ jobs:
|
|||||||
replacesArtifacts: true
|
replacesArtifacts: true
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
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 }}
|
||||||
|
steps:
|
||||||
|
- name: Enable compiler cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.ccache
|
||||||
|
key: v1-ccache-benchmarks-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
v1-ccache-benchmarks-
|
||||||
|
- name: Enable Conan cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.conan
|
||||||
|
key: v1-conan-benchmarks-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
v1-conan-benchmarks-
|
||||||
|
- name: Checkout PR Branch
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.head_ref }}
|
||||||
|
path: pr
|
||||||
|
- run: python3 -m pip install "conan<2.0.0" "requests==2.31.0"
|
||||||
|
- 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@v3
|
||||||
|
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
|
||||||
|
|
||||||
ci-complete:
|
ci-complete:
|
||||||
runs-on: ubuntu-22.04
|
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:
|
steps:
|
||||||
- run: echo "CI complete"
|
- run: echo "CI complete"
|
||||||
|
|||||||
@@ -12,10 +12,15 @@
|
|||||||
- CHANGED: Update actions/cache to v3. [#6420](https://github.com/Project-OSRM/osrm-backend/pull/6420)
|
- 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)
|
- 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)
|
- 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)
|
- 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:
|
- NodeJS:
|
||||||
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
|
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
|
||||||
- Misc:
|
- Misc:
|
||||||
|
- CHANGED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551), see also [#6592](https://github.com/Project-OSRM/osrm-backend/issues/6592)
|
||||||
|
- 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)
|
- 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)
|
- 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)
|
- CHANGED: Allow -1.0 as unlimited for default_radius value. [#6599](https://github.com/Project-OSRM/osrm-backend/pull/6599)
|
||||||
@@ -41,6 +46,11 @@
|
|||||||
- FIXED: Fix adding traffic signal penalties during compression [#6419](https://github.com/Project-OSRM/osrm-backend/pull/6419)
|
- 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: 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: 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. [#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:
|
- Debug tiles:
|
||||||
- FIXED: Ensure speed layer features have unique ids. [#6726](https://github.com/Project-OSRM/osrm-backend/pull/6726)
|
- FIXED: Ensure speed layer features have unique ids. [#6726](https://github.com/Project-OSRM/osrm-backend/pull/6726)
|
||||||
|
|
||||||
|
|||||||
+5
-8
@@ -42,16 +42,13 @@ if (ENABLE_CLANG_TIDY)
|
|||||||
message(FATAL_ERROR "ENABLE_CLANG_TIDY is ON but clang-tidy is not found!")
|
message(FATAL_ERROR "ENABLE_CLANG_TIDY is ON but clang-tidy is not found!")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Found clang-tidy at ${CLANG_TIDY_COMMAND}")
|
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
# be compatible with version handling before cmake 3.x
|
# be compatible with version handling before cmake 3.x
|
||||||
if (POLICY CMP0048)
|
|
||||||
cmake_policy(SET CMP0048 OLD)
|
|
||||||
endif()
|
|
||||||
if (POLICY CMP0057)
|
if (POLICY CMP0057)
|
||||||
cmake_policy(SET CMP0057 NEW)
|
cmake_policy(SET CMP0057 NEW)
|
||||||
endif()
|
endif()
|
||||||
@@ -118,7 +115,7 @@ include(GNUInstallDirs)
|
|||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
message(STATUS "Building on a 64 bit system")
|
message(STATUS "Building on a 64 bit system")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Building on a 32 bit system")
|
message(FATAL_ERROR "Building on a 32 bit system is not supported")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
||||||
@@ -226,7 +223,7 @@ endif()
|
|||||||
set(MAYBE_COVERAGE_LIBRARIES "")
|
set(MAYBE_COVERAGE_LIBRARIES "")
|
||||||
if (ENABLE_COVERAGE)
|
if (ENABLE_COVERAGE)
|
||||||
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
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()
|
endif()
|
||||||
message(STATUS "Enabling coverage")
|
message(STATUS "Enabling coverage")
|
||||||
set(MAYBE_COVERAGE_LIBRARIES "-lgcov")
|
set(MAYBE_COVERAGE_LIBRARIES "-lgcov")
|
||||||
@@ -312,7 +309,7 @@ add_subdirectory(${FLATBUFFERS_SRC_DIR}
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
|
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
|
||||||
EXCLUDE_FROM_ALL)
|
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)
|
add_compile_definitions(FMT_HEADER_ONLY)
|
||||||
include_directories(SYSTEM ${FMT_INCLUDE_DIR})
|
include_directories(SYSTEM ${FMT_INCLUDE_DIR})
|
||||||
|
|
||||||
@@ -333,7 +330,7 @@ if(ENABLE_CONAN)
|
|||||||
|
|
||||||
conan_check(REQUIRED)
|
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_BZIP2_VERSION "1.0.8@#d1b2d5816f25865acf978501dff1f897")
|
||||||
set(CONAN_EXPAT_VERSION "2.2.10@#916908d4a570ad839edd25322c3268cd")
|
set(CONAN_EXPAT_VERSION "2.2.10@#916908d4a570ad839edd25322c3268cd")
|
||||||
set(CONAN_LUA_VERSION "5.4.4@#3ec62efc37cd0a5d80b9e5cb35277360")
|
set(CONAN_LUA_VERSION "5.4.4@#3ec62efc37cd0a5d80b9e5cb35277360")
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ You can add a :+1: emoji reaction to the issue if you want to express interest i
|
|||||||
|
|
||||||
# Developer
|
# 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.
|
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`
|
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.
|
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:
|
Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
|
||||||
- [osrm-frontend](https://github.com/Project-OSRM/osrm-frontend) - User-facing frontend with map. The demo server runs this on top of the backend
|
- [osrm-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%
|
|
||||||
@@ -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,9 +61,11 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
|
|||||||
// Add all non-core edges to container
|
// Add all non-core edges to container
|
||||||
{
|
{
|
||||||
auto non_core_edges = toEdges<QueryEdge>(contractor_graph);
|
auto non_core_edges = toEdges<QueryEdge>(contractor_graph);
|
||||||
auto new_end =
|
auto new_end = std::remove_if(non_core_edges.begin(),
|
||||||
std::remove_if(non_core_edges.begin(), non_core_edges.end(), [&](const auto &edge) {
|
non_core_edges.end(),
|
||||||
return is_shared_core[edge.source] && is_shared_core[edge.target];
|
[&](const auto &edge) {
|
||||||
|
return is_shared_core[edge.source] &&
|
||||||
|
is_shared_core[edge.target];
|
||||||
});
|
});
|
||||||
non_core_edges.resize(new_end - non_core_edges.begin());
|
non_core_edges.resize(new_end - non_core_edges.begin());
|
||||||
edge_container.Insert(std::move(non_core_edges));
|
edge_container.Insert(std::move(non_core_edges));
|
||||||
@@ -75,8 +77,8 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract core graph for further contraction
|
// Extract core graph for further contraction
|
||||||
shared_core_graph = contractor_graph.Filter(
|
shared_core_graph = contractor_graph.Filter([&is_shared_core](const NodeID node)
|
||||||
[&is_shared_core](const NodeID node) { return is_shared_core[node]; });
|
{ return is_shared_core[node]; });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &filter : filters)
|
for (const auto &filter : filters)
|
||||||
|
|||||||
@@ -89,7 +89,10 @@ struct ContractedEdgeContainer
|
|||||||
|
|
||||||
// Remove all edges that are contained in the old set of edges and set the appropriate flag.
|
// Remove all edges that are contained in the old set of edges and set the appropriate flag.
|
||||||
auto new_end =
|
auto new_end =
|
||||||
std::remove_if(new_edges.begin(), new_edges.end(), [&](const QueryEdge &edge) {
|
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
|
// 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 so it is not contained yet in the set of old edges
|
||||||
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
|
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
|
||||||
@@ -132,10 +135,10 @@ struct ContractedEdgeContainer
|
|||||||
// enforce sorting for next merge step
|
// enforce sorting for next merge step
|
||||||
std::vector<unsigned> ordering(edges_size);
|
std::vector<unsigned> ordering(edges_size);
|
||||||
std::iota(ordering.begin(), ordering.end(), 0);
|
std::iota(ordering.begin(), ordering.end(), 0);
|
||||||
tbb::parallel_sort(
|
tbb::parallel_sort(ordering.begin(),
|
||||||
ordering.begin(), ordering.end(), [&](const auto lhs_idx, const auto rhs_idx) {
|
ordering.end(),
|
||||||
return mergeCompare(edges[lhs_idx], edges[rhs_idx]);
|
[&](const auto lhs_idx, const auto rhs_idx)
|
||||||
});
|
{ return mergeCompare(edges[lhs_idx], edges[rhs_idx]); });
|
||||||
auto permutation = util::orderingToPermutation(ordering);
|
auto permutation = util::orderingToPermutation(ordering);
|
||||||
|
|
||||||
util::inplacePermutation(edges.begin(), edges.end(), permutation);
|
util::inplacePermutation(edges.begin(), edges.end(), permutation);
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ class CellCustomizer
|
|||||||
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
|
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
|
||||||
{
|
{
|
||||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(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();
|
auto &heap = heaps.local();
|
||||||
for (auto id = range.begin(), end = range.end(); id != end; ++id)
|
for (auto id = range.begin(), end = range.end(); id != end; ++id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ class BaseAPI
|
|||||||
util::json::Array waypoints;
|
util::json::Array waypoints;
|
||||||
waypoints.values.resize(parameters.coordinates.size());
|
waypoints.values.resize(parameters.coordinates.size());
|
||||||
|
|
||||||
boost::range::transform(
|
boost::range::transform(waypoint_candidates,
|
||||||
waypoint_candidates,
|
|
||||||
waypoints.values.begin(),
|
waypoints.values.begin(),
|
||||||
[this](const PhantomNodeCandidates &candidates) { return MakeWaypoint(candidates); });
|
[this](const PhantomNodeCandidates &candidates)
|
||||||
|
{ return MakeWaypoint(candidates); });
|
||||||
return waypoints;
|
return waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,9 +104,8 @@ class BaseAPI
|
|||||||
std::transform(waypoint_candidates.begin(),
|
std::transform(waypoint_candidates.begin(),
|
||||||
waypoint_candidates.end(),
|
waypoint_candidates.end(),
|
||||||
waypoints.begin(),
|
waypoints.begin(),
|
||||||
[this, builder](const PhantomNodeCandidates &candidates) {
|
[this, builder](const PhantomNodeCandidates &candidates)
|
||||||
return MakeWaypoint(builder, candidates)->Finish();
|
{ return MakeWaypoint(builder, candidates)->Finish(); });
|
||||||
});
|
|
||||||
return builder->CreateVector(waypoints);
|
return builder->CreateVector(waypoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ struct BaseParameters
|
|||||||
(approaches.empty() || approaches.size() == coordinates.size()) &&
|
(approaches.empty() || approaches.size() == coordinates.size()) &&
|
||||||
std::all_of(bearings.begin(),
|
std::all_of(bearings.begin(),
|
||||||
bearings.end(),
|
bearings.end(),
|
||||||
[](const boost::optional<Bearing> &bearing_and_range) {
|
[](const boost::optional<Bearing> &bearing_and_range)
|
||||||
|
{
|
||||||
if (bearing_and_range)
|
if (bearing_and_range)
|
||||||
{
|
{
|
||||||
return bearing_and_range->IsValid();
|
return bearing_and_range->IsValid();
|
||||||
|
|||||||
@@ -52,9 +52,10 @@ class MatchAPI final : public RouteAPI
|
|||||||
data_version_string = fb_result.CreateString(data_timestamp);
|
data_version_string = fb_result.CreateString(data_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = MakeFBResponse(sub_routes, fb_result, [this, &fb_result, &sub_matchings]() {
|
auto response = MakeFBResponse(sub_routes,
|
||||||
return MakeTracepoints(fb_result, sub_matchings);
|
fb_result,
|
||||||
});
|
[this, &fb_result, &sub_matchings]()
|
||||||
|
{ return MakeTracepoints(fb_result, sub_matchings); });
|
||||||
|
|
||||||
if (!data_timestamp.empty())
|
if (!data_timestamp.empty())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ class NearestAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
std::vector<flatbuffers::Offset<fbresult::Waypoint>> waypoints;
|
std::vector<flatbuffers::Offset<fbresult::Waypoint>> waypoints;
|
||||||
waypoints.resize(phantom_nodes.front().size());
|
waypoints.resize(phantom_nodes.front().size());
|
||||||
std::transform(
|
std::transform(phantom_nodes.front().begin(),
|
||||||
phantom_nodes.front().begin(),
|
|
||||||
phantom_nodes.front().end(),
|
phantom_nodes.front().end(),
|
||||||
waypoints.begin(),
|
waypoints.begin(),
|
||||||
[this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance) {
|
[this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance)
|
||||||
|
{
|
||||||
auto &phantom_node = phantom_with_distance.phantom_node;
|
auto &phantom_node = phantom_with_distance.phantom_node;
|
||||||
|
|
||||||
auto node_values = MakeNodes(phantom_node);
|
auto node_values = MakeNodes(phantom_node);
|
||||||
@@ -94,7 +94,8 @@ class NearestAPI final : public BaseAPI
|
|||||||
std::transform(phantom_nodes.front().begin(),
|
std::transform(phantom_nodes.front().begin(),
|
||||||
phantom_nodes.front().end(),
|
phantom_nodes.front().end(),
|
||||||
waypoints.values.begin(),
|
waypoints.values.begin(),
|
||||||
[this](const PhantomNodeWithDistance &phantom_with_distance) {
|
[this](const PhantomNodeWithDistance &phantom_with_distance)
|
||||||
|
{
|
||||||
auto &phantom_node = phantom_with_distance.phantom_node;
|
auto &phantom_node = phantom_with_distance.phantom_node;
|
||||||
auto waypoint = MakeWaypoint({phantom_node});
|
auto waypoint = MakeWaypoint({phantom_node});
|
||||||
|
|
||||||
|
|||||||
@@ -77,9 +77,10 @@ class RouteAPI : public BaseAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto response =
|
auto response =
|
||||||
MakeFBResponse(raw_routes, fb_result, [this, &waypoint_candidates, &fb_result]() {
|
MakeFBResponse(raw_routes,
|
||||||
return BaseAPI::MakeWaypoints(&fb_result, waypoint_candidates);
|
fb_result,
|
||||||
});
|
[this, &waypoint_candidates, &fb_result]()
|
||||||
|
{ return BaseAPI::MakeWaypoints(&fb_result, waypoint_candidates); });
|
||||||
|
|
||||||
if (!data_timestamp.empty())
|
if (!data_timestamp.empty())
|
||||||
{
|
{
|
||||||
@@ -171,8 +172,13 @@ class RouteAPI : public BaseAPI
|
|||||||
}
|
}
|
||||||
std::vector<fbresult::Position> coordinates;
|
std::vector<fbresult::Position> coordinates;
|
||||||
coordinates.resize(std::distance(begin, end));
|
coordinates.resize(std::distance(begin, end));
|
||||||
std::transform(begin, end, coordinates.begin(), [](const Coordinate &c) {
|
std::transform(begin,
|
||||||
return fbresult::Position{static_cast<float>(util::toFloating(c.lon).__value),
|
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)};
|
static_cast<float>(util::toFloating(c.lat).__value)};
|
||||||
});
|
});
|
||||||
return builder.CreateVectorOfStructs(coordinates);
|
return builder.CreateVectorOfStructs(coordinates);
|
||||||
@@ -354,9 +360,8 @@ class RouteAPI : public BaseAPI
|
|||||||
std::transform(leg.steps.begin(),
|
std::transform(leg.steps.begin(),
|
||||||
leg.steps.end(),
|
leg.steps.end(),
|
||||||
legSteps.begin(),
|
legSteps.begin(),
|
||||||
[this, &fb_result, &leg_geometry](auto &step) {
|
[this, &fb_result, &leg_geometry](auto &step)
|
||||||
return this->MakeFBStep(fb_result, leg_geometry, step);
|
{ return this->MakeFBStep(fb_result, leg_geometry, step); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
auto steps_vector = fb_result.CreateVector(legSteps);
|
auto steps_vector = fb_result.CreateVector(legSteps);
|
||||||
|
|
||||||
@@ -441,7 +446,8 @@ class RouteAPI : public BaseAPI
|
|||||||
speed =
|
speed =
|
||||||
GetAnnotations<float>(fb_result,
|
GetAnnotations<float>(fb_result,
|
||||||
leg_geometry,
|
leg_geometry,
|
||||||
[&prev_speed](const guidance::LegGeometry::Annotation &anno) {
|
[&prev_speed](const guidance::LegGeometry::Annotation &anno)
|
||||||
|
{
|
||||||
if (anno.duration < std::numeric_limits<float>::min())
|
if (anno.duration < std::numeric_limits<float>::min())
|
||||||
{
|
{
|
||||||
return prev_speed;
|
return prev_speed;
|
||||||
@@ -459,37 +465,37 @@ class RouteAPI : public BaseAPI
|
|||||||
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> duration;
|
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> duration;
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
|
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
|
||||||
{
|
{
|
||||||
duration = GetAnnotations<uint32_t>(
|
duration = GetAnnotations<uint32_t>(fb_result,
|
||||||
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
leg_geometry,
|
||||||
return anno.duration;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.duration; });
|
||||||
}
|
}
|
||||||
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> distance;
|
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> distance;
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
|
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
|
||||||
{
|
{
|
||||||
distance = GetAnnotations<uint32_t>(
|
distance = GetAnnotations<uint32_t>(fb_result,
|
||||||
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
leg_geometry,
|
||||||
return anno.distance;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.distance; });
|
||||||
}
|
}
|
||||||
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> weight;
|
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> weight;
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
|
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
|
||||||
{
|
{
|
||||||
weight = GetAnnotations<uint32_t>(
|
weight = GetAnnotations<uint32_t>(fb_result,
|
||||||
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
leg_geometry,
|
||||||
return anno.weight;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.weight; });
|
||||||
}
|
}
|
||||||
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> datasources;
|
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> datasources;
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
|
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
|
||||||
{
|
{
|
||||||
datasources = GetAnnotations<uint32_t>(
|
datasources = GetAnnotations<uint32_t>(fb_result,
|
||||||
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
leg_geometry,
|
||||||
return anno.datasource;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.datasource; });
|
||||||
}
|
}
|
||||||
std::vector<uint32_t> nodes;
|
std::vector<uint32_t> nodes;
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
|
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
|
||||||
@@ -653,7 +659,8 @@ class RouteAPI : public BaseAPI
|
|||||||
step.intersections.begin(),
|
step.intersections.begin(),
|
||||||
step.intersections.end(),
|
step.intersections.end(),
|
||||||
intersections.begin(),
|
intersections.begin(),
|
||||||
[&fb_result, this](const guidance::IntermediateIntersection &intersection) {
|
[&fb_result, this](const guidance::IntermediateIntersection &intersection)
|
||||||
|
{
|
||||||
std::vector<flatbuffers::Offset<fbresult::Lane>> lanes;
|
std::vector<flatbuffers::Offset<fbresult::Lane>> lanes;
|
||||||
if (json::detail::hasValidLanes(intersection))
|
if (json::detail::hasValidLanes(intersection))
|
||||||
{
|
{
|
||||||
@@ -681,11 +688,11 @@ class RouteAPI : public BaseAPI
|
|||||||
auto bearings_vector = fb_result.CreateVector(intersection.bearings);
|
auto bearings_vector = fb_result.CreateVector(intersection.bearings);
|
||||||
std::vector<flatbuffers::Offset<flatbuffers::String>> classes;
|
std::vector<flatbuffers::Offset<flatbuffers::String>> classes;
|
||||||
classes.resize(intersection.classes.size());
|
classes.resize(intersection.classes.size());
|
||||||
std::transform(
|
std::transform(intersection.classes.begin(),
|
||||||
intersection.classes.begin(),
|
|
||||||
intersection.classes.end(),
|
intersection.classes.end(),
|
||||||
classes.begin(),
|
classes.begin(),
|
||||||
[&fb_result](const std::string &cls) { return fb_result.CreateString(cls); });
|
[&fb_result](const std::string &cls)
|
||||||
|
{ return fb_result.CreateString(cls); });
|
||||||
auto classes_vector = fb_result.CreateVector(classes);
|
auto classes_vector = fb_result.CreateVector(classes);
|
||||||
auto entry_vector = fb_result.CreateVector(intersection.entry);
|
auto entry_vector = fb_result.CreateVector(intersection.entry);
|
||||||
|
|
||||||
@@ -720,9 +727,10 @@ class RouteAPI : public BaseAPI
|
|||||||
|
|
||||||
std::vector<util::json::Value> step_geometries;
|
std::vector<util::json::Value> step_geometries;
|
||||||
const auto total_step_count =
|
const auto total_step_count =
|
||||||
std::accumulate(legs.begin(), legs.end(), 0, [](const auto &v, const auto &leg) {
|
std::accumulate(legs.begin(),
|
||||||
return v + leg.steps.size();
|
legs.end(),
|
||||||
});
|
0,
|
||||||
|
[](const auto &v, const auto &leg) { return v + leg.steps.size(); });
|
||||||
step_geometries.reserve(total_step_count);
|
step_geometries.reserve(total_step_count);
|
||||||
|
|
||||||
for (const auto idx : util::irange<std::size_t>(0UL, legs.size()))
|
for (const auto idx : util::irange<std::size_t>(0UL, legs.size()))
|
||||||
@@ -733,7 +741,8 @@ class RouteAPI : public BaseAPI
|
|||||||
legs[idx].steps.begin(),
|
legs[idx].steps.begin(),
|
||||||
legs[idx].steps.end(),
|
legs[idx].steps.end(),
|
||||||
std::back_inserter(step_geometries),
|
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)
|
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
|
||||||
{
|
{
|
||||||
return static_cast<util::json::Value>(json::makePolyline<100000>(
|
return static_cast<util::json::Value>(json::makePolyline<100000>(
|
||||||
@@ -778,7 +787,9 @@ class RouteAPI : public BaseAPI
|
|||||||
{
|
{
|
||||||
double prev_speed = 0;
|
double prev_speed = 0;
|
||||||
annotation.values["speed"] = GetAnnotations(
|
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())
|
if (anno.duration < std::numeric_limits<double>::min())
|
||||||
{
|
{
|
||||||
return prev_speed;
|
return prev_speed;
|
||||||
@@ -794,17 +805,17 @@ class RouteAPI : public BaseAPI
|
|||||||
|
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
|
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
|
||||||
{
|
{
|
||||||
annotation.values["duration"] = GetAnnotations(
|
annotation.values["duration"] =
|
||||||
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
GetAnnotations(leg_geometry,
|
||||||
return anno.duration;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.duration; });
|
||||||
}
|
}
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
|
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
|
||||||
{
|
{
|
||||||
annotation.values["distance"] = GetAnnotations(
|
annotation.values["distance"] =
|
||||||
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
GetAnnotations(leg_geometry,
|
||||||
return anno.distance;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.distance; });
|
||||||
}
|
}
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
|
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
|
||||||
{
|
{
|
||||||
@@ -814,10 +825,10 @@ class RouteAPI : public BaseAPI
|
|||||||
}
|
}
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
|
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
|
||||||
{
|
{
|
||||||
annotation.values["datasources"] = GetAnnotations(
|
annotation.values["datasources"] =
|
||||||
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
GetAnnotations(leg_geometry,
|
||||||
return anno.datasource;
|
[](const guidance::LegGeometry::Annotation &anno)
|
||||||
});
|
{ return anno.datasource; });
|
||||||
}
|
}
|
||||||
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
|
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -180,9 +180,9 @@ struct RouteParameters : public BaseParameters
|
|||||||
const auto coordinates_ok = coordinates.size() >= 2;
|
const auto coordinates_ok = coordinates.size() >= 2;
|
||||||
const auto base_params_ok = BaseParameters::IsValid();
|
const auto base_params_ok = BaseParameters::IsValid();
|
||||||
const auto valid_waypoints =
|
const auto valid_waypoints =
|
||||||
std::all_of(waypoints.begin(), waypoints.end(), [this](const auto &w) {
|
std::all_of(waypoints.begin(),
|
||||||
return w < coordinates.size();
|
waypoints.end(),
|
||||||
});
|
[this](const auto &w) { return w < coordinates.size(); });
|
||||||
return coordinates_ok && base_params_ok && valid_waypoints;
|
return coordinates_ok && base_params_ok && valid_waypoints;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -245,9 +245,8 @@ class TableAPI final : public BaseAPI
|
|||||||
|
|
||||||
boost::range::transform(candidates,
|
boost::range::transform(candidates,
|
||||||
std::back_inserter(waypoints),
|
std::back_inserter(waypoints),
|
||||||
[this, &builder](const PhantomNodeCandidates &candidates) {
|
[this, &builder](const PhantomNodeCandidates &candidates)
|
||||||
return BaseAPI::MakeWaypoint(&builder, candidates)->Finish();
|
{ return BaseAPI::MakeWaypoint(&builder, candidates)->Finish(); });
|
||||||
});
|
|
||||||
return builder.CreateVector(waypoints);
|
return builder.CreateVector(waypoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +260,8 @@ class TableAPI final : public BaseAPI
|
|||||||
boost::range::transform(
|
boost::range::transform(
|
||||||
indices,
|
indices,
|
||||||
std::back_inserter(waypoints),
|
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());
|
BOOST_ASSERT(idx < candidates.size());
|
||||||
return BaseAPI::MakeWaypoint(&builder, candidates[idx])->Finish();
|
return BaseAPI::MakeWaypoint(&builder, candidates[idx])->Finish();
|
||||||
});
|
});
|
||||||
@@ -274,8 +274,11 @@ class TableAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
std::vector<float> distance_table;
|
std::vector<float> distance_table;
|
||||||
distance_table.resize(values.size());
|
distance_table.resize(values.size());
|
||||||
std::transform(
|
std::transform(values.begin(),
|
||||||
values.begin(), values.end(), distance_table.begin(), [](const EdgeDuration duration) {
|
values.end(),
|
||||||
|
distance_table.begin(),
|
||||||
|
[](const EdgeDuration duration)
|
||||||
|
{
|
||||||
if (duration == MAXIMAL_EDGE_DURATION)
|
if (duration == MAXIMAL_EDGE_DURATION)
|
||||||
{
|
{
|
||||||
return 0.;
|
return 0.;
|
||||||
@@ -291,8 +294,11 @@ class TableAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
std::vector<float> duration_table;
|
std::vector<float> duration_table;
|
||||||
duration_table.resize(values.size());
|
duration_table.resize(values.size());
|
||||||
std::transform(
|
std::transform(values.begin(),
|
||||||
values.begin(), values.end(), duration_table.begin(), [](const EdgeDistance distance) {
|
values.end(),
|
||||||
|
duration_table.begin(),
|
||||||
|
[](const EdgeDistance distance)
|
||||||
|
{
|
||||||
if (distance == INVALID_EDGE_DISTANCE)
|
if (distance == INVALID_EDGE_DISTANCE)
|
||||||
{
|
{
|
||||||
return 0.;
|
return 0.;
|
||||||
@@ -308,8 +314,10 @@ class TableAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
std::vector<uint32_t> fb_table;
|
std::vector<uint32_t> fb_table;
|
||||||
fb_table.reserve(fallback_speed_cells.size());
|
fb_table.reserve(fallback_speed_cells.size());
|
||||||
std::for_each(
|
std::for_each(fallback_speed_cells.begin(),
|
||||||
fallback_speed_cells.begin(), fallback_speed_cells.end(), [&](const auto &cell) {
|
fallback_speed_cells.end(),
|
||||||
|
[&](const auto &cell)
|
||||||
|
{
|
||||||
fb_table.push_back(cell.row);
|
fb_table.push_back(cell.row);
|
||||||
fb_table.push_back(cell.column);
|
fb_table.push_back(cell.column);
|
||||||
});
|
});
|
||||||
@@ -325,9 +333,8 @@ class TableAPI final : public BaseAPI
|
|||||||
|
|
||||||
boost::range::transform(candidates,
|
boost::range::transform(candidates,
|
||||||
std::back_inserter(json_waypoints.values),
|
std::back_inserter(json_waypoints.values),
|
||||||
[this](const PhantomNodeCandidates &candidates) {
|
[this](const PhantomNodeCandidates &candidates)
|
||||||
return BaseAPI::MakeWaypoint(candidates);
|
{ return BaseAPI::MakeWaypoint(candidates); });
|
||||||
});
|
|
||||||
return json_waypoints;
|
return json_waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +345,8 @@ class TableAPI final : public BaseAPI
|
|||||||
json_waypoints.values.reserve(indices.size());
|
json_waypoints.values.reserve(indices.size());
|
||||||
boost::range::transform(indices,
|
boost::range::transform(indices,
|
||||||
std::back_inserter(json_waypoints.values),
|
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());
|
BOOST_ASSERT(idx < candidates.size());
|
||||||
return BaseAPI::MakeWaypoint(candidates[idx]);
|
return BaseAPI::MakeWaypoint(candidates[idx]);
|
||||||
});
|
});
|
||||||
@@ -359,7 +367,8 @@ class TableAPI final : public BaseAPI
|
|||||||
std::transform(row_begin_iterator,
|
std::transform(row_begin_iterator,
|
||||||
row_end_iterator,
|
row_end_iterator,
|
||||||
json_row.values.begin(),
|
json_row.values.begin(),
|
||||||
[](const EdgeDuration duration) {
|
[](const EdgeDuration duration)
|
||||||
|
{
|
||||||
if (duration == MAXIMAL_EDGE_DURATION)
|
if (duration == MAXIMAL_EDGE_DURATION)
|
||||||
{
|
{
|
||||||
return util::json::Value(util::json::Null());
|
return util::json::Value(util::json::Null());
|
||||||
@@ -387,7 +396,8 @@ class TableAPI final : public BaseAPI
|
|||||||
std::transform(row_begin_iterator,
|
std::transform(row_begin_iterator,
|
||||||
row_end_iterator,
|
row_end_iterator,
|
||||||
json_row.values.begin(),
|
json_row.values.begin(),
|
||||||
[](const EdgeDistance distance) {
|
[](const EdgeDistance distance)
|
||||||
|
{
|
||||||
if (distance == INVALID_EDGE_DISTANCE)
|
if (distance == INVALID_EDGE_DISTANCE)
|
||||||
{
|
{
|
||||||
return util::json::Value(util::json::Null());
|
return util::json::Value(util::json::Null());
|
||||||
@@ -405,8 +415,10 @@ class TableAPI final : public BaseAPI
|
|||||||
MakeEstimatesTable(const std::vector<TableCellRef> &fallback_speed_cells) const
|
MakeEstimatesTable(const std::vector<TableCellRef> &fallback_speed_cells) const
|
||||||
{
|
{
|
||||||
util::json::Array json_table;
|
util::json::Array json_table;
|
||||||
std::for_each(
|
std::for_each(fallback_speed_cells.begin(),
|
||||||
fallback_speed_cells.begin(), fallback_speed_cells.end(), [&](const auto &cell) {
|
fallback_speed_cells.end(),
|
||||||
|
[&](const auto &cell)
|
||||||
|
{
|
||||||
util::json::Array row;
|
util::json::Array row;
|
||||||
row.values.push_back(util::json::Number(cell.row));
|
row.values.push_back(util::json::Number(cell.row));
|
||||||
row.values.push_back(util::json::Number(cell.column));
|
row.values.push_back(util::json::Number(cell.column));
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ class TripAPI final : public RouteAPI
|
|||||||
data_version_string = fb_result.CreateString(data_timestamp);
|
data_version_string = fb_result.CreateString(data_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response =
|
auto response = MakeFBResponse(sub_routes,
|
||||||
MakeFBResponse(sub_routes, fb_result, [this, &fb_result, &sub_trips, &candidates]() {
|
fb_result,
|
||||||
return MakeWaypoints(fb_result, sub_trips, candidates);
|
[this, &fb_result, &sub_trips, &candidates]()
|
||||||
});
|
{ return MakeWaypoints(fb_result, sub_trips, candidates); });
|
||||||
|
|
||||||
if (!data_timestamp.empty())
|
if (!data_timestamp.empty())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodes(
|
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>
|
std::vector<PhantomNodeWithDistance>
|
||||||
@@ -440,9 +440,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
{
|
{
|
||||||
auto indexes = extractor::getClassIndexes(class_data);
|
auto indexes = extractor::getClassIndexes(class_data);
|
||||||
std::vector<std::string> classes(indexes.size());
|
std::vector<std::string> classes(indexes.size());
|
||||||
std::transform(indexes.begin(), indexes.end(), classes.begin(), [this](const auto index) {
|
std::transform(indexes.begin(),
|
||||||
return m_profile_properties->GetClassName(index);
|
indexes.end(),
|
||||||
});
|
classes.begin(),
|
||||||
|
[this](const auto index)
|
||||||
|
{ return m_profile_properties->GetClassName(index); });
|
||||||
|
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
@@ -600,10 +602,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
auto found_range = std::equal_range(
|
auto found_range = std::equal_range(
|
||||||
m_maneuver_overrides.begin(), m_maneuver_overrides.end(), edge_based_node_id, Comp{});
|
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::for_each(found_range.first,
|
||||||
std::vector<NodeID> sequence(
|
found_range.second,
|
||||||
m_maneuver_override_node_sequences.begin() + override.node_sequence_offset_begin,
|
[&](const auto &override)
|
||||||
m_maneuver_override_node_sequences.begin() + override.node_sequence_offset_end);
|
{
|
||||||
|
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),
|
results.push_back(extractor::ManeuverOverride{std::move(sequence),
|
||||||
override.instruction_node,
|
override.instruction_node,
|
||||||
override.override_type,
|
override.override_type,
|
||||||
|
|||||||
@@ -47,12 +47,42 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
return rtree.SearchInBox(bbox);
|
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.
|
// Returns max_results nearest PhantomNodes that are valid within the provided parameters.
|
||||||
// Does not filter by small/big component!
|
// Does not filter by small/big component!
|
||||||
std::vector<PhantomNodeWithDistance>
|
std::vector<PhantomNodeWithDistance>
|
||||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||||
const Approach approach,
|
const Approach approach,
|
||||||
const boost::optional<size_t> max_results,
|
const size_t max_results,
|
||||||
const boost::optional<double> max_distance,
|
const boost::optional<double> max_distance,
|
||||||
const boost::optional<Bearing> bearing_with_range,
|
const boost::optional<Bearing> bearing_with_range,
|
||||||
const boost::optional<bool> use_all_edges) const
|
const boost::optional<bool> use_all_edges) const
|
||||||
@@ -60,7 +90,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, &bearing_with_range, &use_all_edges](
|
[this, approach, &input_coordinate, &bearing_with_range, &use_all_edges](
|
||||||
const CandidateSegment &segment) {
|
const CandidateSegment &segment)
|
||||||
|
{
|
||||||
auto valid = CheckSegmentExclude(segment) &&
|
auto valid = CheckSegmentExclude(segment) &&
|
||||||
CheckApproach(input_coordinate, segment, approach) &&
|
CheckApproach(input_coordinate, segment, approach) &&
|
||||||
(use_all_edges ? HasValidEdge(segment, *use_all_edges)
|
(use_all_edges ? HasValidEdge(segment, *use_all_edges)
|
||||||
@@ -69,9 +100,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
: std::make_pair(true, true));
|
: std::make_pair(true, true));
|
||||||
return valid;
|
return valid;
|
||||||
},
|
},
|
||||||
[this, &max_distance, &max_results, input_coordinate](const std::size_t num_results,
|
[this, &max_distance, max_results, input_coordinate](const std::size_t num_results,
|
||||||
const CandidateSegment &segment) {
|
const CandidateSegment &segment)
|
||||||
return (max_results && num_results >= *max_results) ||
|
{
|
||||||
|
return (num_results >= max_results) ||
|
||||||
(max_distance && max_distance != -1.0 &&
|
(max_distance && max_distance != -1.0 &&
|
||||||
CheckSegmentDistance(input_coordinate, segment, *max_distance));
|
CheckSegmentDistance(input_coordinate, segment, *max_distance));
|
||||||
});
|
});
|
||||||
@@ -107,7 +139,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
&big_component_coord,
|
&big_component_coord,
|
||||||
&big_component_distance,
|
&big_component_distance,
|
||||||
&use_all_edges,
|
&use_all_edges,
|
||||||
&bearing_with_range](const CandidateSegment &segment) {
|
&bearing_with_range](const CandidateSegment &segment)
|
||||||
|
{
|
||||||
auto is_big_component = !IsTinyComponent(segment);
|
auto is_big_component = !IsTinyComponent(segment);
|
||||||
auto not_nearest =
|
auto not_nearest =
|
||||||
has_nearest && segment.fixed_projected_coordinate != nearest_coord;
|
has_nearest && segment.fixed_projected_coordinate != nearest_coord;
|
||||||
@@ -159,7 +192,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
return use_candidate;
|
return use_candidate;
|
||||||
},
|
},
|
||||||
[this, &has_big_component, &max_distance, input_coordinate, &big_component_distance](
|
[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 distance = GetSegmentDistance(input_coordinate, segment);
|
||||||
auto further_than_big_component = distance > big_component_distance;
|
auto further_than_big_component = distance > big_component_distance;
|
||||||
auto no_more_candidates = has_big_component && further_than_big_component;
|
auto no_more_candidates = has_big_component && further_than_big_component;
|
||||||
@@ -190,10 +224,14 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
PhantomNodeCandidates nearest_phantoms;
|
PhantomNodeCandidates nearest_phantoms;
|
||||||
PhantomNodeCandidates big_component_phantoms;
|
PhantomNodeCandidates big_component_phantoms;
|
||||||
|
|
||||||
const auto add_to_candidates = [this, &input_coordinate](PhantomNodeCandidates &candidates,
|
const auto add_to_candidates =
|
||||||
const EdgeData data) {
|
[this, &input_coordinate](PhantomNodeCandidates &candidates, const EdgeData data)
|
||||||
|
{
|
||||||
auto candidate_it =
|
auto candidate_it =
|
||||||
std::find_if(candidates.begin(), candidates.end(), [&](const PhantomNode &node) {
|
std::find_if(candidates.begin(),
|
||||||
|
candidates.end(),
|
||||||
|
[&](const PhantomNode &node)
|
||||||
|
{
|
||||||
return data.forward_segment_id.id == node.forward_segment_id.id &&
|
return data.forward_segment_id.id == node.forward_segment_id.id &&
|
||||||
data.reverse_segment_id.id == node.reverse_segment_id.id;
|
data.reverse_segment_id.id == node.reverse_segment_id.id;
|
||||||
});
|
});
|
||||||
@@ -259,7 +297,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::for_each(results.begin(), results.end(), [&](const CandidateSegment &segment) {
|
std::for_each(results.begin(),
|
||||||
|
results.end(),
|
||||||
|
[&](const CandidateSegment &segment)
|
||||||
|
{
|
||||||
if (segment.fixed_projected_coordinate == nearest_coord)
|
if (segment.fixed_projected_coordinate == nearest_coord)
|
||||||
{
|
{
|
||||||
add_to_candidates(nearest_phantoms, segment.data);
|
add_to_candidates(nearest_phantoms, segment.data);
|
||||||
@@ -281,9 +322,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
std::transform(results.begin(),
|
std::transform(results.begin(),
|
||||||
results.end(),
|
results.end(),
|
||||||
distance_and_phantoms.begin(),
|
distance_and_phantoms.begin(),
|
||||||
[this, &input_coordinate](const CandidateSegment &segment) {
|
[this, &input_coordinate](const CandidateSegment &segment)
|
||||||
return MakePhantomNode(input_coordinate, segment.data);
|
{ return MakePhantomNode(input_coordinate, segment.data); });
|
||||||
});
|
|
||||||
return distance_and_phantoms;
|
return distance_and_phantoms;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,9 +440,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check phantom node segments validity
|
// check phantom node segments validity
|
||||||
auto areSegmentsValid = [](auto first, auto last) -> bool {
|
auto areSegmentsValid = [](auto first, auto last) -> bool
|
||||||
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
|
{ return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last; };
|
||||||
};
|
|
||||||
bool is_forward_valid_source =
|
bool is_forward_valid_source =
|
||||||
areSegmentsValid(forward_weights.begin(), forward_weights.end());
|
areSegmentsValid(forward_weights.begin(), forward_weights.end());
|
||||||
bool is_forward_valid_target = areSegmentsValid(
|
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)
|
const bool target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
// merges segments with same name id
|
// 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 out = segments.begin();
|
||||||
auto end = segments.end();
|
auto end = segments.end();
|
||||||
|
|
||||||
@@ -75,7 +76,8 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
|
|||||||
std::transform(route_data.begin(),
|
std::transform(route_data.begin(),
|
||||||
route_data.end(),
|
route_data.end(),
|
||||||
segments.begin(),
|
segments.begin(),
|
||||||
[&index, &facade](const PathData &point) {
|
[&index, &facade](const PathData &point)
|
||||||
|
{
|
||||||
return NamedSegment{point.duration_until_turn,
|
return NamedSegment{point.duration_until_turn,
|
||||||
index++,
|
index++,
|
||||||
facade.GetNameIndex(point.from_edge_based_node)};
|
facade.GetNameIndex(point.from_edge_based_node)};
|
||||||
@@ -87,8 +89,10 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
|
|||||||
if (target_duration > EdgeDuration{1})
|
if (target_duration > EdgeDuration{1})
|
||||||
segments.push_back({target_duration, index++, facade.GetNameIndex(target_node_id)});
|
segments.push_back({target_duration, index++, facade.GetNameIndex(target_node_id)});
|
||||||
// this makes sure that the segment with the lowest position comes first
|
// this makes sure that the segment with the lowest position comes first
|
||||||
std::sort(
|
std::sort(segments.begin(),
|
||||||
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
|
segments.end(),
|
||||||
|
[](const NamedSegment &lhs, const NamedSegment &rhs)
|
||||||
|
{
|
||||||
return lhs.name_id < rhs.name_id ||
|
return lhs.name_id < rhs.name_id ||
|
||||||
(lhs.name_id == rhs.name_id && lhs.position < rhs.position);
|
(lhs.name_id == rhs.name_id && lhs.position < rhs.position);
|
||||||
});
|
});
|
||||||
@@ -96,24 +100,26 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
|
|||||||
segments.resize(new_end - segments.begin());
|
segments.resize(new_end - segments.begin());
|
||||||
|
|
||||||
// Filter out segments with an empty name (name_id == 0)
|
// Filter out segments with an empty name (name_id == 0)
|
||||||
new_end = std::remove_if(segments.begin(), segments.end(), [](const NamedSegment &segment) {
|
new_end = std::remove_if(segments.begin(),
|
||||||
return segment.name_id == 0;
|
segments.end(),
|
||||||
});
|
[](const NamedSegment &segment) { return segment.name_id == 0; });
|
||||||
segments.resize(new_end - segments.begin());
|
segments.resize(new_end - segments.begin());
|
||||||
|
|
||||||
// sort descending
|
// sort descending
|
||||||
std::sort(
|
std::sort(segments.begin(),
|
||||||
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
|
segments.end(),
|
||||||
|
[](const NamedSegment &lhs, const NamedSegment &rhs)
|
||||||
|
{
|
||||||
return lhs.duration > rhs.duration ||
|
return lhs.duration > rhs.duration ||
|
||||||
(lhs.duration == rhs.duration && lhs.position < rhs.position);
|
(lhs.duration == rhs.duration && lhs.position < rhs.position);
|
||||||
});
|
});
|
||||||
|
|
||||||
// make sure the segments are sorted by position
|
// make sure the segments are sorted by position
|
||||||
segments.resize(std::min(segments.size(), SegmentNumber));
|
segments.resize(std::min(segments.size(), SegmentNumber));
|
||||||
std::sort(
|
std::sort(segments.begin(),
|
||||||
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
|
segments.end(),
|
||||||
return lhs.position < rhs.position;
|
[](const NamedSegment &lhs, const NamedSegment &rhs)
|
||||||
});
|
{ return lhs.position < rhs.position; });
|
||||||
|
|
||||||
std::array<std::uint32_t, SegmentNumber> summary;
|
std::array<std::uint32_t, SegmentNumber> summary;
|
||||||
std::fill(summary.begin(), summary.end(), EMPTY_NAMEID);
|
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-
|
// transform a name_id into a string containing either the name, or -if the name is empty-
|
||||||
// the reference.
|
// 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);
|
const auto name = facade.GetNameForID(name_id);
|
||||||
if (!name.empty())
|
if (!name.empty())
|
||||||
return std::string(name);
|
return std::string(name);
|
||||||
@@ -178,14 +185,16 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
const auto target_weight =
|
const auto target_weight =
|
||||||
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight);
|
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight);
|
||||||
|
|
||||||
auto duration = std::accumulate(
|
auto duration = std::accumulate(route_data.begin(),
|
||||||
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
|
route_data.end(),
|
||||||
return sum + from_alias<double>(data.duration_until_turn);
|
0,
|
||||||
});
|
[](const double sum, const PathData &data)
|
||||||
auto weight = std::accumulate(
|
{ return sum + from_alias<double>(data.duration_until_turn); });
|
||||||
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
|
auto weight = std::accumulate(route_data.begin(),
|
||||||
return sum + from_alias<double>(data.weight_until_turn);
|
route_data.end(),
|
||||||
});
|
0,
|
||||||
|
[](const double sum, const PathData &data)
|
||||||
|
{ return sum + from_alias<double>(data.weight_until_turn); });
|
||||||
|
|
||||||
// s
|
// s
|
||||||
// |
|
// |
|
||||||
|
|||||||
@@ -122,9 +122,8 @@ inline bool haveSameMode(const RouteStep &first, const RouteStep &second, const
|
|||||||
// alias for readability
|
// alias for readability
|
||||||
inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
|
inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
|
||||||
{
|
{
|
||||||
const auto has_name_or_ref = [](auto const &step) {
|
const auto has_name_or_ref = [](auto const &step)
|
||||||
return !step.name.empty() || !step.ref.empty();
|
{ return !step.name.empty() || !step.ref.empty(); };
|
||||||
};
|
|
||||||
|
|
||||||
// make sure empty is not involved
|
// make sure empty is not involved
|
||||||
if (!has_name_or_ref(lhs) || !has_name_or_ref(rhs))
|
if (!has_name_or_ref(lhs) || !has_name_or_ref(rhs))
|
||||||
@@ -151,12 +150,14 @@ inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
|
|||||||
// alias for readability, both turn right | left
|
// alias for readability, both turn right | left
|
||||||
inline bool areSameSide(const RouteStep &lhs, const RouteStep &rhs)
|
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) ||
|
return hasModifier(step, osrm::guidance::DirectionModifier::Straight) ||
|
||||||
hasLeftModifier(step.maneuver.instruction);
|
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) ||
|
return hasModifier(step, osrm::guidance::DirectionModifier::Straight) ||
|
||||||
hasRightModifier(step.maneuver.instruction);
|
hasRightModifier(step.maneuver.instruction);
|
||||||
};
|
};
|
||||||
@@ -174,7 +175,8 @@ inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> st
|
|||||||
// Two valid NO_TURNs exist in each leg in the form of Depart/Arrive
|
// Two valid NO_TURNs exist in each leg in the form of Depart/Arrive
|
||||||
|
|
||||||
// keep valid instructions
|
// 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() &&
|
return step.maneuver.instruction == osrm::guidance::TurnInstruction::NO_TURN() &&
|
||||||
step.maneuver.waypoint_type == WaypointType::None;
|
step.maneuver.waypoint_type == WaypointType::None;
|
||||||
};
|
};
|
||||||
@@ -225,7 +227,8 @@ inline double totalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_
|
|||||||
inline bool bearingsAreReversed(const double bearing_in, const double bearing_out)
|
inline bool bearingsAreReversed(const double bearing_in, const double bearing_out)
|
||||||
{
|
{
|
||||||
// Nearly perfectly reversed angles have a difference close to 180 degrees (straight)
|
// 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)
|
if (0 <= bearing_out && bearing_out <= bearing_in)
|
||||||
return bearing_in - bearing_out;
|
return bearing_in - bearing_out;
|
||||||
return bearing_in + 360 - bearing_out;
|
return bearing_in + 360 - bearing_out;
|
||||||
|
|||||||
@@ -20,14 +20,16 @@ template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, It
|
|||||||
{
|
{
|
||||||
while (first != last)
|
while (first != last)
|
||||||
{
|
{
|
||||||
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
|
const auto enter = std::find_if(first,
|
||||||
return entersRoundabout(step.maneuver.instruction);
|
last,
|
||||||
});
|
[](const RouteStep &step)
|
||||||
|
{ return entersRoundabout(step.maneuver.instruction); });
|
||||||
|
|
||||||
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
|
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
|
||||||
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
|
const auto leave = std::find_if(enter,
|
||||||
return leavesRoundabout(step.maneuver.instruction);
|
last,
|
||||||
});
|
[](const RouteStep &step)
|
||||||
|
{ return leavesRoundabout(step.maneuver.instruction); });
|
||||||
|
|
||||||
// No roundabouts, or partial one (like start / end inside a roundabout)
|
// No roundabouts, or partial one (like start / end inside a roundabout)
|
||||||
if (enter == last || leave == last)
|
if (enter == last || leave == last)
|
||||||
|
|||||||
@@ -259,10 +259,10 @@ inline util::Coordinate candidatesInputLocation(const PhantomNodeCandidates &can
|
|||||||
|
|
||||||
inline bool candidatesHaveComponent(const PhantomNodeCandidates &candidates, uint32_t component_id)
|
inline bool candidatesHaveComponent(const PhantomNodeCandidates &candidates, uint32_t component_id)
|
||||||
{
|
{
|
||||||
return std::any_of(
|
return std::any_of(candidates.begin(),
|
||||||
candidates.begin(), candidates.end(), [component_id](const PhantomNode &node) {
|
candidates.end(),
|
||||||
return node.component.id == component_id;
|
[component_id](const PhantomNode &node)
|
||||||
});
|
{ return node.component.id == component_id; });
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PhantomEndpoints
|
struct PhantomEndpoints
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ class BasePlugin
|
|||||||
|
|
||||||
bool CheckAllCoordinates(const std::vector<util::Coordinate> &coordinates) const
|
bool CheckAllCoordinates(const std::vector<util::Coordinate> &coordinates) const
|
||||||
{
|
{
|
||||||
return !std::any_of(
|
return !std::any_of(std::begin(coordinates),
|
||||||
std::begin(coordinates), std::end(coordinates), [](const util::Coordinate coordinate) {
|
std::end(coordinates),
|
||||||
return !coordinate.IsValid();
|
[](const util::Coordinate coordinate)
|
||||||
});
|
{ return !coordinate.IsValid(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckAlgorithms(const api::BaseParameters ¶ms,
|
bool CheckAlgorithms(const api::BaseParameters ¶ms,
|
||||||
@@ -105,13 +105,15 @@ class BasePlugin
|
|||||||
{
|
{
|
||||||
// are all phantoms from a tiny cc?
|
// are all phantoms from a tiny cc?
|
||||||
const auto all_in_same_tiny_component =
|
const auto all_in_same_tiny_component =
|
||||||
[](const std::vector<PhantomCandidateAlternatives> &alts_list) {
|
[](const std::vector<PhantomCandidateAlternatives> &alts_list)
|
||||||
|
{
|
||||||
return std::any_of(
|
return std::any_of(
|
||||||
alts_list.front().first.begin(),
|
alts_list.front().first.begin(),
|
||||||
alts_list.front().first.end(),
|
alts_list.front().first.end(),
|
||||||
// For each of the first possible phantoms, check if all other
|
// For each of the first possible phantoms, check if all other
|
||||||
// positions in the list have a phantom from the same small component.
|
// positions in the list have a phantom from the same small component.
|
||||||
[&](const PhantomNode &phantom) {
|
[&](const PhantomNode &phantom)
|
||||||
|
{
|
||||||
if (!phantom.component.is_tiny)
|
if (!phantom.component.is_tiny)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -120,30 +122,28 @@ class BasePlugin
|
|||||||
return std::all_of(
|
return std::all_of(
|
||||||
std::next(alts_list.begin()),
|
std::next(alts_list.begin()),
|
||||||
std::end(alts_list),
|
std::end(alts_list),
|
||||||
[component_id](const PhantomCandidateAlternatives &alternatives) {
|
[component_id](const PhantomCandidateAlternatives &alternatives)
|
||||||
return candidatesHaveComponent(alternatives.first, component_id);
|
{ return candidatesHaveComponent(alternatives.first, component_id); });
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Move the alternative into the final list
|
// 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();
|
auto no_big_alternative = alternatives.second.empty();
|
||||||
return no_big_alternative ? std::move(alternatives.first)
|
return no_big_alternative ? std::move(alternatives.first)
|
||||||
: std::move(alternatives.second);
|
: std::move(alternatives.second);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Move the alternative into the final list
|
// Move the alternative into the final list
|
||||||
const auto use_closed_phantom = [](PhantomCandidateAlternatives &alternatives) {
|
const auto use_closed_phantom = [](PhantomCandidateAlternatives &alternatives)
|
||||||
return std::move(alternatives.first);
|
{ return std::move(alternatives.first); };
|
||||||
};
|
|
||||||
|
|
||||||
const auto no_alternatives =
|
const auto no_alternatives =
|
||||||
std::all_of(alternatives_list.begin(),
|
std::all_of(alternatives_list.begin(),
|
||||||
alternatives_list.end(),
|
alternatives_list.end(),
|
||||||
[](const PhantomCandidateAlternatives &alternatives) {
|
[](const PhantomCandidateAlternatives &alternatives)
|
||||||
return alternatives.second.empty();
|
{ return alternatives.second.empty(); });
|
||||||
});
|
|
||||||
|
|
||||||
std::vector<PhantomNodeCandidates> snapped_phantoms;
|
std::vector<PhantomNodeCandidates> snapped_phantoms;
|
||||||
snapped_phantoms.reserve(alternatives_list.size());
|
snapped_phantoms.reserve(alternatives_list.size());
|
||||||
@@ -313,12 +313,12 @@ class BasePlugin
|
|||||||
alternatives.end(),
|
alternatives.end(),
|
||||||
coordinates.begin(),
|
coordinates.begin(),
|
||||||
coordinates.end(),
|
coordinates.end(),
|
||||||
[](const auto &candidates_pair, const auto &coordinate) {
|
[](const auto &candidates_pair, const auto &coordinate)
|
||||||
|
{
|
||||||
return std::any_of(candidates_pair.first.begin(),
|
return std::any_of(candidates_pair.first.begin(),
|
||||||
candidates_pair.first.end(),
|
candidates_pair.first.end(),
|
||||||
[&](const auto &phantom) {
|
[&](const auto &phantom)
|
||||||
return phantom.input_location == coordinate;
|
{ return phantom.input_location == coordinate; });
|
||||||
});
|
|
||||||
});
|
});
|
||||||
std::size_t missing_index = std::distance(alternatives.begin(), mismatch.first);
|
std::size_t missing_index = std::distance(alternatives.begin(), mismatch.first);
|
||||||
return std::string("Could not find a matching segment for coordinate ") +
|
return std::string("Could not find a matching segment for coordinate ") +
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter
|
|||||||
begin,
|
begin,
|
||||||
end,
|
end,
|
||||||
[&delta_numbers, ¤t_lat, ¤t_lon, coordinate_to_polyline](
|
[&delta_numbers, ¤t_lat, ¤t_lon, coordinate_to_polyline](
|
||||||
const util::Coordinate loc) {
|
const util::Coordinate loc)
|
||||||
|
{
|
||||||
const int lat_diff =
|
const int lat_diff =
|
||||||
std::round(static_cast<int>(loc.lat) * coordinate_to_polyline) - current_lat;
|
std::round(static_cast<int>(loc.lat) * coordinate_to_polyline) - current_lat;
|
||||||
const int lon_diff =
|
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 FORWARD_DIRECTION = true;
|
||||||
static constexpr bool REVERSE_DIRECTION = false;
|
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.
|
// e.g. if source and destination nodes are on the same segment.
|
||||||
std::vector<NodeID> getForwardLoopNodes(const PhantomEndpointCandidates &candidates);
|
std::vector<NodeID> getForwardForceNodes(const PhantomEndpointCandidates &candidates);
|
||||||
std::vector<NodeID> getForwardLoopNodes(const PhantomCandidatesToTarget &candidates);
|
std::vector<NodeID> getForwardForceNodes(const PhantomCandidatesToTarget &candidates);
|
||||||
std::vector<NodeID> getBackwardLoopNodes(const PhantomEndpointCandidates &candidates);
|
std::vector<NodeID> getBackwardForceNodes(const PhantomEndpointCandidates &candidates);
|
||||||
std::vector<NodeID> getBackwardLoopNodes(const PhantomCandidatesToTarget &candidates);
|
std::vector<NodeID> getBackwardForceNodes(const PhantomCandidatesToTarget &candidates);
|
||||||
|
|
||||||
// Find the specific phantom node endpoints for a given path from a list of candidates.
|
// Find the specific phantom node endpoints for a given path from a list of candidates.
|
||||||
PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candidates,
|
PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candidates,
|
||||||
const std::vector<NodeID> &path);
|
const std::vector<NodeID> &path);
|
||||||
|
|
||||||
template <typename HeapNodeT>
|
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
|
// routing steps are forced when the node is a source of both forward and reverse search heaps.
|
||||||
return !force_nodes.empty() &&
|
return forward_heap_node.data.parent == forward_heap_node.node &&
|
||||||
std::find(force_nodes.begin(), force_nodes.end(), heap_node.node) != force_nodes.end() &&
|
reverse_heap_node.data.parent == reverse_heap_node.node &&
|
||||||
heap_node.data.parent == heap_node.node;
|
std::find(force_nodes.begin(), force_nodes.end(), forward_heap_node.node) !=
|
||||||
|
force_nodes.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Heap>
|
template <typename Heap>
|
||||||
@@ -190,8 +193,10 @@ void annotatePath(const FacadeT &facade,
|
|||||||
std::vector<SegmentDuration> duration_vector;
|
std::vector<SegmentDuration> duration_vector;
|
||||||
std::vector<DatasourceID> datasource_vector;
|
std::vector<DatasourceID> datasource_vector;
|
||||||
|
|
||||||
const auto get_segment_geometry = [&](const auto geometry_index) {
|
const auto get_segment_geometry = [&](const auto geometry_index)
|
||||||
const auto copy = [](auto &vector, const auto range) {
|
{
|
||||||
|
const auto copy = [](auto &vector, const auto range)
|
||||||
|
{
|
||||||
vector.resize(range.size());
|
vector.resize(range.size());
|
||||||
std::copy(range.begin(), range.end(), vector.begin());
|
std::copy(range.begin(), range.end(), vector.begin());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -112,8 +112,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
NodeID &middle_node_id,
|
NodeID &middle_node_id,
|
||||||
EdgeWeight &upper_bound,
|
EdgeWeight &upper_bound,
|
||||||
EdgeWeight min_edge_offset,
|
EdgeWeight min_edge_offset,
|
||||||
const std::vector<NodeID> &force_loop_forward_nodes,
|
const std::vector<NodeID> &force_step_nodes)
|
||||||
const std::vector<NodeID> &force_loop_reverse_nodes)
|
|
||||||
{
|
{
|
||||||
auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
||||||
const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node);
|
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;
|
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
|
||||||
if (new_weight < upper_bound)
|
if (new_weight < upper_bound)
|
||||||
{
|
{
|
||||||
if (force_loop(force_loop_forward_nodes, heapNode) ||
|
if (shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) ||
|
||||||
force_loop(force_loop_reverse_nodes, heapNode) ||
|
|
||||||
// in this case we are looking at a bi-directional way where the source
|
// in this case we are looking at a bi-directional way where the source
|
||||||
// and target phantom are on the same edge based node
|
// and target phantom are on the same edge based node
|
||||||
new_weight < EdgeWeight{0})
|
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))
|
for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
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)
|
// Look for an edge on the forward CH graph (.forward)
|
||||||
EdgeID smaller_edge_id =
|
EdgeID smaller_edge_id =
|
||||||
facade.FindSmallestEdge(std::get<0>(edge), std::get<1>(edge), [](const auto &data) {
|
facade.FindSmallestEdge(std::get<0>(edge),
|
||||||
return data.forward;
|
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
|
// 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,
|
// was found using the backward search. Here, we flip the node order (.second,
|
||||||
@@ -381,7 +380,8 @@ void unpackPath(const FacadeT &facade,
|
|||||||
unpackPath(facade,
|
unpackPath(facade,
|
||||||
packed_path_begin,
|
packed_path_begin,
|
||||||
packed_path_end,
|
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());
|
BOOST_ASSERT(edge.first == unpacked_nodes.back());
|
||||||
unpacked_nodes.push_back(edge.second);
|
unpacked_nodes.push_back(edge.second);
|
||||||
unpacked_edges.push_back(edge_id);
|
unpacked_edges.push_back(edge_id);
|
||||||
@@ -420,23 +420,22 @@ void retrievePackedPathFromSingleManyToManyHeap(
|
|||||||
// assumes that heaps are already setup correctly.
|
// assumes that heaps are already setup correctly.
|
||||||
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
|
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
|
||||||
// Offsets.
|
// Offsets.
|
||||||
// In case additional offsets are supplied, you might have to force a loop first.
|
// In case additional offsets are supplied, you might have to force a routing step first.
|
||||||
// A forced loop might be necessary, if source and target are on the same segment.
|
// 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
|
// If this is the case and the offsets of the respective direction are larger for the source
|
||||||
// than the target
|
// 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
|
// target_phantom.forward_segment_id
|
||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// 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,
|
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const std::vector<NodeID> &force_loop_forward_node,
|
const std::vector<NodeID> &force_step_nodes,
|
||||||
const std::vector<NodeID> &force_loop_reverse_node,
|
|
||||||
const EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT);
|
const EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
template <typename PhantomEndpointT>
|
template <typename PhantomEndpointT>
|
||||||
@@ -446,8 +445,7 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const std::vector<NodeID> &force_loop_forward_node,
|
const std::vector<NodeID> &force_step_nodes,
|
||||||
const std::vector<NodeID> &force_loop_reverse_node,
|
|
||||||
const PhantomEndpointT & /*endpoints*/,
|
const PhantomEndpointT & /*endpoints*/,
|
||||||
const EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT)
|
const EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
@@ -458,14 +456,13 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
reverse_heap,
|
reverse_heap,
|
||||||
weight,
|
weight,
|
||||||
packed_leg,
|
packed_leg,
|
||||||
force_loop_forward_node,
|
force_step_nodes,
|
||||||
force_loop_reverse_node,
|
|
||||||
duration_upper_bound);
|
duration_upper_bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// 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,
|
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<ch::Algorithm> &facade,
|
const DataFacade<ch::Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
const PhantomNode &source,
|
const PhantomNode &source,
|
||||||
const PhantomNode &target)
|
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)
|
if (source.enabled && target.enabled)
|
||||||
return partition.GetQueryLevel(source.id, target.id, node);
|
return partition.GetQueryLevel(source.id, target.id, node);
|
||||||
return INVALID_LEVEL_ID;
|
return INVALID_LEVEL_ID;
|
||||||
@@ -59,7 +60,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
endpoint_candidates.source_phantoms.begin(),
|
endpoint_candidates.source_phantoms.begin(),
|
||||||
endpoint_candidates.source_phantoms.end(),
|
endpoint_candidates.source_phantoms.end(),
|
||||||
INVALID_LEVEL_ID,
|
INVALID_LEVEL_ID,
|
||||||
[&](LevelID current_level, const PhantomNode &source) {
|
[&](LevelID current_level, const PhantomNode &source)
|
||||||
|
{
|
||||||
return std::min(
|
return std::min(
|
||||||
current_level,
|
current_level,
|
||||||
getNodeQueryLevel(partition, node, source, endpoint_candidates.target_phantom));
|
getNodeQueryLevel(partition, node, source, endpoint_candidates.target_phantom));
|
||||||
@@ -76,7 +78,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
endpoint_candidates.source_phantoms.begin(),
|
endpoint_candidates.source_phantoms.begin(),
|
||||||
endpoint_candidates.source_phantoms.end(),
|
endpoint_candidates.source_phantoms.end(),
|
||||||
INVALID_LEVEL_ID,
|
INVALID_LEVEL_ID,
|
||||||
[&](LevelID level_1, const PhantomNode &source) {
|
[&](LevelID level_1, const PhantomNode &source)
|
||||||
|
{
|
||||||
return std::min(
|
return std::min(
|
||||||
level_1,
|
level_1,
|
||||||
std::accumulate(endpoint_candidates.target_phantoms.begin(),
|
std::accumulate(endpoint_candidates.target_phantoms.begin(),
|
||||||
@@ -119,7 +122,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
const NodeID node,
|
const NodeID node,
|
||||||
const PhantomNodeCandidates &candidates)
|
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)
|
return segment.enabled ? partition.GetHighestDifferentLevel(segment.id, node)
|
||||||
: INVALID_LEVEL_ID;
|
: INVALID_LEVEL_ID;
|
||||||
};
|
};
|
||||||
@@ -128,7 +132,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
std::accumulate(candidates.begin(),
|
std::accumulate(candidates.begin(),
|
||||||
candidates.end(),
|
candidates.end(),
|
||||||
INVALID_LEVEL_ID,
|
INVALID_LEVEL_ID,
|
||||||
[&](LevelID current_level, const PhantomNode &phantom_node) {
|
[&](LevelID current_level, const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
auto highest_level =
|
auto highest_level =
|
||||||
std::min(highest_different_level(phantom_node.forward_segment_id),
|
std::min(highest_different_level(phantom_node.forward_segment_id),
|
||||||
highest_different_level(phantom_node.reverse_segment_id));
|
highest_different_level(phantom_node.reverse_segment_id));
|
||||||
@@ -151,9 +156,11 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
|
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
|
||||||
auto init = getNodeQueryLevel(partition, node, candidates_list[phantom_index]);
|
auto init = getNodeQueryLevel(partition, node, candidates_list[phantom_index]);
|
||||||
auto result = std::accumulate(
|
auto result = std::accumulate(
|
||||||
phantom_indices.begin(), phantom_indices.end(), init, [&](LevelID level, size_t index) {
|
phantom_indices.begin(),
|
||||||
return std::min(level, getNodeQueryLevel(partition, node, candidates_list[index]));
|
phantom_indices.end(),
|
||||||
});
|
init,
|
||||||
|
[&](LevelID level, size_t index)
|
||||||
|
{ return std::min(level, getNodeQueryLevel(partition, node, candidates_list[index])); });
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -382,8 +389,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
NodeID &middle_node,
|
NodeID &middle_node,
|
||||||
EdgeWeight &path_upper_bound,
|
EdgeWeight &path_upper_bound,
|
||||||
const std::vector<NodeID> &force_loop_forward_nodes,
|
const std::vector<NodeID> &force_step_nodes,
|
||||||
const std::vector<NodeID> &force_loop_reverse_nodes,
|
|
||||||
const Args &...args)
|
const Args &...args)
|
||||||
{
|
{
|
||||||
const auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
const auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
||||||
@@ -402,11 +408,8 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
auto reverse_weight = reverseHeapNode->weight;
|
auto reverse_weight = reverseHeapNode->weight;
|
||||||
auto path_weight = weight + reverse_weight;
|
auto path_weight = weight + reverse_weight;
|
||||||
|
|
||||||
// MLD uses loops forcing only to prune single node paths in forward and/or
|
if (!shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) &&
|
||||||
// backward direction (there is no need to force loops in MLD but in CH)
|
(path_weight >= EdgeWeight{0}) && (path_weight < path_upper_bound))
|
||||||
if (!force_loop(force_loop_forward_nodes, heapNode) &&
|
|
||||||
!force_loop(force_loop_reverse_nodes, heapNode) && (path_weight >= EdgeWeight{0}) &&
|
|
||||||
(path_weight < path_upper_bound))
|
|
||||||
{
|
{
|
||||||
middle_node = heapNode.node;
|
middle_node = heapNode.node;
|
||||||
path_upper_bound = path_weight;
|
path_upper_bound = path_weight;
|
||||||
@@ -431,8 +434,7 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
const std::vector<NodeID> &force_loop_forward_nodes,
|
const std::vector<NodeID> &force_step_nodes,
|
||||||
const std::vector<NodeID> &force_loop_reverse_nodes,
|
|
||||||
EdgeWeight weight_upper_bound,
|
EdgeWeight weight_upper_bound,
|
||||||
const Args &...args)
|
const Args &...args)
|
||||||
{
|
{
|
||||||
@@ -456,27 +458,15 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{
|
{
|
||||||
if (!forward_heap.Empty())
|
if (!forward_heap.Empty())
|
||||||
{
|
{
|
||||||
routingStep<FORWARD_DIRECTION>(facade,
|
routingStep<FORWARD_DIRECTION>(
|
||||||
forward_heap,
|
facade, forward_heap, reverse_heap, middle, weight, force_step_nodes, args...);
|
||||||
reverse_heap,
|
|
||||||
middle,
|
|
||||||
weight,
|
|
||||||
force_loop_forward_nodes,
|
|
||||||
force_loop_reverse_nodes,
|
|
||||||
args...);
|
|
||||||
if (!forward_heap.Empty())
|
if (!forward_heap.Empty())
|
||||||
forward_heap_min = forward_heap.MinKey();
|
forward_heap_min = forward_heap.MinKey();
|
||||||
}
|
}
|
||||||
if (!reverse_heap.Empty())
|
if (!reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
routingStep<REVERSE_DIRECTION>(facade,
|
routingStep<REVERSE_DIRECTION>(
|
||||||
reverse_heap,
|
facade, reverse_heap, forward_heap, middle, weight, force_step_nodes, args...);
|
||||||
forward_heap,
|
|
||||||
middle,
|
|
||||||
weight,
|
|
||||||
force_loop_reverse_nodes,
|
|
||||||
force_loop_forward_nodes,
|
|
||||||
args...);
|
|
||||||
if (!reverse_heap.Empty())
|
if (!reverse_heap.Empty())
|
||||||
reverse_heap_min = reverse_heap.MinKey();
|
reverse_heap_min = reverse_heap.MinKey();
|
||||||
}
|
}
|
||||||
@@ -505,9 +495,7 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
for (auto const &packed_edge : packed_path)
|
for (auto const &packed_edge : packed_path)
|
||||||
{
|
{
|
||||||
NodeID source, target;
|
auto [source, target, overlay_edge] = packed_edge;
|
||||||
bool overlay_edge;
|
|
||||||
std::tie(source, target, overlay_edge) = packed_edge;
|
|
||||||
if (!overlay_edge)
|
if (!overlay_edge)
|
||||||
{ // a base graph edge
|
{ // a base graph edge
|
||||||
unpacked_nodes.push_back(target);
|
unpacked_nodes.push_back(target);
|
||||||
@@ -527,18 +515,11 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
forward_heap.Insert(source, {0}, {source});
|
forward_heap.Insert(source, {0}, {source});
|
||||||
reverse_heap.Insert(target, {0}, {target});
|
reverse_heap.Insert(target, {0}, {target});
|
||||||
|
|
||||||
// TODO: when structured bindings will be allowed change to
|
auto [subpath_weight, subpath_nodes, subpath_edges] = search(engine_working_data,
|
||||||
// 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,
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
force_loop_forward_nodes,
|
force_step_nodes,
|
||||||
force_loop_reverse_nodes,
|
|
||||||
INVALID_EDGE_WEIGHT,
|
INVALID_EDGE_WEIGHT,
|
||||||
sublevel,
|
sublevel,
|
||||||
parent_cell_id);
|
parent_cell_id);
|
||||||
@@ -563,8 +544,7 @@ inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &unpacked_nodes,
|
std::vector<NodeID> &unpacked_nodes,
|
||||||
const std::vector<NodeID> &force_loop_forward_node,
|
const std::vector<NodeID> &force_step_nodes,
|
||||||
const std::vector<NodeID> &force_loop_reverse_node,
|
|
||||||
const PhantomEndpointT &endpoints,
|
const PhantomEndpointT &endpoints,
|
||||||
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
@@ -573,8 +553,7 @@ inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
facade,
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
force_loop_forward_node,
|
force_step_nodes,
|
||||||
force_loop_reverse_node,
|
|
||||||
weight_upper_bound,
|
weight_upper_bound,
|
||||||
endpoints);
|
endpoints);
|
||||||
}
|
}
|
||||||
@@ -601,7 +580,8 @@ void unpackPath(const FacadeT &facade,
|
|||||||
util::for_each_pair(
|
util::for_each_pair(
|
||||||
packed_path_begin,
|
packed_path_begin,
|
||||||
packed_path_end,
|
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_nodes.push_back(to);
|
||||||
unpacked_edges.push_back(facade.FindEdge(from, to));
|
unpacked_edges.push_back(facade.FindEdge(from, to));
|
||||||
});
|
});
|
||||||
@@ -625,28 +605,46 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const PhantomEndpoints endpoints{source_phantom, target_phantom};
|
const PhantomEndpoints endpoints{source_phantom, target_phantom};
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, endpoints);
|
insertNodesInHeaps(forward_heap, reverse_heap, endpoints);
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
auto [weight, unpacked_nodes, unpacked_edges] = search(
|
||||||
std::vector<NodeID> unpacked_nodes;
|
engine_working_data, facade, forward_heap, reverse_heap, {}, weight_upper_bound, endpoints);
|
||||||
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);
|
|
||||||
|
|
||||||
if (weight == INVALID_EDGE_WEIGHT)
|
if (weight == INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PathData> unpacked_path;
|
BOOST_ASSERT(unpacked_nodes.size() >= 1);
|
||||||
|
|
||||||
annotatePath(facade, endpoints, unpacked_nodes, unpacked_edges, unpacked_path);
|
EdgeDistance distance = {0.0};
|
||||||
|
|
||||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
if (source_phantom.forward_segment_id.id == unpacked_nodes.front())
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(source_phantom.forward_segment_id.enabled);
|
||||||
|
distance = EdgeDistance{0} - source_phantom.GetForwardDistance();
|
||||||
|
}
|
||||||
|
else if (source_phantom.reverse_segment_id.id == unpacked_nodes.front())
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(source_phantom.reverse_segment_id.enabled);
|
||||||
|
distance = EdgeDistance{0} - source_phantom.GetReverseDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t index = 0; index < unpacked_nodes.size() - 1; ++index)
|
||||||
|
{
|
||||||
|
distance += facade.GetNodeDistance(unpacked_nodes[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_phantom.forward_segment_id.id == unpacked_nodes.back())
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(target_phantom.forward_segment_id.enabled);
|
||||||
|
distance += target_phantom.GetForwardDistance();
|
||||||
|
}
|
||||||
|
else if (target_phantom.reverse_segment_id.id == unpacked_nodes.back())
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(target_phantom.reverse_segment_id.enabled);
|
||||||
|
distance += target_phantom.GetReverseDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return from_alias<double>(distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace osrm::engine::routing_algorithms::mld
|
} // 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 &forward_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
const PhantomEndpointCandidates &candidates,
|
const PhantomEndpointCandidates &candidates,
|
||||||
const EdgeWeight &total_weight,
|
EdgeWeight &leg_weight,
|
||||||
EdgeWeight &new_total_weight,
|
|
||||||
std::vector<NodeID> &leg_packed_path)
|
std::vector<NodeID> &leg_packed_path)
|
||||||
{
|
{
|
||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
@@ -31,14 +30,14 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
if (source.IsValidForwardSource())
|
if (source.IsValidForwardSource())
|
||||||
{
|
{
|
||||||
forward_heap.Insert(source.forward_segment_id.id,
|
forward_heap.Insert(source.forward_segment_id.id,
|
||||||
total_weight - source.GetForwardWeightPlusOffset(),
|
EdgeWeight{0} - source.GetForwardWeightPlusOffset(),
|
||||||
source.forward_segment_id.id);
|
source.forward_segment_id.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.IsValidReverseSource())
|
if (source.IsValidReverseSource())
|
||||||
{
|
{
|
||||||
forward_heap.Insert(source.reverse_segment_id.id,
|
forward_heap.Insert(source.reverse_segment_id.id,
|
||||||
total_weight - source.GetReverseWeightPlusOffset(),
|
EdgeWeight{0} - source.GetReverseWeightPlusOffset(),
|
||||||
source.reverse_segment_id.id);
|
source.reverse_segment_id.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,10 +61,9 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
facade,
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
new_total_weight,
|
leg_weight,
|
||||||
leg_packed_path,
|
leg_packed_path,
|
||||||
getForwardLoopNodes(candidates),
|
{},
|
||||||
getBackwardLoopNodes(candidates),
|
|
||||||
candidates);
|
candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +123,7 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
reverse_heap,
|
reverse_heap,
|
||||||
new_total_weight_to_forward,
|
new_total_weight_to_forward,
|
||||||
leg_packed_path_forward,
|
leg_packed_path_forward,
|
||||||
getForwardLoopNodes(candidates),
|
getForwardForceNodes(candidates),
|
||||||
{},
|
|
||||||
candidates);
|
candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,8 +162,7 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
reverse_heap,
|
reverse_heap,
|
||||||
new_total_weight_to_reverse,
|
new_total_weight_to_reverse,
|
||||||
leg_packed_path_reverse,
|
leg_packed_path_reverse,
|
||||||
{},
|
getBackwardForceNodes(candidates),
|
||||||
getBackwardLoopNodes(candidates),
|
|
||||||
candidates);
|
candidates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +244,8 @@ constructRouteResult(const DataFacade<Algorithm> &facade,
|
|||||||
auto source_it =
|
auto source_it =
|
||||||
std::find_if(source_candidates.begin(),
|
std::find_if(source_candidates.begin(),
|
||||||
source_candidates.end(),
|
source_candidates.end(),
|
||||||
[&start_node](const auto &source_phantom) {
|
[&start_node](const auto &source_phantom)
|
||||||
|
{
|
||||||
return (start_node == source_phantom.forward_segment_id.id ||
|
return (start_node == source_phantom.forward_segment_id.id ||
|
||||||
start_node == source_phantom.reverse_segment_id.id);
|
start_node == source_phantom.reverse_segment_id.id);
|
||||||
});
|
});
|
||||||
@@ -257,7 +254,8 @@ constructRouteResult(const DataFacade<Algorithm> &facade,
|
|||||||
auto target_it =
|
auto target_it =
|
||||||
std::find_if(target_candidates.begin(),
|
std::find_if(target_candidates.begin(),
|
||||||
target_candidates.end(),
|
target_candidates.end(),
|
||||||
[&end_node](const auto &target_phantom) {
|
[&end_node](const auto &target_phantom)
|
||||||
|
{
|
||||||
return (end_node == target_phantom.forward_segment_id.id ||
|
return (end_node == target_phantom.forward_segment_id.id ||
|
||||||
end_node == target_phantom.reverse_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],
|
PhantomEndpointCandidates search_candidates{waypoint_candidates[i],
|
||||||
waypoint_candidates[i + 1]};
|
waypoint_candidates[i + 1]};
|
||||||
std::vector<NodeID> packed_leg;
|
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
|
// We have a valid path up to this leg
|
||||||
BOOST_ASSERT(total_weight != INVALID_EDGE_WEIGHT);
|
BOOST_ASSERT(total_weight != INVALID_EDGE_WEIGHT);
|
||||||
@@ -311,16 +309,15 @@ shortestPathWithWaypointUTurns(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
search_candidates,
|
search_candidates,
|
||||||
total_weight,
|
leg_weight,
|
||||||
new_total_weight,
|
|
||||||
packed_leg);
|
packed_leg);
|
||||||
|
|
||||||
if (new_total_weight == INVALID_EDGE_WEIGHT)
|
if (leg_weight == INVALID_EDGE_WEIGHT)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
packed_leg_begin.push_back(total_packed_path.size());
|
packed_leg_begin.push_back(total_packed_path.size());
|
||||||
total_packed_path.insert(total_packed_path.end(), packed_leg.begin(), packed_leg.end());
|
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
|
// Add sentinel
|
||||||
@@ -466,16 +463,16 @@ struct route_state
|
|||||||
last.total_weight_to_forward.resize(init_candidates.size(), {0});
|
last.total_weight_to_forward.resize(init_candidates.size(), {0});
|
||||||
last.total_weight_to_reverse.resize(init_candidates.size(), {0});
|
last.total_weight_to_reverse.resize(init_candidates.size(), {0});
|
||||||
// Initialize routability from source validity.
|
// Initialize routability from source validity.
|
||||||
std::transform(
|
std::transform(init_candidates.begin(),
|
||||||
init_candidates.begin(),
|
|
||||||
init_candidates.end(),
|
init_candidates.end(),
|
||||||
std::back_inserter(last.reached_forward_node_target),
|
std::back_inserter(last.reached_forward_node_target),
|
||||||
[](const PhantomNode &phantom_node) { return phantom_node.IsValidForwardSource(); });
|
[](const PhantomNode &phantom_node)
|
||||||
std::transform(
|
{ return phantom_node.IsValidForwardSource(); });
|
||||||
init_candidates.begin(),
|
std::transform(init_candidates.begin(),
|
||||||
init_candidates.end(),
|
init_candidates.end(),
|
||||||
std::back_inserter(last.reached_reverse_node_target),
|
std::back_inserter(last.reached_reverse_node_target),
|
||||||
[](const PhantomNode &phantom_node) { return phantom_node.IsValidReverseSource(); });
|
[](const PhantomNode &phantom_node)
|
||||||
|
{ return phantom_node.IsValidReverseSource(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool completeLeg()
|
bool completeLeg()
|
||||||
@@ -613,15 +610,21 @@ struct route_state
|
|||||||
{
|
{
|
||||||
// Find the segment from final leg with the shortest path
|
// 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_range = util::irange<std::size_t>(0UL, last.total_weight_to_forward.size());
|
||||||
auto forward_min =
|
auto forward_min = std::min_element(
|
||||||
std::min_element(forward_range.begin(), forward_range.end(), [&](size_t a, size_t b) {
|
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] ||
|
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_weight_to_forward[a] == last.total_weight_to_forward[b] &&
|
||||||
last.total_nodes_to_forward[a] < last.total_nodes_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_range = util::irange<std::size_t>(0UL, last.total_weight_to_reverse.size());
|
||||||
auto reverse_min =
|
auto reverse_min = std::min_element(
|
||||||
std::min_element(reverse_range.begin(), reverse_range.end(), [&](size_t a, size_t b) {
|
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] ||
|
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_weight_to_reverse[a] == last.total_weight_to_reverse[b] &&
|
||||||
last.total_nodes_to_reverse[a] < last.total_nodes_to_reverse[b]));
|
last.total_nodes_to_reverse[a] < last.total_nodes_to_reverse[b]));
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ inline auto getClassData(const std::size_t index)
|
|||||||
|
|
||||||
inline bool isValidClassName(const std::string &name)
|
inline bool isValidClassName(const std::string &name)
|
||||||
{
|
{
|
||||||
return std::find_if_not(name.begin(), name.end(), [](const auto c) {
|
return std::find_if_not(name.begin(),
|
||||||
return std::isalnum(c);
|
name.end(),
|
||||||
}) == name.end();
|
[](const auto c) { return std::isalnum(c); }) == name.end();
|
||||||
}
|
}
|
||||||
} // namespace osrm::extractor
|
} // 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
|
// collapse spaces; this is needed in case we expand "; X" => "; X" above
|
||||||
// but also makes sense to do irregardless of the fact - canonicalizing strings.
|
// but also makes sense to do irregardless of the fact - canonicalizing strings.
|
||||||
const auto spaces = [](unsigned char lhs, unsigned char rhs) {
|
const auto spaces = [](unsigned char lhs, unsigned char rhs)
|
||||||
return ::isspace(lhs) && ::isspace(rhs);
|
{ return ::isspace(lhs) && ::isspace(rhs); };
|
||||||
};
|
|
||||||
auto it = std::unique(begin(strlist), end(strlist), spaces);
|
auto it = std::unique(begin(strlist), end(strlist), spaces);
|
||||||
strlist.erase(it, end(strlist));
|
strlist.erase(it, end(strlist));
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ class ExtractionRelationContainer
|
|||||||
(void)res; // prevent unused warning in release
|
(void)res; // prevent unused warning in release
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MergeRefMap = [&](RelationRefMap &source, RelationRefMap &target) {
|
auto MergeRefMap = [&](RelationRefMap &source, RelationRefMap &target)
|
||||||
|
{
|
||||||
for (auto it : source)
|
for (auto it : source)
|
||||||
{
|
{
|
||||||
auto &v = target[it.first];
|
auto &v = target[it.first];
|
||||||
@@ -151,7 +152,8 @@ class ExtractionRelationContainer
|
|||||||
const RelationIDList &GetRelations(const OsmIDTyped &member_id) const
|
const RelationIDList &GetRelations(const OsmIDTyped &member_id) const
|
||||||
{
|
{
|
||||||
auto getFromMap = [this](std::uint64_t id,
|
auto getFromMap = [this](std::uint64_t id,
|
||||||
const RelationRefMap &map) -> const RelationIDList & {
|
const RelationRefMap &map) -> const RelationIDList &
|
||||||
|
{
|
||||||
auto it = map.find(id);
|
auto it = map.find(id);
|
||||||
if (it != map.end())
|
if (it != map.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|||||||
@@ -453,7 +453,8 @@ void readRawNBGraph(const boost::filesystem::path &path,
|
|||||||
coordinates.resize(number_of_nodes);
|
coordinates.resize(number_of_nodes);
|
||||||
osm_node_ids.reserve(number_of_nodes);
|
osm_node_ids.reserve(number_of_nodes);
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
auto decode = [&](const auto ¤t_node) {
|
auto decode = [&](const auto ¤t_node)
|
||||||
|
{
|
||||||
coordinates[index].lon = current_node.lon;
|
coordinates[index].lon = current_node.lon;
|
||||||
coordinates[index].lat = current_node.lat;
|
coordinates[index].lat = current_node.lat;
|
||||||
osm_node_ids.push_back(current_node.node_id);
|
osm_node_ids.push_back(current_node.node_id);
|
||||||
|
|||||||
@@ -26,16 +26,14 @@ namespace osrm::extractor::intersection
|
|||||||
|
|
||||||
inline auto makeCompareAngularDeviation(const double angle)
|
inline auto makeCompareAngularDeviation(const double angle)
|
||||||
{
|
{
|
||||||
return [angle](const auto &lhs, const auto &rhs) {
|
return [angle](const auto &lhs, const auto &rhs)
|
||||||
return util::angularDeviation(lhs.angle, angle) < util::angularDeviation(rhs.angle, angle);
|
{ return util::angularDeviation(lhs.angle, angle) < util::angularDeviation(rhs.angle, angle); };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto makeExtractLanesForRoad(const util::NodeBasedDynamicGraph &node_based_graph)
|
inline auto makeExtractLanesForRoad(const util::NodeBasedDynamicGraph &node_based_graph)
|
||||||
{
|
{
|
||||||
return [&node_based_graph](const auto &road) {
|
return [&node_based_graph](const auto &road)
|
||||||
return node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
|
{ 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
|
// 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
|
auto FindClosestBearing(double base_bearing) const
|
||||||
{
|
{
|
||||||
return std::min_element(
|
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) <
|
return util::angularDeviation(lhs.perceived_bearing, base_bearing) <
|
||||||
util::angularDeviation(rhs.perceived_bearing, base_bearing);
|
util::angularDeviation(rhs.perceived_bearing, base_bearing);
|
||||||
});
|
});
|
||||||
@@ -81,7 +82,8 @@ template <typename Self> struct EnableShapeOps
|
|||||||
BOOST_ASSERT(!self()->empty());
|
BOOST_ASSERT(!self()->empty());
|
||||||
auto initial = converter(self()->front());
|
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));
|
initial = std::max(initial, converter(road));
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -191,8 +193,10 @@ template <typename Self> struct EnableIntersectionOps
|
|||||||
auto findClosestTurn(const double angle, const UnaryPredicate filter) const
|
auto findClosestTurn(const double angle, const UnaryPredicate filter) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!self()->empty());
|
BOOST_ASSERT(!self()->empty());
|
||||||
const auto candidate =
|
const auto candidate = boost::range::min_element(
|
||||||
boost::range::min_element(*self(), [angle, &filter](const auto &lhs, const auto &rhs) {
|
*self(),
|
||||||
|
[angle, &filter](const auto &lhs, const auto &rhs)
|
||||||
|
{
|
||||||
const auto filtered_lhs = filter(lhs), filtered_rhs = filter(rhs);
|
const auto filtered_lhs = filter(lhs), filtered_rhs = filter(rhs);
|
||||||
const auto deviation_lhs = util::angularDeviation(lhs.angle, angle),
|
const auto deviation_lhs = util::angularDeviation(lhs.angle, angle),
|
||||||
deviation_rhs = util::angularDeviation(rhs.angle, angle);
|
deviation_rhs = util::angularDeviation(rhs.angle, angle);
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace osrm::extractor::intersection
|
namespace osrm::extractor::intersection
|
||||||
@@ -42,7 +42,7 @@ class NodeBasedGraphWalker
|
|||||||
* selector not provinding any further edge to traverse)
|
* selector not provinding any further edge to traverse)
|
||||||
*/
|
*/
|
||||||
template <class accumulator_type, class selector_type>
|
template <class accumulator_type, class selector_type>
|
||||||
boost::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
|
std::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
|
||||||
EdgeID following_edge_id,
|
EdgeID following_edge_id,
|
||||||
accumulator_type &accumulator,
|
accumulator_type &accumulator,
|
||||||
const selector_type &selector) const;
|
const selector_type &selector) const;
|
||||||
@@ -111,7 +111,7 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
|
|||||||
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
|
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
|
||||||
* form of obious turn to follow.
|
* form of obious turn to follow.
|
||||||
*/
|
*/
|
||||||
boost::optional<EdgeID> operator()(const NodeID nid,
|
std::optional<EdgeID> operator()(const NodeID nid,
|
||||||
const EdgeID via_edge_id,
|
const EdgeID via_edge_id,
|
||||||
const IntersectionView &intersection,
|
const IntersectionView &intersection,
|
||||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
@@ -138,7 +138,7 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
|
|||||||
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
|
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
|
||||||
* form of obious turn to follow.
|
* form of obious turn to follow.
|
||||||
*/
|
*/
|
||||||
boost::optional<EdgeID> operator()(const NodeID nid,
|
std::optional<EdgeID> operator()(const NodeID nid,
|
||||||
const EdgeID via_edge_id,
|
const EdgeID via_edge_id,
|
||||||
const IntersectionView &intersection,
|
const IntersectionView &intersection,
|
||||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
@@ -187,7 +187,7 @@ struct IntersectionFinderAccumulator
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class accumulator_type, class selector_type>
|
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,
|
NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
|
||||||
EdgeID current_edge_id,
|
EdgeID current_edge_id,
|
||||||
accumulator_type &accumulator,
|
accumulator_type &accumulator,
|
||||||
@@ -254,7 +254,7 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
|
|||||||
|
|
||||||
struct SkipTrafficSignalBarrierRoadSelector
|
struct SkipTrafficSignalBarrierRoadSelector
|
||||||
{
|
{
|
||||||
boost::optional<EdgeID> operator()(const NodeID,
|
std::optional<EdgeID> operator()(const NodeID,
|
||||||
const EdgeID,
|
const EdgeID,
|
||||||
const IntersectionView &intersection,
|
const IntersectionView &intersection,
|
||||||
const util::NodeBasedDynamicGraph &,
|
const util::NodeBasedDynamicGraph &,
|
||||||
@@ -262,11 +262,11 @@ struct SkipTrafficSignalBarrierRoadSelector
|
|||||||
{
|
{
|
||||||
if (intersection.isTrafficSignalOrBarrier())
|
if (intersection.isTrafficSignalOrBarrier())
|
||||||
{
|
{
|
||||||
return boost::make_optional(intersection[1].eid);
|
return std::make_optional(intersection[1].eid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "maneuver_override.hpp"
|
#include "maneuver_override.hpp"
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class ManeuverOverrideRelationParser
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ManeuverOverrideRelationParser();
|
ManeuverOverrideRelationParser();
|
||||||
boost::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
|
std::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
|
||||||
};
|
};
|
||||||
} // namespace osrm::extractor
|
} // namespace osrm::extractor
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,8 @@ template <typename RestrictionFilter> class NodeRestrictionMap
|
|||||||
// Find all restrictions applicable to (from,via,to) turns
|
// Find all restrictions applicable to (from,via,to) turns
|
||||||
auto Restrictions(NodeID from, NodeID via, NodeID to) const
|
auto Restrictions(NodeID from, NodeID via, NodeID to) const
|
||||||
{
|
{
|
||||||
const auto turnFilter = [this, to](const auto &restriction) {
|
const auto turnFilter = [this, to](const auto &restriction)
|
||||||
return index_filter(restriction) && restriction->IsTurnRestricted(to);
|
{ return index_filter(restriction) && restriction->IsTurnRestricted(to); };
|
||||||
};
|
|
||||||
return getRange(from, via) | boost::adaptors::filtered(turnFilter);
|
return getRange(from, via) | boost::adaptors::filtered(turnFilter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/numeric/conversion/cast.hpp>
|
#include <boost/numeric/conversion/cast.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace osrm::extractor
|
namespace osrm::extractor
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ struct ProfileProperties
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if this classes are excludable
|
// 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);
|
auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes);
|
||||||
if (iter != excludable_classes.end())
|
if (iter != excludable_classes.end())
|
||||||
|
|||||||
@@ -15,11 +15,10 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace osrm::guidance
|
namespace osrm::guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -129,7 +128,7 @@ class IntersectionHandler
|
|||||||
// ^ via
|
// ^ via
|
||||||
//
|
//
|
||||||
// For this scenario returns intersection at `b` and `b`.
|
// 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;
|
getNextIntersection(const NodeID at, const EdgeID via) const;
|
||||||
|
|
||||||
bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) 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);
|
node_data_container.GetAnnotation(candidate_data.annotation_data);
|
||||||
auto const candidate_deviation = util::angularDeviation(candidate->angle, STRAIGHT_ANGLE);
|
auto const candidate_deviation = util::angularDeviation(candidate->angle, STRAIGHT_ANGLE);
|
||||||
|
|
||||||
auto const num_lanes = [](auto const &data) {
|
auto const num_lanes = [](auto const &data)
|
||||||
return data.flags.road_classification.GetNumberOfLanes();
|
{ 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
|
// 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);
|
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
|
// 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
|
// 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
|
// 1. Skip the candidate road
|
||||||
if (road.eid == candidate->eid)
|
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
|
// 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
|
// 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
|
// 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
|
// 1. Skip over our candidate
|
||||||
if (road.eid == candidate->eid)
|
if (road.eid == candidate->eid)
|
||||||
return false;
|
return false;
|
||||||
@@ -503,7 +504,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
node_data_container.GetAnnotation(via_edge_data.annotation_data);
|
node_data_container.GetAnnotation(via_edge_data.annotation_data);
|
||||||
|
|
||||||
// implement a filter, taking out all roads of lower class or different names
|
// 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
|
// it needs to be possible to enter the road
|
||||||
if (!road.entry_allowed)
|
if (!road.entry_allowed)
|
||||||
return true;
|
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
|
// 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
|
// 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 &from_data = node_based_graph.GetEdgeData(via_edge);
|
||||||
auto const &to_data = node_based_graph.GetEdgeData(iterator->eid);
|
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
|
// opposed to before, we do not care about name changes, again: this is a filter, so internal
|
||||||
// false/true will be negated for selection
|
// 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)
|
if (!road.entry_allowed)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -640,7 +644,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
const auto all_roads_have_same_name =
|
const auto all_roads_have_same_name =
|
||||||
std::all_of(intersection.begin(),
|
std::all_of(intersection.begin(),
|
||||||
intersection.end(),
|
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 data_id = node_based_graph.GetEdgeData(road.eid).annotation_data;
|
||||||
auto const name_id = node_data_container.GetAnnotation(data_id).name_id;
|
auto const name_id = node_data_container.GetAnnotation(data_id).name_id;
|
||||||
return (name_id != EMPTY_NAMEID) && (name_id == id);
|
return (name_id != EMPTY_NAMEID) && (name_id == id);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t co
|
|||||||
OSRM_ATTR_WARN_UNUSED
|
OSRM_ATTR_WARN_UNUSED
|
||||||
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
|
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);
|
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
|
||||||
tokenizer tokens(lane_string, sep);
|
tokenizer tokens(lane_string, sep);
|
||||||
tokenizer access(access_tokens, sep);
|
tokenizer access(access_tokens, sep);
|
||||||
|
|||||||
@@ -9,10 +9,9 @@
|
|||||||
|
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace osrm::guidance
|
namespace osrm::guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ class SliproadHandler final : public IntersectionHandler
|
|||||||
Intersection intersection) const override final;
|
Intersection intersection) const override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
|
std::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
|
||||||
const Intersection &intersection,
|
const Intersection &intersection,
|
||||||
const NodeID at) const;
|
const NodeID at) const;
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,8 @@
|
|||||||
#include "util/attributes.hpp"
|
#include "util/attributes.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -72,7 +71,7 @@ class TurnHandler final : public IntersectionHandler
|
|||||||
|
|
||||||
bool hasObvious(const EdgeID &via_edge, const Fork &fork) const;
|
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;
|
bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const;
|
||||||
|
|
||||||
@@ -96,7 +95,7 @@ class TurnHandler final : public IntersectionHandler
|
|||||||
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
||||||
|
|
||||||
// Classification
|
// 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
|
OSRM_ATTR_WARN_UNUSED
|
||||||
Intersection assignLeftTurns(const EdgeID via_edge,
|
Intersection assignLeftTurns(const EdgeID via_edge,
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
#ifndef OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
|
#ifndef OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
|
||||||
#define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
|
#define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include "guidance/roundabout_type.hpp"
|
#include "guidance/roundabout_type.hpp"
|
||||||
#include "util/attributes.hpp"
|
#include "util/attributes.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace osrm::guidance
|
namespace osrm::guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -154,7 +155,8 @@ inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs)
|
|||||||
inline bool hasRoundaboutType(const TurnInstruction instruction)
|
inline bool hasRoundaboutType(const TurnInstruction instruction)
|
||||||
{
|
{
|
||||||
using namespace guidance::TurnType;
|
using namespace guidance::TurnType;
|
||||||
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
|
const constexpr std::array<TurnType::Enum, 13> valid_types = {
|
||||||
|
TurnType::EnterRoundabout,
|
||||||
TurnType::EnterAndExitRoundabout,
|
TurnType::EnterAndExitRoundabout,
|
||||||
TurnType::EnterRotary,
|
TurnType::EnterRotary,
|
||||||
TurnType::EnterAndExitRotary,
|
TurnType::EnterAndExitRotary,
|
||||||
@@ -168,10 +170,8 @@ inline bool hasRoundaboutType(const TurnInstruction instruction)
|
|||||||
TurnType::ExitRoundaboutIntersection,
|
TurnType::ExitRoundaboutIntersection,
|
||||||
TurnType::StayOnRoundabout};
|
TurnType::StayOnRoundabout};
|
||||||
|
|
||||||
const auto *first = valid_types;
|
return std::find(valid_types.cbegin(), valid_types.cend(), instruction.type) !=
|
||||||
const auto *last = first + sizeof(valid_types) / sizeof(valid_types[0]);
|
valid_types.cend();
|
||||||
|
|
||||||
return std::find(first, last, instruction.type) != last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool entersRoundabout(const guidance::TurnInstruction instruction)
|
inline bool entersRoundabout(const guidance::TurnInstruction instruction)
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ inline BisectionGraph makeBisectionGraph(const std::vector<util::Coordinate> &co
|
|||||||
result_edges.reserve(edges.size());
|
result_edges.reserve(edges.size());
|
||||||
|
|
||||||
// find the end of edges that belong to node_id
|
// find the end of edges that belong to node_id
|
||||||
const auto advance_edge_itr = [&edges, &result_edges](const std::size_t node_id,
|
const auto advance_edge_itr = [&edges, &result_edges](const std::size_t node_id, auto edge_itr)
|
||||||
auto edge_itr) {
|
{
|
||||||
while (edge_itr != edges.end() && edge_itr->source == node_id)
|
while (edge_itr != edges.end() && edge_itr->source == node_id)
|
||||||
{
|
{
|
||||||
result_edges.push_back(edge_itr->Reduce());
|
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
|
// 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 make_bisection_node =
|
||||||
const auto begin_itr,
|
[&edges, &coordinates](const std::size_t node_id, const auto begin_itr, const auto end_itr)
|
||||||
const auto end_itr) {
|
{
|
||||||
std::size_t range_begin = std::distance(edges.begin(), begin_itr);
|
std::size_t range_begin = std::distance(edges.begin(), begin_itr);
|
||||||
std::size_t range_end = std::distance(edges.begin(), end_itr);
|
std::size_t range_end = std::distance(edges.begin(), end_itr);
|
||||||
return BisectionGraph::NodeT(range_begin, range_end, coordinates[node_id], node_id);
|
return BisectionGraph::NodeT(range_begin, range_end, coordinates[node_id], node_id);
|
||||||
@@ -102,7 +102,10 @@ std::vector<BisectionInputEdge> adaptToBisectionEdge(std::vector<InputEdge> edge
|
|||||||
std::vector<BisectionInputEdge> result;
|
std::vector<BisectionInputEdge> result;
|
||||||
result.reserve(edges.size());
|
result.reserve(edges.size());
|
||||||
|
|
||||||
std::transform(begin(edges), end(edges), std::back_inserter(result), [](const auto &edge) {
|
std::transform(begin(edges),
|
||||||
|
end(edges),
|
||||||
|
std::back_inserter(result),
|
||||||
|
[](const auto &edge) {
|
||||||
return BisectionInputEdge{edge.source, edge.target};
|
return BisectionInputEdge{edge.source, edge.target};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -298,7 +298,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
auto set_num_nodes_fn,
|
auto set_num_nodes_fn,
|
||||||
auto set_boundary_offset_fn,
|
auto set_boundary_offset_fn,
|
||||||
auto begin,
|
auto begin,
|
||||||
auto end) {
|
auto end)
|
||||||
|
{
|
||||||
BOOST_ASSERT(std::distance(begin, end) > 0);
|
BOOST_ASSERT(std::distance(begin, end) > 0);
|
||||||
|
|
||||||
const auto cell_id = begin->first;
|
const auto cell_id = begin->first;
|
||||||
@@ -316,7 +317,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
util::for_each_range(
|
util::for_each_range(
|
||||||
level_source_boundary.begin(),
|
level_source_boundary.begin(),
|
||||||
level_source_boundary.end(),
|
level_source_boundary.end(),
|
||||||
[this, insert_cell_boundary](auto begin, auto end) {
|
[this, insert_cell_boundary](auto begin, auto end)
|
||||||
|
{
|
||||||
insert_cell_boundary(
|
insert_cell_boundary(
|
||||||
source_boundary,
|
source_boundary,
|
||||||
[](auto &cell, auto value) { cell.num_source_nodes = value; },
|
[](auto &cell, auto value) { cell.num_source_nodes = value; },
|
||||||
@@ -327,7 +329,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
|||||||
util::for_each_range(
|
util::for_each_range(
|
||||||
level_destination_boundary.begin(),
|
level_destination_boundary.begin(),
|
||||||
level_destination_boundary.end(),
|
level_destination_boundary.end(),
|
||||||
[this, insert_cell_boundary](auto begin, auto end) {
|
[this, insert_cell_boundary](auto begin, auto end)
|
||||||
|
{
|
||||||
insert_cell_boundary(
|
insert_cell_boundary(
|
||||||
destination_boundary,
|
destination_boundary,
|
||||||
[](auto &cell, auto value) { cell.num_destination_nodes = value; },
|
[](auto &cell, auto value) { cell.num_destination_nodes = value; },
|
||||||
|
|||||||
@@ -64,7 +64,10 @@ std::vector<OutputEdgeT> prepareEdgesForUsageInGraph(std::vector<extractor::Edge
|
|||||||
// sort into blocks of edges with same source + target
|
// 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 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
|
// 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) {
|
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) <
|
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::tie(rhs.source, rhs.target, lhs.data.forward, rhs.data.weight);
|
||||||
});
|
});
|
||||||
@@ -77,10 +80,11 @@ std::vector<OutputEdgeT> prepareEdgesForUsageInGraph(std::vector<extractor::Edge
|
|||||||
const NodeID source = begin_interval->source;
|
const NodeID source = begin_interval->source;
|
||||||
const NodeID target = begin_interval->target;
|
const NodeID target = begin_interval->target;
|
||||||
|
|
||||||
auto end_interval =
|
auto end_interval = std::find_if_not(
|
||||||
std::find_if_not(begin_interval, edges.end(), [source, target](const auto &edge) {
|
begin_interval,
|
||||||
return std::tie(edge.source, edge.target) == std::tie(source, target);
|
edges.end(),
|
||||||
});
|
[source, target](const auto &edge)
|
||||||
|
{ return std::tie(edge.source, edge.target) == std::tie(source, target); });
|
||||||
BOOST_ASSERT(begin_interval != end_interval);
|
BOOST_ASSERT(begin_interval != end_interval);
|
||||||
|
|
||||||
// remove eigenloops
|
// remove eigenloops
|
||||||
@@ -144,7 +148,8 @@ graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
|
|||||||
auto max_turn_id = tbb::parallel_reduce(
|
auto max_turn_id = tbb::parallel_reduce(
|
||||||
range,
|
range,
|
||||||
NodeID{0},
|
NodeID{0},
|
||||||
[&edge_based_graph](const auto range, NodeID initial) {
|
[&edge_based_graph](const auto range, NodeID initial)
|
||||||
|
{
|
||||||
NodeID max_turn_id = initial;
|
NodeID max_turn_id = initial;
|
||||||
for (auto node = range.begin(); node < range.end(); ++node)
|
for (auto node = range.begin(); node < range.end(); ++node)
|
||||||
{
|
{
|
||||||
@@ -159,7 +164,10 @@ graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
|
|||||||
[](const NodeID lhs, const NodeID rhs) { return std::max(lhs, rhs); });
|
[](const NodeID lhs, const NodeID rhs) { return std::max(lhs, rhs); });
|
||||||
|
|
||||||
std::vector<extractor::EdgeBasedEdge> edges(max_turn_id + 1);
|
std::vector<extractor::EdgeBasedEdge> edges(max_turn_id + 1);
|
||||||
tbb::parallel_for(range, [&](const auto range) {
|
tbb::parallel_for(
|
||||||
|
range,
|
||||||
|
[&](const auto range)
|
||||||
|
{
|
||||||
for (auto node = range.begin(); node < range.end(); ++node)
|
for (auto node = range.begin(); node < range.end(); ++node)
|
||||||
{
|
{
|
||||||
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
|
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
|
||||||
|
|||||||
@@ -159,10 +159,11 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
|||||||
auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
|
auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
|
||||||
{
|
{
|
||||||
std::vector<LevelID> highest_border_level(edges.size());
|
std::vector<LevelID> highest_border_level(edges.size());
|
||||||
std::transform(
|
std::transform(edges.begin(),
|
||||||
edges.begin(), edges.end(), highest_border_level.begin(), [&mlp](const auto &edge) {
|
edges.end(),
|
||||||
return mlp.GetHighestDifferentLevel(edge.source, edge.target);
|
highest_border_level.begin(),
|
||||||
});
|
[&mlp](const auto &edge)
|
||||||
|
{ return mlp.GetHighestDifferentLevel(edge.source, edge.target); });
|
||||||
return highest_border_level;
|
return highest_border_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +176,8 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
|||||||
tbb::parallel_sort(
|
tbb::parallel_sort(
|
||||||
permutation.begin(),
|
permutation.begin(),
|
||||||
permutation.end(),
|
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
|
// sort by source node and then by level in ascending order
|
||||||
return std::tie(edges[lhs].source, highest_border_level[lhs], edges[lhs].target) <
|
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);
|
std::tie(edges[rhs].source, highest_border_level[rhs], edges[rhs].target);
|
||||||
@@ -201,8 +203,9 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
|||||||
auto level_begin = iter;
|
auto level_begin = iter;
|
||||||
for (auto level : util::irange<LevelID>(0, mlp.GetNumberOfLevels()))
|
for (auto level : util::irange<LevelID>(0, mlp.GetNumberOfLevels()))
|
||||||
{
|
{
|
||||||
iter = std::find_if(
|
iter = std::find_if(iter,
|
||||||
iter, edge_and_level_end, [node, level](const auto &edge_and_level) {
|
edge_and_level_end,
|
||||||
|
[node, level](const auto &edge_and_level) {
|
||||||
return boost::get<0>(edge_and_level).source != node ||
|
return boost::get<0>(edge_and_level).source != node ||
|
||||||
boost::get<1>(edge_and_level) != level;
|
boost::get<1>(edge_and_level) != level;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
|||||||
auto lidx = 0UL;
|
auto lidx = 0UL;
|
||||||
util::for_each_pair(level_offsets.begin(),
|
util::for_each_pair(level_offsets.begin(),
|
||||||
level_offsets.begin() + num_level,
|
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.
|
// create mask that has `bits` ones at its LSBs.
|
||||||
// 000011
|
// 000011
|
||||||
BOOST_ASSERT(offset <= NUM_PARTITION_BITS);
|
BOOST_ASSERT(offset <= NUM_PARTITION_BITS);
|
||||||
@@ -274,9 +275,8 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
|||||||
{
|
{
|
||||||
std::stable_sort(permutation.begin(),
|
std::stable_sort(permutation.begin(),
|
||||||
permutation.end(),
|
permutation.end(),
|
||||||
[&partition](const auto lhs, const auto rhs) {
|
[&partition](const auto lhs, const auto rhs)
|
||||||
return partition[lhs] < partition[rhs];
|
{ return partition[lhs] < partition[rhs]; });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// top down assign new cell ids
|
// top down assign new cell ids
|
||||||
|
|||||||
@@ -59,8 +59,10 @@ std::size_t removeUnconnectedBoundaryNodes(const GraphT &edge_based_graph,
|
|||||||
|
|
||||||
if (level_index < static_cast<int>(partitions.size() - 1))
|
if (level_index < static_cast<int>(partitions.size() - 1))
|
||||||
{
|
{
|
||||||
auto new_end = std::remove_if(
|
auto new_end =
|
||||||
witnesses.begin(), witnesses.end(), [&](const auto &witness) {
|
std::remove_if(witnesses.begin(),
|
||||||
|
witnesses.end(),
|
||||||
|
[&](const auto &witness) {
|
||||||
return partitions[level_index + 1][node] !=
|
return partitions[level_index + 1][node] !=
|
||||||
partitions[level_index + 1][witness.id];
|
partitions[level_index + 1][witness.id];
|
||||||
});
|
});
|
||||||
@@ -87,8 +89,10 @@ std::size_t removeUnconnectedBoundaryNodes(const GraphT &edge_based_graph,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto best_witness = std::min_element(
|
auto best_witness =
|
||||||
witnesses.begin(), witnesses.end(), [](const auto &lhs, const auto &rhs) {
|
std::min_element(witnesses.begin(),
|
||||||
|
witnesses.end(),
|
||||||
|
[](const auto &lhs, const auto &rhs) {
|
||||||
return lhs.induced_border_edges < rhs.induced_border_edges;
|
return lhs.induced_border_edges < rhs.induced_border_edges;
|
||||||
});
|
});
|
||||||
BOOST_ASSERT(best_witness != witnesses.end());
|
BOOST_ASSERT(best_witness != witnesses.end());
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ void reorderFirstLast(RandomIt first, RandomIt last, std::size_t n, Comparator c
|
|||||||
// requirements.
|
// requirements.
|
||||||
std::reverse_iterator<RandomIt> rfirst{last}, rlast{first + n};
|
std::reverse_iterator<RandomIt> rfirst{last}, rlast{first + n};
|
||||||
|
|
||||||
const auto flipped = [](auto fn) {
|
const auto flipped = [](auto fn)
|
||||||
return [fn](auto &&lhs, auto &&rhs) {
|
{
|
||||||
return fn(std::forward<decltype(lhs)>(rhs), std::forward<decltype(rhs)>(lhs));
|
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));
|
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)
|
: BaseParametersGrammar::base_type(root_rule)
|
||||||
{
|
{
|
||||||
const auto add_hint = [](engine::api::BaseParameters &base_parameters,
|
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())
|
if (!hint_strings.empty())
|
||||||
{
|
{
|
||||||
std::vector<engine::SegmentHint> location_hints(hint_strings.size());
|
std::vector<engine::SegmentHint> location_hints(hint_strings.size());
|
||||||
std::transform(hint_strings.begin(),
|
std::transform(hint_strings.begin(),
|
||||||
hint_strings.end(),
|
hint_strings.end(),
|
||||||
location_hints.begin(),
|
location_hints.begin(),
|
||||||
[](const auto &hint_string) {
|
[](const auto &hint_string)
|
||||||
return engine::SegmentHint::FromBase64(hint_string);
|
{ return engine::SegmentHint::FromBase64(hint_string); });
|
||||||
});
|
|
||||||
base_parameters.hints.push_back(engine::Hint{std::move(location_hints)});
|
base_parameters.hints.push_back(engine::Hint{std::move(location_hints)});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -94,7 +94,8 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
|
|
||||||
const auto add_bearing =
|
const auto add_bearing =
|
||||||
[](engine::api::BaseParameters &base_parameters,
|
[](engine::api::BaseParameters &base_parameters,
|
||||||
boost::optional<boost::fusion::vector2<short, short>> bearing_range) {
|
boost::optional<boost::fusion::vector2<short, short>> bearing_range)
|
||||||
|
{
|
||||||
boost::optional<engine::Bearing> bearing;
|
boost::optional<engine::Bearing> bearing;
|
||||||
if (bearing_range)
|
if (bearing_range)
|
||||||
{
|
{
|
||||||
@@ -118,7 +119,8 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
|
|
||||||
location_rule = (double_ > qi::lit(',') >
|
location_rule = (double_ > qi::lit(',') >
|
||||||
double_)[qi::_val = ph::bind(
|
double_)[qi::_val = ph::bind(
|
||||||
[](double lon, double lat) {
|
[](double lon, double lat)
|
||||||
|
{
|
||||||
return util::Coordinate(
|
return util::Coordinate(
|
||||||
util::toFixed(util::UnsafeFloatLongitude{lon}),
|
util::toFixed(util::UnsafeFloatLongitude{lon}),
|
||||||
util::toFixed(util::UnsafeFloatLatitude{lat}));
|
util::toFixed(util::UnsafeFloatLatitude{lat}));
|
||||||
@@ -126,18 +128,16 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
qi::_1,
|
qi::_1,
|
||||||
qi::_2)];
|
qi::_2)];
|
||||||
|
|
||||||
polyline_rule = qi::as_string[qi::lit("polyline(") > +polyline_chars > ')']
|
polyline_rule =
|
||||||
[qi::_val = ph::bind(
|
qi::as_string[qi::lit("polyline(") > +polyline_chars > ')']
|
||||||
[](const std::string &polyline) {
|
[qi::_val = ph::bind([](const std::string &polyline)
|
||||||
return engine::decodePolyline(polyline);
|
{ return engine::decodePolyline(polyline); },
|
||||||
},
|
|
||||||
qi::_1)];
|
qi::_1)];
|
||||||
|
|
||||||
polyline6_rule = qi::as_string[qi::lit("polyline6(") > +polyline_chars > ')']
|
polyline6_rule =
|
||||||
[qi::_val = ph::bind(
|
qi::as_string[qi::lit("polyline6(") > +polyline_chars > ')']
|
||||||
[](const std::string &polyline) {
|
[qi::_val = ph::bind([](const std::string &polyline)
|
||||||
return engine::decodePolyline<1000000>(polyline);
|
{ return engine::decodePolyline<1000000>(polyline); },
|
||||||
},
|
|
||||||
qi::_1)];
|
qi::_1)];
|
||||||
|
|
||||||
query_rule =
|
query_rule =
|
||||||
|
|||||||
@@ -54,8 +54,9 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
|||||||
#endif
|
#endif
|
||||||
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
|
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
|
||||||
|
|
||||||
const auto add_annotation = [](engine::api::RouteParameters &route_parameters,
|
const auto add_annotation =
|
||||||
AnnotationsType route_param) {
|
[](engine::api::RouteParameters &route_parameters, AnnotationsType route_param)
|
||||||
|
{
|
||||||
route_parameters.annotations_type = route_parameters.annotations_type | route_param;
|
route_parameters.annotations_type = route_parameters.annotations_type | route_param;
|
||||||
route_parameters.annotations =
|
route_parameters.annotations =
|
||||||
route_parameters.annotations_type != AnnotationsType::None;
|
route_parameters.annotations_type != AnnotationsType::None;
|
||||||
|
|||||||
@@ -14,18 +14,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#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
|
namespace osrm::server
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ void readBoolVector(tar::FileReader &reader, const std::string &name, VectorT &d
|
|||||||
using BlockType = std::uint64_t;
|
using BlockType = std::uint64_t;
|
||||||
constexpr std::uint64_t BLOCK_BITS = CHAR_BIT * sizeof(BlockType);
|
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);
|
auto read_size = std::min<std::size_t>(count - index, BLOCK_BITS);
|
||||||
unpackBits<VectorT, BlockType>(data, index, read_size, block);
|
unpackBits<VectorT, BlockType>(data, index, read_size, block);
|
||||||
index += BLOCK_BITS;
|
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
|
// FIXME on old boost version the function_input_iterator does not work with lambdas
|
||||||
// so we need to wrap it in a function here.
|
// 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 write_size = std::min<std::size_t>(count - index, BLOCK_BITS);
|
||||||
auto packed = packBits<VectorT, BlockType>(data, index, write_size);
|
auto packed = packBits<VectorT, BlockType>(data, index, write_size);
|
||||||
index += BLOCK_BITS;
|
index += BLOCK_BITS;
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ class SharedDataIndex
|
|||||||
// Build mapping from block name to region
|
// Build mapping from block name to region
|
||||||
for (auto index : util::irange<std::uint32_t>(0, regions.size()))
|
for (auto index : util::irange<std::uint32_t>(0, regions.size()))
|
||||||
{
|
{
|
||||||
regions[index].layout->List("",
|
regions[index].layout->List(
|
||||||
boost::make_function_output_iterator([&](const auto &name) {
|
"",
|
||||||
block_to_region[name] = index;
|
boost::make_function_output_iterator([&](const auto &name)
|
||||||
}));
|
{ block_to_region[name] = index; }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,10 @@ struct SharedRegionRegister
|
|||||||
// Returns the key of the region with the given name
|
// Returns the key of the region with the given name
|
||||||
RegionID Find(const std::string &name) const
|
RegionID Find(const std::string &name) const
|
||||||
{
|
{
|
||||||
auto iter = std::find_if(regions.begin(), regions.end(), [&](const auto ®ion) {
|
auto iter = std::find_if(
|
||||||
|
regions.begin(),
|
||||||
|
regions.end(),
|
||||||
|
[&](const auto ®ion) {
|
||||||
return std::strncmp(region.name, name.c_str(), SharedRegion::MAX_NAME_LENGTH) == 0;
|
return std::strncmp(region.name, name.c_str(), SharedRegion::MAX_NAME_LENGTH) == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ class SharedMemory
|
|||||||
{
|
{
|
||||||
auto shmid = shm.get_shmid();
|
auto shmid = shm.get_shmid();
|
||||||
::shmid_ds xsi_ds;
|
::shmid_ds xsi_ds;
|
||||||
const auto errorToMessage = [](int error) -> std::string {
|
const auto errorToMessage = [](int error) -> std::string
|
||||||
|
{
|
||||||
switch (error)
|
switch (error)
|
||||||
{
|
{
|
||||||
case EPERM:
|
case EPERM:
|
||||||
|
|||||||
@@ -241,9 +241,9 @@ inline auto make_contracted_metric_view(const SharedDataIndex &index, const std:
|
|||||||
|
|
||||||
std::vector<util::vector_view<bool>> edge_filter;
|
std::vector<util::vector_view<bool>> edge_filter;
|
||||||
index.List(name + "/exclude",
|
index.List(name + "/exclude",
|
||||||
boost::make_function_output_iterator([&](const auto &filter_name) {
|
boost::make_function_output_iterator(
|
||||||
edge_filter.push_back(make_vector_view<bool>(index, filter_name));
|
[&](const auto &filter_name)
|
||||||
}));
|
{ edge_filter.push_back(make_vector_view<bool>(index, filter_name)); }));
|
||||||
|
|
||||||
return contractor::ContractedMetricView{{node_list, edge_list}, std::move(edge_filter)};
|
return contractor::ContractedMetricView{{node_list, edge_list}, std::move(edge_filter)};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,17 @@ template <typename Key, typename Value> struct CSVFilesParser
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operator returns a lambda function that maps input Key to boost::optional<Value>.
|
// Operator returns a lambda function that maps input Key to std::optional<Value>.
|
||||||
auto operator()(const std::vector<std::string> &csv_filenames) const
|
auto operator()(const std::vector<std::string> &csv_filenames) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tbb::spin_mutex mutex;
|
tbb::spin_mutex mutex;
|
||||||
std::vector<std::pair<Key, Value>> lookup;
|
std::vector<std::pair<Key, Value>> lookup;
|
||||||
tbb::parallel_for(std::size_t{0}, csv_filenames.size(), [&](const std::size_t idx) {
|
tbb::parallel_for(std::size_t{0},
|
||||||
|
csv_filenames.size(),
|
||||||
|
[&](const std::size_t idx)
|
||||||
|
{
|
||||||
auto local = ParseCSVFile(csv_filenames[idx], start_index + idx);
|
auto local = ParseCSVFile(csv_filenames[idx], start_index + idx);
|
||||||
|
|
||||||
{ // Merge local CSV results into a flat global vector
|
{ // Merge local CSV results into a flat global vector
|
||||||
@@ -61,16 +64,18 @@ template <typename Key, typename Value> struct CSVFilesParser
|
|||||||
// and unique them on key to keep only the value with the largest file index
|
// and unique them on key to keep only the value with the largest file index
|
||||||
// and the largest line number in a file.
|
// and the largest line number in a file.
|
||||||
// The operands order is swapped to make descending ordering on (key, source)
|
// The operands order is swapped to make descending ordering on (key, source)
|
||||||
tbb::parallel_sort(begin(lookup), end(lookup), [](const auto &lhs, const auto &rhs) {
|
tbb::parallel_sort(begin(lookup),
|
||||||
|
end(lookup),
|
||||||
|
[](const auto &lhs, const auto &rhs) {
|
||||||
return std::tie(rhs.first, rhs.second.source) <
|
return std::tie(rhs.first, rhs.second.source) <
|
||||||
std::tie(lhs.first, lhs.second.source);
|
std::tie(lhs.first, lhs.second.source);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Unique only on key to take the source precedence into account and remove duplicates.
|
// Unique only on key to take the source precedence into account and remove duplicates.
|
||||||
const auto it =
|
const auto it = std::unique(begin(lookup),
|
||||||
std::unique(begin(lookup), end(lookup), [](const auto &lhs, const auto &rhs) {
|
end(lookup),
|
||||||
return lhs.first == rhs.first;
|
[](const auto &lhs, const auto &rhs)
|
||||||
});
|
{ return lhs.first == rhs.first; });
|
||||||
lookup.erase(it, end(lookup));
|
lookup.erase(it, end(lookup));
|
||||||
|
|
||||||
util::Log() << "In total loaded " << csv_filenames.size() << " file(s) with a total of "
|
util::Log() << "In total loaded " << csv_filenames.size() << " file(s) with a total of "
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm::updater
|
namespace osrm::updater
|
||||||
@@ -12,13 +11,14 @@ namespace osrm::updater
|
|||||||
|
|
||||||
template <typename Key, typename Value> struct LookupTable
|
template <typename Key, typename Value> struct LookupTable
|
||||||
{
|
{
|
||||||
boost::optional<Value> operator()(const Key &key) const
|
std::optional<Value> operator()(const Key &key) const
|
||||||
{
|
{
|
||||||
using Result = boost::optional<Value>;
|
using Result = std::optional<Value>;
|
||||||
const auto it = std::lower_bound(
|
const auto it =
|
||||||
lookup.begin(), lookup.end(), key, [](const auto &lhs, const auto &rhs) {
|
std::lower_bound(lookup.begin(),
|
||||||
return rhs < lhs.first;
|
lookup.end(),
|
||||||
});
|
key,
|
||||||
|
[](const auto &lhs, const auto &rhs) { return rhs < lhs.first; });
|
||||||
return it != std::end(lookup) && !(it->first < key) ? Result(it->second) : Result();
|
return it != std::end(lookup) && !(it->first < key) ? Result(it->second) : Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ struct SpeedSource final
|
|||||||
{
|
{
|
||||||
SpeedSource() : speed(0.), rate() {}
|
SpeedSource() : speed(0.), rate() {}
|
||||||
double speed;
|
double speed;
|
||||||
boost::optional<double> rate;
|
std::optional<double> rate;
|
||||||
std::uint8_t source;
|
std::uint8_t source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
|
|
||||||
#include <boost/math/constants/constants.hpp>
|
#include <boost/math/constants/constants.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -36,6 +36,13 @@ inline double radToDeg(const double radian)
|
|||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
const constexpr static double METERS_PER_DEGREE_LAT = 110567.0;
|
||||||
|
|
||||||
|
inline double metersPerLngDegree(const FixedLatitude lat)
|
||||||
|
{
|
||||||
|
return std::cos(detail::degToRad(static_cast<double>(toFloating(lat)))) * METERS_PER_DEGREE_LAT;
|
||||||
|
}
|
||||||
|
|
||||||
//! Takes the squared euclidean distance of the input coordinates. Does not return meters!
|
//! Takes the squared euclidean distance of the input coordinates. Does not return meters!
|
||||||
std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs);
|
std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs);
|
||||||
|
|
||||||
@@ -102,7 +109,7 @@ double bearing(const Coordinate first_coordinate, const Coordinate second_coordi
|
|||||||
double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third);
|
double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third);
|
||||||
|
|
||||||
// find the center of a circle through three coordinates
|
// find the center of a circle through three coordinates
|
||||||
boost::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
|
std::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
|
||||||
const Coordinate second_coordinate,
|
const Coordinate second_coordinate,
|
||||||
const Coordinate third_coordinate);
|
const Coordinate third_coordinate);
|
||||||
|
|
||||||
@@ -179,7 +186,8 @@ template <class BinaryOperation, typename iterator_type>
|
|||||||
double getLength(iterator_type begin, const iterator_type end, BinaryOperation op)
|
double getLength(iterator_type begin, const iterator_type end, BinaryOperation op)
|
||||||
{
|
{
|
||||||
double result = 0;
|
double result = 0;
|
||||||
const auto functor = [&result, op](const Coordinate lhs, const Coordinate rhs) {
|
const auto functor = [&result, op](const Coordinate lhs, const Coordinate rhs)
|
||||||
|
{
|
||||||
result += op(lhs, rhs);
|
result += op(lhs, rhs);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -197,8 +205,9 @@ findClosestDistance(const Coordinate coordinate, const iterator_type begin, cons
|
|||||||
double current_min = std::numeric_limits<double>::max();
|
double current_min = std::numeric_limits<double>::max();
|
||||||
|
|
||||||
// comparator updating current_min without ever finding an element
|
// comparator updating current_min without ever finding an element
|
||||||
const auto compute_minimum_distance = [¤t_min, coordinate](const Coordinate lhs,
|
const auto compute_minimum_distance =
|
||||||
const Coordinate rhs) {
|
[¤t_min, coordinate](const Coordinate lhs, const Coordinate rhs)
|
||||||
|
{
|
||||||
current_min = std::min(current_min, findClosestDistance(coordinate, lhs, rhs));
|
current_min = std::min(current_min, findClosestDistance(coordinate, lhs, rhs));
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -216,8 +225,9 @@ double findClosestDistance(const iterator_type lhs_begin,
|
|||||||
{
|
{
|
||||||
double current_min = std::numeric_limits<double>::max();
|
double current_min = std::numeric_limits<double>::max();
|
||||||
|
|
||||||
const auto compute_minimum_distance_in_rhs = [¤t_min, rhs_begin, rhs_end](
|
const auto compute_minimum_distance_in_rhs =
|
||||||
const Coordinate coordinate) {
|
[¤t_min, rhs_begin, rhs_end](const Coordinate coordinate)
|
||||||
|
{
|
||||||
current_min = std::min(current_min, findClosestDistance(coordinate, rhs_begin, rhs_end));
|
current_min = std::min(current_min, findClosestDistance(coordinate, rhs_begin, rhs_end));
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -233,13 +243,11 @@ std::pair<Coordinate, Coordinate> leastSquareRegression(const iterator_type begi
|
|||||||
// following the formulas of https://faculty.elgin.edu/dkernler/statistics/ch04/4-2.html
|
// following the formulas of https://faculty.elgin.edu/dkernler/statistics/ch04/4-2.html
|
||||||
const auto number_of_coordinates = std::distance(begin, end);
|
const auto number_of_coordinates = std::distance(begin, end);
|
||||||
BOOST_ASSERT(number_of_coordinates >= 2);
|
BOOST_ASSERT(number_of_coordinates >= 2);
|
||||||
const auto extract_lon = [](const Coordinate coordinate) {
|
const auto extract_lon = [](const Coordinate coordinate)
|
||||||
return static_cast<double>(toFloating(coordinate.lon));
|
{ return static_cast<double>(toFloating(coordinate.lon)); };
|
||||||
};
|
|
||||||
|
|
||||||
const auto extract_lat = [](const Coordinate coordinate) {
|
const auto extract_lat = [](const Coordinate coordinate)
|
||||||
return static_cast<double>(toFloating(coordinate.lat));
|
{ return static_cast<double>(toFloating(coordinate.lat)); };
|
||||||
};
|
|
||||||
|
|
||||||
double min_lon = extract_lon(*begin);
|
double min_lon = extract_lon(*begin);
|
||||||
double max_lon = extract_lon(*begin);
|
double max_lon = extract_lon(*begin);
|
||||||
@@ -262,19 +270,21 @@ std::pair<Coordinate, Coordinate> leastSquareRegression(const iterator_type begi
|
|||||||
{
|
{
|
||||||
std::vector<util::Coordinate> rotated_coordinates(number_of_coordinates);
|
std::vector<util::Coordinate> rotated_coordinates(number_of_coordinates);
|
||||||
// rotate all coordinates to the right
|
// rotate all coordinates to the right
|
||||||
std::transform(begin, end, rotated_coordinates.begin(), [](const auto coordinate) {
|
std::transform(begin,
|
||||||
return rotateCCWAroundZero(coordinate, detail::degToRad(-90));
|
end,
|
||||||
});
|
rotated_coordinates.begin(),
|
||||||
|
[](const auto coordinate)
|
||||||
|
{ return rotateCCWAroundZero(coordinate, detail::degToRad(-90)); });
|
||||||
const auto rotated_regression =
|
const auto rotated_regression =
|
||||||
leastSquareRegression(rotated_coordinates.begin(), rotated_coordinates.end());
|
leastSquareRegression(rotated_coordinates.begin(), rotated_coordinates.end());
|
||||||
return {rotateCCWAroundZero(rotated_regression.first, detail::degToRad(90)),
|
return {rotateCCWAroundZero(rotated_regression.first, detail::degToRad(90)),
|
||||||
rotateCCWAroundZero(rotated_regression.second, detail::degToRad(90))};
|
rotateCCWAroundZero(rotated_regression.second, detail::degToRad(90))};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto make_accumulate = [](const auto extraction_function) {
|
const auto make_accumulate = [](const auto extraction_function)
|
||||||
return [extraction_function](const double sum_so_far, const Coordinate coordinate) {
|
{
|
||||||
return sum_so_far + extraction_function(coordinate);
|
return [extraction_function](const double sum_so_far, const Coordinate coordinate)
|
||||||
};
|
{ return sum_so_far + extraction_function(coordinate); };
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto accumulated_lon = std::accumulate(begin, end, 0., make_accumulate(extract_lon));
|
const auto accumulated_lon = std::accumulate(begin, end, 0., make_accumulate(extract_lon));
|
||||||
@@ -283,8 +293,10 @@ std::pair<Coordinate, Coordinate> leastSquareRegression(const iterator_type begi
|
|||||||
|
|
||||||
const auto mean_lon = accumulated_lon / number_of_coordinates;
|
const auto mean_lon = accumulated_lon / number_of_coordinates;
|
||||||
const auto mean_lat = accumulated_lat / number_of_coordinates;
|
const auto mean_lat = accumulated_lat / number_of_coordinates;
|
||||||
const auto make_variance = [](const auto mean, const auto extraction_function) {
|
const auto make_variance = [](const auto mean, const auto extraction_function)
|
||||||
return [extraction_function, mean](const double sum_so_far, const Coordinate coordinate) {
|
{
|
||||||
|
return [extraction_function, mean](const double sum_so_far, const Coordinate coordinate)
|
||||||
|
{
|
||||||
const auto difference = extraction_function(coordinate) - mean;
|
const auto difference = extraction_function(coordinate) - mean;
|
||||||
return sum_so_far + difference * difference;
|
return sum_so_far + difference * difference;
|
||||||
};
|
};
|
||||||
@@ -312,7 +324,8 @@ std::pair<Coordinate, Coordinate> leastSquareRegression(const iterator_type begi
|
|||||||
std::accumulate(begin,
|
std::accumulate(begin,
|
||||||
end,
|
end,
|
||||||
0.,
|
0.,
|
||||||
[&](const auto sum_so_far, const auto current_coordinate) {
|
[&](const auto sum_so_far, const auto current_coordinate)
|
||||||
|
{
|
||||||
return sum_so_far + (extract_lon(current_coordinate) - mean_lon) *
|
return sum_so_far + (extract_lon(current_coordinate) - mean_lon) *
|
||||||
(extract_lat(current_coordinate) - mean_lat) /
|
(extract_lat(current_coordinate) - mean_lat) /
|
||||||
(sample_variance_lon * sample_variance_lat);
|
(sample_variance_lon * sample_variance_lat);
|
||||||
@@ -323,9 +336,8 @@ std::pair<Coordinate, Coordinate> leastSquareRegression(const iterator_type begi
|
|||||||
const auto intercept = mean_lat - slope * mean_lon;
|
const auto intercept = mean_lat - slope * mean_lon;
|
||||||
|
|
||||||
const auto GetLatAtLon = [intercept,
|
const auto GetLatAtLon = [intercept,
|
||||||
slope](const util::FloatLongitude longitude) -> util::FloatLatitude {
|
slope](const util::FloatLongitude longitude) -> util::FloatLatitude
|
||||||
return {intercept + slope * static_cast<double>((longitude))};
|
{ return {intercept + slope * static_cast<double>((longitude))}; };
|
||||||
};
|
|
||||||
|
|
||||||
const double offset = 0.00001;
|
const double offset = 0.00001;
|
||||||
const Coordinate regression_first = {
|
const Coordinate regression_first = {
|
||||||
@@ -359,7 +371,8 @@ bool areParallel(const iterator_type lhs_begin,
|
|||||||
const auto rotation_angle_radians = detail::degToRad(bearing_lhs - 90);
|
const auto rotation_angle_radians = detail::degToRad(bearing_lhs - 90);
|
||||||
const auto rotated_difference_rhs = rotateCCWAroundZero(difference_rhs, rotation_angle_radians);
|
const auto rotated_difference_rhs = rotateCCWAroundZero(difference_rhs, rotation_angle_radians);
|
||||||
|
|
||||||
const auto get_slope = [](const Coordinate from, const Coordinate to) {
|
const auto get_slope = [](const Coordinate from, const Coordinate to)
|
||||||
|
{
|
||||||
const auto diff_lat = static_cast<int>(from.lat) - static_cast<int>(to.lat);
|
const auto diff_lat = static_cast<int>(from.lat) - static_cast<int>(to.lat);
|
||||||
const auto diff_lon = static_cast<int>(from.lon) - static_cast<int>(to.lon);
|
const auto diff_lon = static_cast<int>(from.lon) - static_cast<int>(to.lon);
|
||||||
if (diff_lon == 0)
|
if (diff_lon == 0)
|
||||||
|
|||||||
@@ -189,8 +189,11 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
other.node_array.resize(node_array.size());
|
other.node_array.resize(node_array.size());
|
||||||
|
|
||||||
NodeID node_id = 0;
|
NodeID node_id = 0;
|
||||||
std::transform(
|
std::transform(node_array.begin(),
|
||||||
node_array.begin(), node_array.end(), other.node_array.begin(), [&](const Node &node) {
|
node_array.end(),
|
||||||
|
other.node_array.begin(),
|
||||||
|
[&](const Node &node)
|
||||||
|
{
|
||||||
const EdgeIterator first_edge = other.edge_list.size();
|
const EdgeIterator first_edge = other.edge_list.size();
|
||||||
|
|
||||||
BOOST_ASSERT(node_id < number_of_nodes);
|
BOOST_ASSERT(node_id < number_of_nodes);
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ class FilteredGraphImpl<util::StaticGraph<EdgeDataT, Ownership>, Ownership>
|
|||||||
unsigned GetOutDegree(const NodeIterator n) const
|
unsigned GetOutDegree(const NodeIterator n) const
|
||||||
{
|
{
|
||||||
auto range = graph.GetAdjacentEdgeRange(n);
|
auto range = graph.GetAdjacentEdgeRange(n);
|
||||||
return std::count_if(range.begin(), range.end(), [this](const EdgeIterator edge) {
|
return std::count_if(range.begin(),
|
||||||
return edge_filter[edge];
|
range.end(),
|
||||||
});
|
[this](const EdgeIterator edge) { return edge_filter[edge]; });
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NodeIterator GetTarget(const EdgeIterator e) const
|
inline NodeIterator GetTarget(const EdgeIterator e) const
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef OSRM_GEOJSON_DEBUG_POLICIES
|
#ifndef OSRM_GEOJSON_DEBUG_POLICIES
|
||||||
#define OSRM_GEOJSON_DEBUG_POLICIES
|
#define OSRM_GEOJSON_DEBUG_POLICIES
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
@@ -9,8 +10,6 @@
|
|||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace osrm::util
|
namespace osrm::util
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -20,7 +19,7 @@ struct NodeIdVectorToLineString
|
|||||||
|
|
||||||
// converts a vector of node ids into a linestring geojson feature
|
// converts a vector of node ids into a linestring geojson feature
|
||||||
util::json::Object operator()(const std::vector<NodeID> &node_ids,
|
util::json::Object operator()(const std::vector<NodeID> &node_ids,
|
||||||
const boost::optional<json::Object> &properties = {}) const;
|
const std::optional<json::Object> &properties = {}) const;
|
||||||
|
|
||||||
const std::vector<util::Coordinate> &node_coordinates;
|
const std::vector<util::Coordinate> &node_coordinates;
|
||||||
};
|
};
|
||||||
@@ -29,7 +28,7 @@ struct CoordinateVectorToLineString
|
|||||||
{
|
{
|
||||||
// converts a vector of node ids into a linestring geojson feature
|
// converts a vector of node ids into a linestring geojson feature
|
||||||
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
|
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
|
||||||
const boost::optional<json::Object> &properties = {}) const;
|
const std::optional<json::Object> &properties = {}) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NodeIdVectorToMultiPoint
|
struct NodeIdVectorToMultiPoint
|
||||||
@@ -38,7 +37,7 @@ struct NodeIdVectorToMultiPoint
|
|||||||
|
|
||||||
// converts a vector of node ids into a linestring geojson feature
|
// converts a vector of node ids into a linestring geojson feature
|
||||||
util::json::Object operator()(const std::vector<NodeID> &node_ids,
|
util::json::Object operator()(const std::vector<NodeID> &node_ids,
|
||||||
const boost::optional<json::Object> &properties = {}) const;
|
const std::optional<json::Object> &properties = {}) const;
|
||||||
|
|
||||||
const std::vector<util::Coordinate> &node_coordinates;
|
const std::vector<util::Coordinate> &node_coordinates;
|
||||||
};
|
};
|
||||||
@@ -47,7 +46,7 @@ struct CoordinateVectorToMultiPoint
|
|||||||
{
|
{
|
||||||
// converts a vector of node ids into a linestring geojson feature
|
// converts a vector of node ids into a linestring geojson feature
|
||||||
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
|
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
|
||||||
const boost::optional<json::Object> &properties = {}) const;
|
const std::optional<json::Object> &properties = {}) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace osrm::util
|
} // namespace osrm::util
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace osrm::util
|
namespace osrm::util
|
||||||
{
|
{
|
||||||
@@ -84,7 +83,7 @@ struct NodeIdToCoordinate
|
|||||||
|
|
||||||
inline util::json::Object makeFeature(std::string type,
|
inline util::json::Object makeFeature(std::string type,
|
||||||
util::json::Array coordinates,
|
util::json::Array coordinates,
|
||||||
const boost::optional<util::json::Object> &properties = {})
|
const std::optional<util::json::Object> &properties = {})
|
||||||
{
|
{
|
||||||
util::json::Object result;
|
util::json::Object result;
|
||||||
result.values["type"] = "Feature";
|
result.values["type"] = "Feature";
|
||||||
|
|||||||
@@ -63,14 +63,16 @@ template <typename StringView> inline auto decompose(const StringView &lhs, cons
|
|||||||
auto const lcs = longest_common_substring(lhs, rhs);
|
auto const lcs = longest_common_substring(lhs, rhs);
|
||||||
|
|
||||||
// trim spaces, transform to lower
|
// trim spaces, transform to lower
|
||||||
const auto trim = [](StringView view) {
|
const auto trim = [](StringView view)
|
||||||
|
{
|
||||||
// we compare suffixes based on this value, it might break UTF chars, but as long as we are
|
// we compare suffixes based on this value, it might break UTF chars, but as long as we are
|
||||||
// consistent in handling, we do not create bad results
|
// consistent in handling, we do not create bad results
|
||||||
std::string str;
|
std::string str;
|
||||||
str.reserve(view.size());
|
str.reserve(view.size());
|
||||||
std::transform(view.begin(), view.end(), std::back_inserter(str), [](unsigned char c) {
|
std::transform(view.begin(),
|
||||||
return std::tolower(c);
|
view.end(),
|
||||||
});
|
std::back_inserter(str),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
auto front = str.find_first_not_of(' ');
|
auto front = str.find_first_not_of(' ');
|
||||||
|
|
||||||
if (front == std::string::npos)
|
if (front == std::string::npos)
|
||||||
@@ -131,13 +133,13 @@ inline bool requiresNameAnnounced(const StringView &from_name,
|
|||||||
|
|
||||||
const auto checkForPrefixOrSuffixChange = [](const std::string_view first,
|
const auto checkForPrefixOrSuffixChange = [](const std::string_view first,
|
||||||
const std::string_view second,
|
const std::string_view second,
|
||||||
const SuffixTable &suffix_table) {
|
const SuffixTable &suffix_table)
|
||||||
|
{
|
||||||
std::string first_prefix, first_suffix, second_prefix, second_suffix;
|
std::string first_prefix, first_suffix, second_prefix, second_suffix;
|
||||||
std::tie(first_prefix, first_suffix, second_prefix, second_suffix) =
|
std::tie(first_prefix, first_suffix, second_prefix, second_suffix) =
|
||||||
decompose(first, second);
|
decompose(first, second);
|
||||||
const auto checkTable = [&](const std::string &str) {
|
const auto checkTable = [&](const std::string &str)
|
||||||
return str.empty() || suffix_table.isSuffix(str);
|
{ return str.empty() || suffix_table.isSuffix(str); };
|
||||||
};
|
|
||||||
|
|
||||||
return checkTable(first_prefix) && checkTable(first_suffix) && checkTable(second_prefix) &&
|
return checkTable(first_prefix) && checkTable(first_suffix) && checkTable(second_prefix) &&
|
||||||
checkTable(second_suffix);
|
checkTable(second_suffix);
|
||||||
|
|||||||
@@ -315,9 +315,8 @@ template <typename GroupBlockPolicy, storage::Ownership Ownership> struct Indexe
|
|||||||
values_byte_iter = block.WriteBlockPrefix(curr, next, values_byte_iter);
|
values_byte_iter = block.WriteBlockPrefix(curr, next, values_byte_iter);
|
||||||
std::advance(next, std::min<diff_type>(1, std::distance(next, sentinel)));
|
std::advance(next, std::min<diff_type>(1, std::distance(next, sentinel)));
|
||||||
|
|
||||||
auto to_bytes = [&](const auto &data) {
|
auto to_bytes = [&](const auto &data)
|
||||||
values_byte_iter = std::copy_n(&data, sizeof(ValueType), values_byte_iter);
|
{ values_byte_iter = std::copy_n(&data, sizeof(ValueType), values_byte_iter); };
|
||||||
};
|
|
||||||
std::copy(data + *curr,
|
std::copy(data + *curr,
|
||||||
data + *next,
|
data + *next,
|
||||||
boost::make_function_output_iterator(std::cref(to_bytes)));
|
boost::make_function_output_iterator(std::cref(to_bytes)));
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ class integer_iterator : public boost::iterator_facade<integer_iterator<Integer>
|
|||||||
|
|
||||||
difference_type distance_to(const integer_iterator &other) const
|
difference_type distance_to(const integer_iterator &other) const
|
||||||
{
|
{
|
||||||
return std::is_signed<value_type>::value
|
return std::is_signed<value_type>::value ? (other.m_value - m_value)
|
||||||
? (other.m_value - m_value)
|
|
||||||
: (other.m_value >= m_value)
|
: (other.m_value >= m_value)
|
||||||
? static_cast<difference_type>(other.m_value - m_value)
|
? static_cast<difference_type>(other.m_value - m_value)
|
||||||
: -static_cast<difference_type>(m_value - other.m_value);
|
: -static_cast<difference_type>(m_value - other.m_value);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ extern "C"
|
|||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <boost/filesystem/convenience.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
|
|||||||
auto edges_list = directedEdgesFromCompressed<NodeBasedDynamicGraph::InputEdge>(
|
auto edges_list = directedEdgesFromCompressed<NodeBasedDynamicGraph::InputEdge>(
|
||||||
input_edge_list,
|
input_edge_list,
|
||||||
[](NodeBasedDynamicGraph::InputEdge &output_edge,
|
[](NodeBasedDynamicGraph::InputEdge &output_edge,
|
||||||
const extractor::NodeBasedEdge &input_edge) {
|
const extractor::NodeBasedEdge &input_edge)
|
||||||
|
{
|
||||||
output_edge.data.weight = input_edge.weight;
|
output_edge.data.weight = input_edge.weight;
|
||||||
output_edge.data.duration = input_edge.duration;
|
output_edge.data.duration = input_edge.duration;
|
||||||
output_edge.data.distance = input_edge.distance;
|
output_edge.data.distance = input_edge.distance;
|
||||||
|
|||||||
@@ -193,23 +193,20 @@ struct OpeningHours
|
|||||||
&& (times.empty() ||
|
&& (times.empty() ||
|
||||||
std::any_of(times.begin(),
|
std::any_of(times.begin(),
|
||||||
times.end(),
|
times.end(),
|
||||||
[&time, &use_curr_day, &use_next_day](const auto &x) {
|
[&time, &use_curr_day, &use_next_day](const auto &x)
|
||||||
return x.IsInRange(time, use_curr_day, use_next_day);
|
{ return x.IsInRange(time, use_curr_day, use_next_day); }))
|
||||||
}))
|
|
||||||
// .. and if weekdays are not specified or matches weekdays range
|
// .. and if weekdays are not specified or matches weekdays range
|
||||||
&& (weekdays.empty() ||
|
&& (weekdays.empty() ||
|
||||||
std::any_of(weekdays.begin(),
|
std::any_of(weekdays.begin(),
|
||||||
weekdays.end(),
|
weekdays.end(),
|
||||||
[&time, use_curr_day, use_next_day](const auto &x) {
|
[&time, use_curr_day, use_next_day](const auto &x)
|
||||||
return x.IsInRange(time, use_curr_day, use_next_day);
|
{ return x.IsInRange(time, use_curr_day, use_next_day); }))
|
||||||
}))
|
|
||||||
// .. and if month-day ranges are not specified or is in any month-day range
|
// .. and if month-day ranges are not specified or is in any month-day range
|
||||||
&& (monthdays.empty() ||
|
&& (monthdays.empty() ||
|
||||||
std::any_of(monthdays.begin(),
|
std::any_of(monthdays.begin(),
|
||||||
monthdays.end(),
|
monthdays.end(),
|
||||||
[&time, use_curr_day, use_next_day](const auto &x) {
|
[&time, use_curr_day, use_next_day](const auto &x)
|
||||||
return x.IsInRange(time, use_curr_day, use_next_day);
|
{ return x.IsInRange(time, use_curr_day, use_next_day); }));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TimeSpan> times;
|
std::vector<TimeSpan> times;
|
||||||
|
|||||||
+10
-10
@@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/heap/d_ary_heap.hpp>
|
#include <boost/heap/d_ary_heap.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -290,26 +290,26 @@ class QueryHeap
|
|||||||
return inserted_nodes[index].node == node;
|
return inserted_nodes[index].node == node;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<HeapNode &> GetHeapNodeIfWasInserted(const NodeID node)
|
HeapNode *GetHeapNodeIfWasInserted(const NodeID node)
|
||||||
{
|
{
|
||||||
const auto index = node_index.peek_index(node);
|
const auto index = node_index.peek_index(node);
|
||||||
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
|
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
|
||||||
inserted_nodes[index].node != node)
|
inserted_nodes[index].node != node)
|
||||||
{
|
{
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
return inserted_nodes[index];
|
return &inserted_nodes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<const HeapNode &> GetHeapNodeIfWasInserted(const NodeID node) const
|
const HeapNode *GetHeapNodeIfWasInserted(const NodeID node) const
|
||||||
{
|
{
|
||||||
const auto index = node_index.peek_index(node);
|
const auto index = node_index.peek_index(node);
|
||||||
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
|
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
|
||||||
inserted_nodes[index].node != node)
|
inserted_nodes[index].node != node)
|
||||||
{
|
{
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
return inserted_nodes[index];
|
return &inserted_nodes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID Min() const
|
NodeID Min() const
|
||||||
@@ -345,9 +345,9 @@ class QueryHeap
|
|||||||
void DeleteAll()
|
void DeleteAll()
|
||||||
{
|
{
|
||||||
auto const none_handle = heap.s_handle_from_iterator(heap.end());
|
auto const none_handle = heap.s_handle_from_iterator(heap.end());
|
||||||
std::for_each(inserted_nodes.begin(), inserted_nodes.end(), [&none_handle](auto &node) {
|
std::for_each(inserted_nodes.begin(),
|
||||||
node.handle = none_handle;
|
inserted_nodes.end(),
|
||||||
});
|
[&none_handle](auto &node) { node.handle = none_handle; });
|
||||||
heap.clear();
|
heap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
|
|||||||
// construct table from length vector
|
// construct table from length vector
|
||||||
template <typename VectorT> explicit RangeTable(const VectorT &lengths)
|
template <typename VectorT> explicit RangeTable(const VectorT &lengths)
|
||||||
{
|
{
|
||||||
const unsigned number_of_blocks = [&lengths]() {
|
const unsigned number_of_blocks = [&lengths]()
|
||||||
|
{
|
||||||
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
|
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
|
||||||
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
|
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -168,6 +167,18 @@ struct RectangleInt2D
|
|||||||
min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
|
min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
|
||||||
max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
|
max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RectangleInt2D ExpandMeters(const Coordinate &coordinate, const double meters)
|
||||||
|
{
|
||||||
|
const double lat_offset = meters / coordinate_calculation::METERS_PER_DEGREE_LAT;
|
||||||
|
const double lon_offset =
|
||||||
|
meters / coordinate_calculation::metersPerLngDegree(coordinate.lat);
|
||||||
|
|
||||||
|
return RectangleInt2D{coordinate.lon - toFixed(FloatLongitude{lon_offset}),
|
||||||
|
coordinate.lon + toFixed(FloatLongitude{lon_offset}),
|
||||||
|
coordinate.lat - toFixed(FloatLatitude{lat_offset}),
|
||||||
|
coordinate.lat + toFixed(FloatLatitude{lat_offset})};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace osrm::util
|
} // namespace osrm::util
|
||||||
|
|
||||||
|
|||||||
@@ -304,7 +304,11 @@ class StaticGraph
|
|||||||
BOOST_ASSERT(node_array.size() == number_of_nodes + 1);
|
BOOST_ASSERT(node_array.size() == number_of_nodes + 1);
|
||||||
|
|
||||||
edge_array.resize(number_of_edges);
|
edge_array.resize(number_of_edges);
|
||||||
std::transform(begin, end, edge_array.begin(), [](const auto &from) {
|
std::transform(begin,
|
||||||
|
end,
|
||||||
|
edge_array.begin(),
|
||||||
|
[](const auto &from)
|
||||||
|
{
|
||||||
return static_graph_details::edgeToEntry<EdgeArrayEntry>(
|
return static_graph_details::edgeToEntry<EdgeArrayEntry>(
|
||||||
from, traits::HasDataMember<EdgeArrayEntry>{});
|
from, traits::HasDataMember<EdgeArrayEntry>{});
|
||||||
});
|
});
|
||||||
|
|||||||
+114
-67
@@ -2,7 +2,6 @@
|
|||||||
#define STATIC_RTREE_HPP
|
#define STATIC_RTREE_HPP
|
||||||
|
|
||||||
#include "storage/tar_fwd.hpp"
|
#include "storage/tar_fwd.hpp"
|
||||||
|
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "util/deallocating_vector.hpp"
|
||||||
@@ -11,6 +10,7 @@
|
|||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
#include "util/mmap_file.hpp"
|
#include "util/mmap_file.hpp"
|
||||||
#include "util/rectangle.hpp"
|
#include "util/rectangle.hpp"
|
||||||
|
#include "util/timing_util.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
#include "util/vector_view.hpp"
|
#include "util/vector_view.hpp"
|
||||||
#include "util/web_mercator.hpp"
|
#include "util/web_mercator.hpp"
|
||||||
@@ -281,7 +281,8 @@ class StaticRTree
|
|||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<uint64_t>(0, element_count),
|
tbb::blocked_range<uint64_t>(0, element_count),
|
||||||
[&input_data_vector, &input_wrapper_vector, this](
|
[&input_data_vector, &input_wrapper_vector, this](
|
||||||
const tbb::blocked_range<uint64_t> &range) {
|
const tbb::blocked_range<uint64_t> &range)
|
||||||
|
{
|
||||||
for (uint64_t element_counter = range.begin(), end = range.end();
|
for (uint64_t element_counter = range.begin(), end = range.end();
|
||||||
element_counter != end;
|
element_counter != end;
|
||||||
++element_counter)
|
++element_counter)
|
||||||
@@ -486,70 +487,9 @@ class StaticRTree
|
|||||||
Rectangle needs to be projected!*/
|
Rectangle needs to be projected!*/
|
||||||
std::vector<EdgeDataT> SearchInBox(const Rectangle &search_rectangle) const
|
std::vector<EdgeDataT> SearchInBox(const Rectangle &search_rectangle) const
|
||||||
{
|
{
|
||||||
const Rectangle projected_rectangle{
|
|
||||||
search_rectangle.min_lon,
|
|
||||||
search_rectangle.max_lon,
|
|
||||||
toFixed(FloatLatitude{
|
|
||||||
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.min_lat)))}),
|
|
||||||
toFixed(FloatLatitude{
|
|
||||||
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})};
|
|
||||||
std::vector<EdgeDataT> results;
|
std::vector<EdgeDataT> results;
|
||||||
|
SearchInBox(search_rectangle,
|
||||||
std::queue<TreeIndex> traversal_queue;
|
[&results](const auto &edge_data) { results.push_back(edge_data); });
|
||||||
traversal_queue.push(TreeIndex{});
|
|
||||||
|
|
||||||
while (!traversal_queue.empty())
|
|
||||||
{
|
|
||||||
auto const current_tree_index = traversal_queue.front();
|
|
||||||
traversal_queue.pop();
|
|
||||||
|
|
||||||
// If we're at the bottom of the tree, we need to explore the
|
|
||||||
// element array
|
|
||||||
if (is_leaf(current_tree_index))
|
|
||||||
{
|
|
||||||
|
|
||||||
// Note: irange is [start,finish), so we need to +1 to make sure we visit the
|
|
||||||
// last
|
|
||||||
for (const auto current_child_index : child_indexes(current_tree_index))
|
|
||||||
{
|
|
||||||
const auto ¤t_edge = m_objects[current_child_index];
|
|
||||||
|
|
||||||
// we don't need to project the coordinates here,
|
|
||||||
// because we use the unprojected rectangle to test against
|
|
||||||
const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon,
|
|
||||||
m_coordinate_list[current_edge.v].lon),
|
|
||||||
std::max(m_coordinate_list[current_edge.u].lon,
|
|
||||||
m_coordinate_list[current_edge.v].lon),
|
|
||||||
std::min(m_coordinate_list[current_edge.u].lat,
|
|
||||||
m_coordinate_list[current_edge.v].lat),
|
|
||||||
std::max(m_coordinate_list[current_edge.u].lat,
|
|
||||||
m_coordinate_list[current_edge.v].lat)};
|
|
||||||
|
|
||||||
// use the _unprojected_ input rectangle here
|
|
||||||
if (bbox.Intersects(search_rectangle))
|
|
||||||
{
|
|
||||||
results.push_back(current_edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(current_tree_index.level + 1 < m_tree_level_starts.size());
|
|
||||||
|
|
||||||
for (const auto child_index : child_indexes(current_tree_index))
|
|
||||||
{
|
|
||||||
const auto &child_rectangle =
|
|
||||||
m_search_tree[child_index].minimum_bounding_rectangle;
|
|
||||||
|
|
||||||
if (child_rectangle.Intersects(projected_rectangle))
|
|
||||||
{
|
|
||||||
traversal_queue.push(TreeIndex(
|
|
||||||
current_tree_index.level + 1,
|
|
||||||
child_index - m_tree_level_starts[current_tree_index.level + 1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,9 +500,47 @@ class StaticRTree
|
|||||||
return Nearest(
|
return Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[](const CandidateSegment &) { return std::make_pair(true, true); },
|
[](const CandidateSegment &) { return std::make_pair(true, true); },
|
||||||
[max_results](const std::size_t num_results, const CandidateSegment &) {
|
[max_results](const std::size_t num_results, const CandidateSegment &)
|
||||||
return num_results >= max_results;
|
{ return num_results >= max_results; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB 1: results are not guaranteed to be sorted by distance
|
||||||
|
// NB 2: maxDistanceMeters is not a hard limit, it's just a way to reduce the number of edges
|
||||||
|
// returned
|
||||||
|
template <typename FilterT>
|
||||||
|
std::vector<CandidateSegment> SearchInRange(const Coordinate input_coordinate,
|
||||||
|
double maxDistanceMeters,
|
||||||
|
const FilterT filter) const
|
||||||
|
{
|
||||||
|
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
||||||
|
Coordinate fixed_projected_coordinate{projected_coordinate};
|
||||||
|
|
||||||
|
auto bbox = Rectangle::ExpandMeters(input_coordinate, maxDistanceMeters);
|
||||||
|
std::vector<CandidateSegment> results;
|
||||||
|
|
||||||
|
SearchInBox(
|
||||||
|
bbox,
|
||||||
|
[&results, &filter, fixed_projected_coordinate, this](const EdgeDataT ¤t_edge)
|
||||||
|
{
|
||||||
|
const auto projected_u = web_mercator::fromWGS84(m_coordinate_list[current_edge.u]);
|
||||||
|
const auto projected_v = web_mercator::fromWGS84(m_coordinate_list[current_edge.v]);
|
||||||
|
|
||||||
|
auto [_, projected_nearest] = coordinate_calculation::projectPointOnSegment(
|
||||||
|
projected_u, projected_v, fixed_projected_coordinate);
|
||||||
|
|
||||||
|
CandidateSegment current_candidate{projected_nearest, current_edge};
|
||||||
|
auto use_segment = filter(current_candidate);
|
||||||
|
if (!use_segment.first && !use_segment.second)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_candidate.data.forward_segment_id.enabled &= use_segment.first;
|
||||||
|
current_candidate.data.reverse_segment_id.enabled &= use_segment.second;
|
||||||
|
|
||||||
|
results.push_back(current_candidate);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return edges in distance order with the coordinate of the closest point on the edge.
|
// Return edges in distance order with the coordinate of the closest point on the edge.
|
||||||
@@ -572,8 +550,10 @@ class StaticRTree
|
|||||||
const TerminationT terminate) const
|
const TerminationT terminate) const
|
||||||
{
|
{
|
||||||
std::vector<CandidateSegment> results;
|
std::vector<CandidateSegment> results;
|
||||||
|
|
||||||
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
||||||
Coordinate fixed_projected_coordinate{projected_coordinate};
|
Coordinate fixed_projected_coordinate{projected_coordinate};
|
||||||
|
|
||||||
// initialize queue with root element
|
// initialize queue with root element
|
||||||
std::priority_queue<QueryCandidate> traversal_queue;
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
traversal_queue.push(QueryCandidate{0, TreeIndex{}});
|
traversal_queue.push(QueryCandidate{0, TreeIndex{}});
|
||||||
@@ -631,6 +611,73 @@ class StaticRTree
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename Callback>
|
||||||
|
void SearchInBox(const Rectangle &search_rectangle, Callback &&callback) const
|
||||||
|
{
|
||||||
|
const Rectangle projected_rectangle{
|
||||||
|
search_rectangle.min_lon,
|
||||||
|
search_rectangle.max_lon,
|
||||||
|
toFixed(FloatLatitude{
|
||||||
|
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.min_lat)))}),
|
||||||
|
toFixed(FloatLatitude{
|
||||||
|
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})};
|
||||||
|
std::queue<TreeIndex> traversal_queue;
|
||||||
|
traversal_queue.push(TreeIndex{});
|
||||||
|
|
||||||
|
while (!traversal_queue.empty())
|
||||||
|
{
|
||||||
|
auto const current_tree_index = traversal_queue.front();
|
||||||
|
traversal_queue.pop();
|
||||||
|
|
||||||
|
// If we're at the bottom of the tree, we need to explore the
|
||||||
|
// element array
|
||||||
|
if (is_leaf(current_tree_index))
|
||||||
|
{
|
||||||
|
|
||||||
|
// Note: irange is [start,finish), so we need to +1 to make sure we visit the
|
||||||
|
// last
|
||||||
|
for (const auto current_child_index : child_indexes(current_tree_index))
|
||||||
|
{
|
||||||
|
const auto ¤t_edge = m_objects[current_child_index];
|
||||||
|
|
||||||
|
// we don't need to project the coordinates here,
|
||||||
|
// because we use the unprojected rectangle to test against
|
||||||
|
const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon,
|
||||||
|
m_coordinate_list[current_edge.v].lon),
|
||||||
|
std::max(m_coordinate_list[current_edge.u].lon,
|
||||||
|
m_coordinate_list[current_edge.v].lon),
|
||||||
|
std::min(m_coordinate_list[current_edge.u].lat,
|
||||||
|
m_coordinate_list[current_edge.v].lat),
|
||||||
|
std::max(m_coordinate_list[current_edge.u].lat,
|
||||||
|
m_coordinate_list[current_edge.v].lat)};
|
||||||
|
|
||||||
|
// use the _unprojected_ input rectangle here
|
||||||
|
if (bbox.Intersects(search_rectangle))
|
||||||
|
{
|
||||||
|
callback(current_edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(current_tree_index.level + 1 < m_tree_level_starts.size());
|
||||||
|
|
||||||
|
for (const auto child_index : child_indexes(current_tree_index))
|
||||||
|
{
|
||||||
|
const auto &child_rectangle =
|
||||||
|
m_search_tree[child_index].minimum_bounding_rectangle;
|
||||||
|
|
||||||
|
if (child_rectangle.Intersects(projected_rectangle))
|
||||||
|
{
|
||||||
|
traversal_queue.push(TreeIndex(
|
||||||
|
current_tree_index.level + 1,
|
||||||
|
child_index - m_tree_level_starts[current_tree_index.level + 1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates over all the objects in a leaf node and inserts them into our
|
* Iterates over all the objects in a leaf node and inserts them into our
|
||||||
* search priority queue. The speed of this function is very much governed
|
* search priority queue. The speed of this function is very much governed
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ template <int length, int precision> char *printInt(char *buffer, int value)
|
|||||||
static_assert(length > 0, "length must be positive");
|
static_assert(length > 0, "length must be positive");
|
||||||
static_assert(precision > 0, "precision must be positive");
|
static_assert(precision > 0, "precision must be positive");
|
||||||
|
|
||||||
const bool minus = [&value] {
|
const bool minus = [&value]
|
||||||
|
{
|
||||||
if (value >= 0)
|
if (value >= 0)
|
||||||
{
|
{
|
||||||
value = -value;
|
value = -value;
|
||||||
|
|||||||
@@ -51,13 +51,17 @@ template <std::size_t TimeBinSize = 1000, std::size_t IndexBinSize = 1000> class
|
|||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
|
|
||||||
const auto print_bins = [&out](auto frame_index, auto begin, auto end) {
|
const auto print_bins = [&out](auto frame_index, auto begin, auto end)
|
||||||
|
{
|
||||||
auto bin_index = 0;
|
auto bin_index = 0;
|
||||||
std::for_each(begin, end, [&](const auto count) {
|
std::for_each(begin,
|
||||||
|
end,
|
||||||
|
[&](const auto count)
|
||||||
|
{
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
out << (frame_index * TimeBinSize) << "," << (bin_index * IndexBinSize) << ","
|
out << (frame_index * TimeBinSize) << ","
|
||||||
<< count << std::endl;
|
<< (bin_index * IndexBinSize) << "," << count << std::endl;
|
||||||
}
|
}
|
||||||
bin_index++;
|
bin_index++;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <boost/geometry.hpp>
|
#include <boost/geometry.hpp>
|
||||||
#include <boost/geometry/index/rtree.hpp>
|
#include <boost/geometry/index/rtree.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace osrm::updater
|
namespace osrm::updater
|
||||||
{
|
{
|
||||||
@@ -34,7 +34,7 @@ class Timezoner
|
|||||||
Timezoner(const char geojson[], std::time_t utc_time_now);
|
Timezoner(const char geojson[], std::time_t utc_time_now);
|
||||||
Timezoner(const boost::filesystem::path &tz_shapes_filename, std::time_t utc_time_now);
|
Timezoner(const boost::filesystem::path &tz_shapes_filename, std::time_t utc_time_now);
|
||||||
|
|
||||||
boost::optional<struct tm> operator()(const point_t &point) const;
|
std::optional<struct tm> operator()(const point_t &point) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time);
|
void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time);
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/sh -ex
|
|
||||||
|
|
||||||
sudo dpkg --add-architecture i386
|
|
||||||
sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test && ( sudo apt-get update -qq --yes || true )
|
|
||||||
|
|
||||||
sudo apt-get install -qq --yes --force-yes g++-9-multilib libxml2-dev:i386 libexpat1-dev:i386 libzip-dev:i386 libbz2-dev:i386 libtbb-dev:i386 lua5.2:i386 liblua5.2-dev:i386 libboost-date-time-dev:i386 libboost-filesystem-dev:i386 libboost-iostreams-dev:i386 libboost-program-options-dev:i386 libboost-regex-dev:i386 libboost-system-dev:i386 libboost-thread-dev:i386 libboost-test-dev:i386
|
|
||||||
@@ -12,11 +12,6 @@ if [[ ${BUILD_TYPE} == "Debug" ]]; then
|
|||||||
NPM_FLAGS='--debug'
|
NPM_FLAGS='--debug'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# append --target_arch in order to handle cross-compilation for Apple Silicon
|
|
||||||
if [[ "$ENABLE_APPLE_SILICON" == "ON" ]]; then
|
|
||||||
NPM_FLAGS="${NPM_FLAGS} --target_arch=arm64"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "dumping binary meta..."
|
echo "dumping binary meta..."
|
||||||
./node_modules/.bin/node-pre-gyp reveal $NPM_FLAGS
|
./node_modules/.bin/node-pre-gyp reveal $NPM_FLAGS
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import requests
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
|
||||||
|
REPO = os.getenv('GITHUB_REPOSITORY')
|
||||||
|
PR_NUMBER = os.getenv('PR_NUMBER')
|
||||||
|
|
||||||
|
REPO_OWNER, REPO_NAME = REPO.split('/')
|
||||||
|
|
||||||
|
def create_markdown_table(results):
|
||||||
|
results = sorted(results, key=lambda x: x['name'])
|
||||||
|
header = "| Benchmark | Base | PR |\n|-----------|------|----|"
|
||||||
|
rows = []
|
||||||
|
for result in results:
|
||||||
|
name = result['name']
|
||||||
|
base = result['base'].replace('\n', '<br/>')
|
||||||
|
pr = result['pr'].replace('\n', '<br/>')
|
||||||
|
row = f"| {name} | {base} | {pr} |"
|
||||||
|
rows.append(row)
|
||||||
|
return f"{header}\n" + "\n".join(rows)
|
||||||
|
|
||||||
|
def get_pr_details(repo_owner, repo_name, pr_number):
|
||||||
|
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls/{pr_number}"
|
||||||
|
headers = {'Authorization': f'token {GITHUB_TOKEN}'}
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def update_pr_description(repo_owner, repo_name, pr_number, body):
|
||||||
|
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls/{pr_number}"
|
||||||
|
headers = {'Authorization': f'token {GITHUB_TOKEN}'}
|
||||||
|
data = {'body': body}
|
||||||
|
response = requests.patch(url, headers=headers, json=data)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
|
||||||
|
def collect_benchmark_results(base_folder, pr_folder):
|
||||||
|
results = []
|
||||||
|
results_index = {}
|
||||||
|
|
||||||
|
for file in os.listdir(base_folder):
|
||||||
|
if not file.endswith('.bench'): continue
|
||||||
|
with open(f"{base_folder}/{file}") as f:
|
||||||
|
result = f.read().strip()
|
||||||
|
results.append({'base': result, 'pr': None, 'name': os.path.splitext(file)[0]})
|
||||||
|
results_index[file] = len(results) - 1
|
||||||
|
|
||||||
|
for file in os.listdir(pr_folder):
|
||||||
|
if not file.endswith('.bench'): continue
|
||||||
|
with open(f"{pr_folder}/{file}") as f:
|
||||||
|
result = f.read().strip()
|
||||||
|
if file in results_index:
|
||||||
|
results[results_index[file]]['pr'] = result
|
||||||
|
else:
|
||||||
|
results.append({'base': None, 'pr': result, 'name': os.path.splitext(file)[0]})
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Usage: python post_benchmark_results.py <base_folder> <pr_folder>")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
base_folder = sys.argv[1]
|
||||||
|
pr_folder = sys.argv[2]
|
||||||
|
|
||||||
|
benchmark_results = collect_benchmark_results(base_folder, pr_folder)
|
||||||
|
|
||||||
|
pr_details = get_pr_details(REPO_OWNER, REPO_NAME, PR_NUMBER)
|
||||||
|
# in both cases when there is no PR body or PR body is None fallback to empty string
|
||||||
|
pr_body = pr_details.get('body', '') or ''
|
||||||
|
|
||||||
|
markdown_table = create_markdown_table(benchmark_results)
|
||||||
|
new_benchmark_section = f"<!-- BENCHMARK_RESULTS_START -->\n## Benchmark Results\n{markdown_table}\n<!-- BENCHMARK_RESULTS_END -->"
|
||||||
|
|
||||||
|
if re.search(r'<!-- BENCHMARK_RESULTS_START -->.*<!-- BENCHMARK_RESULTS_END -->', pr_body, re.DOTALL):
|
||||||
|
updated_body = re.sub(
|
||||||
|
r'<!-- BENCHMARK_RESULTS_START -->.*<!-- BENCHMARK_RESULTS_END -->',
|
||||||
|
new_benchmark_section,
|
||||||
|
pr_body,
|
||||||
|
flags=re.DOTALL
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
updated_body = f"{pr_body}\n\n{new_benchmark_section}" if len(pr_body) > 0 else new_benchmark_section
|
||||||
|
|
||||||
|
update_pr_description(REPO_OWNER, REPO_NAME, PR_NUMBER, updated_body)
|
||||||
|
print("PR description updated successfully.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eou pipefail
|
||||||
|
|
||||||
|
function run_benchmarks_for_folder {
|
||||||
|
echo "Running benchmarks for $1"
|
||||||
|
|
||||||
|
FOLDER=$1
|
||||||
|
RESULTS_FOLDER=$2
|
||||||
|
|
||||||
|
mkdir -p $RESULTS_FOLDER
|
||||||
|
|
||||||
|
BENCHMARKS_FOLDER="$FOLDER/build/src/benchmarks"
|
||||||
|
|
||||||
|
./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench"
|
||||||
|
./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/match_ch.bench"
|
||||||
|
./$BENCHMARKS_FOLDER/alias-bench > "$RESULTS_FOLDER/alias.bench"
|
||||||
|
./$BENCHMARKS_FOLDER/json-render-bench "./$FOLDER/src/benchmarks/portugal_to_korea.json" > "$RESULTS_FOLDER/json-render.bench"
|
||||||
|
./$BENCHMARKS_FOLDER/packedvector-bench > "$RESULTS_FOLDER/packedvector.bench"
|
||||||
|
./$BENCHMARKS_FOLDER/rtree-bench "./$FOLDER/test/data/monaco.osrm.ramIndex" "./$FOLDER/test/data/monaco.osrm.fileIndex" "./$FOLDER/test/data/monaco.osrm.nbg_nodes" > "$RESULTS_FOLDER/rtree.bench"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_benchmarks_for_folder $1 "${1}_results"
|
||||||
|
run_benchmarks_for_folder $2 "${2}_results"
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
alignment:src/contractor/graph_contractor.cpp
|
||||||
enum:include/tbb/pipeline.h
|
enum:include/tbb/pipeline.h
|
||||||
vptr:src/util/log.cpp
|
vptr:src/util/log.cpp
|
||||||
vptr:include/tbb/task.h
|
vptr:include/tbb/task.h
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ msbuild OSRM.sln ^
|
|||||||
/p:BuildInParallel=true ^
|
/p:BuildInParallel=true ^
|
||||||
/m:%NUMBER_OF_PROCESSORS% ^
|
/m:%NUMBER_OF_PROCESSORS% ^
|
||||||
/toolsversion:Current ^
|
/toolsversion:Current ^
|
||||||
/clp:Verbosity=normal ^
|
/clp:Verbosity=quiet ^
|
||||||
/nologo
|
/nologo
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -19,18 +19,18 @@ elif [[ ${OS} = "Darwin" ]] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Discover clang-format
|
# Discover clang-format
|
||||||
if type clang-format-10 2> /dev/null ; then
|
if type clang-format-15 2> /dev/null ; then
|
||||||
CLANG_FORMAT=clang-format-10
|
CLANG_FORMAT=clang-format-15
|
||||||
elif type clang-format 2> /dev/null ; then
|
elif type clang-format 2> /dev/null ; then
|
||||||
# Clang format found, but need to check version
|
# Clang format found, but need to check version
|
||||||
CLANG_FORMAT=clang-format
|
CLANG_FORMAT=clang-format
|
||||||
V=$(clang-format --version)
|
V=$(clang-format --version)
|
||||||
if [[ $V != *10.0* ]] ; then
|
if [[ $V != *15.0* ]] ; then
|
||||||
echo "clang-format is not 10.0 (returned ${V})"
|
echo "clang-format is not 15.0 (returned ${V})"
|
||||||
#exit 1
|
#exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "No appropriate clang-format found (expected clang-format-10, or clang-format)"
|
echo "No appropriate clang-format found (expected clang-format-15, or clang-format)"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
# Runs the Clang Modernizer in parallel on the code base.
|
|
||||||
# Requires a compilation database in the build directory.
|
|
||||||
|
|
||||||
find src include unit_tests -type f -name '*.hpp' -o -name '*.cpp' \
|
|
||||||
| xargs \
|
|
||||||
-I{} \
|
|
||||||
-P $(nproc) \
|
|
||||||
clang-modernize \
|
|
||||||
-p build \
|
|
||||||
-final-syntax-check \
|
|
||||||
-format \
|
|
||||||
-style=file \
|
|
||||||
-summary \
|
|
||||||
-for-compilers=clang-3.4,gcc-4.8 \
|
|
||||||
-include . \
|
|
||||||
-exclude third_party \
|
|
||||||
{}
|
|
||||||
@@ -28,7 +28,10 @@ PROTOZERO_PATH="mapbox/protozero"
|
|||||||
PROTOZERO_TAG=v1.6.2
|
PROTOZERO_TAG=v1.6.2
|
||||||
|
|
||||||
VTZERO_PATH="mapbox/vtzero"
|
VTZERO_PATH="mapbox/vtzero"
|
||||||
VTZERO_TAG=v1.0.1
|
VTZERO_TAG=v1.1.0
|
||||||
|
|
||||||
|
FMT_PATH="fmtlib/fmt"
|
||||||
|
FMT_TAG=v10.2.1
|
||||||
|
|
||||||
function update_subtree () {
|
function update_subtree () {
|
||||||
name=${1^^}
|
name=${1^^}
|
||||||
@@ -53,6 +56,6 @@ function update_subtree () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
## Update dependencies
|
## Update dependencies
|
||||||
for dep in osmium variant sol rapidjson microtar protozero vtzero ; do
|
for dep in osmium variant sol rapidjson microtar protozero vtzero fmt; do
|
||||||
update_subtree $dep
|
update_subtree $dep
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ int main(int, char **)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
TIMER_STOP(aliased_u32);
|
TIMER_STOP(aliased_u32);
|
||||||
util::Log() << "aliased u32: " << TIMER_MSEC(aliased_u32);
|
std::cout << "aliased u32: " << TIMER_MSEC(aliased_u32) << std::endl;
|
||||||
|
|
||||||
TIMER_START(plain_u32);
|
TIMER_START(plain_u32);
|
||||||
for (auto round : util::irange(0, num_rounds))
|
for (auto round : util::irange(0, num_rounds))
|
||||||
@@ -83,7 +83,7 @@ int main(int, char **)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
TIMER_STOP(plain_u32);
|
TIMER_STOP(plain_u32);
|
||||||
util::Log() << "plain u32: " << TIMER_MSEC(plain_u32);
|
std::cout << "plain u32: " << TIMER_MSEC(plain_u32) << std::endl;
|
||||||
|
|
||||||
TIMER_START(aliased_double);
|
TIMER_START(aliased_double);
|
||||||
for (auto round : util::irange(0, num_rounds))
|
for (auto round : util::irange(0, num_rounds))
|
||||||
@@ -103,7 +103,7 @@ int main(int, char **)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
TIMER_STOP(aliased_double);
|
TIMER_STOP(aliased_double);
|
||||||
util::Log() << "aliased double: " << TIMER_MSEC(aliased_double);
|
std::cout << "aliased double: " << TIMER_MSEC(aliased_double) << std::endl;
|
||||||
|
|
||||||
TIMER_START(plain_double);
|
TIMER_START(plain_double);
|
||||||
for (auto round : util::irange(0, num_rounds))
|
for (auto round : util::irange(0, num_rounds))
|
||||||
@@ -123,5 +123,5 @@ int main(int, char **)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
TIMER_STOP(plain_double);
|
TIMER_STOP(plain_double);
|
||||||
util::Log() << "plain double: " << TIMER_MSEC(plain_double);
|
std::cout << "plain double: " << TIMER_MSEC(plain_double) << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "engine/engine_config.hpp"
|
||||||
#include "util/timing_util.hpp"
|
#include "util/timing_util.hpp"
|
||||||
|
|
||||||
#include "osrm/match_parameters.hpp"
|
#include "osrm/match_parameters.hpp"
|
||||||
@@ -11,13 +12,14 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -32,6 +34,8 @@ try
|
|||||||
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
|
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
|
||||||
EngineConfig config;
|
EngineConfig config;
|
||||||
config.storage_config = {argv[1]};
|
config.storage_config = {argv[1]};
|
||||||
|
config.algorithm = (argc > 2 && std::string{argv[2]} == "mld") ? EngineConfig::Algorithm::MLD
|
||||||
|
: EngineConfig::Algorithm::CH;
|
||||||
config.use_shared_memory = false;
|
config.use_shared_memory = false;
|
||||||
|
|
||||||
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
|
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
|
||||||
@@ -211,6 +215,17 @@ try
|
|||||||
params.coordinates.push_back(
|
params.coordinates.push_back(
|
||||||
FloatCoordinate{FloatLongitude{7.415342330932617}, FloatLatitude{43.733251335381205}});
|
FloatCoordinate{FloatLongitude{7.415342330932617}, FloatLatitude{43.733251335381205}});
|
||||||
|
|
||||||
|
auto run_benchmark = [&](std::optional<double> radiusInMeters)
|
||||||
|
{
|
||||||
|
params.radiuses = {};
|
||||||
|
if (radiusInMeters)
|
||||||
|
{
|
||||||
|
for (size_t index = 0; index < params.coordinates.size(); ++index)
|
||||||
|
{
|
||||||
|
params.radiuses.emplace_back(*radiusInMeters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TIMER_START(routes);
|
TIMER_START(routes);
|
||||||
auto NUM = 100;
|
auto NUM = 100;
|
||||||
for (int i = 0; i < NUM; ++i)
|
for (int i = 0; i < NUM; ++i)
|
||||||
@@ -221,14 +236,28 @@ try
|
|||||||
if (rc != Status::Ok ||
|
if (rc != Status::Ok ||
|
||||||
json_result.values.at("matchings").get<json::Array>().values.size() != 1)
|
json_result.values.at("matchings").get<json::Array>().values.size() != 1)
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
throw std::runtime_error{"Couldn't match"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TIMER_STOP(routes);
|
TIMER_STOP(routes);
|
||||||
|
if (radiusInMeters)
|
||||||
|
{
|
||||||
|
std::cout << "Radius " << *radiusInMeters << "m: " << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Default radius: " << std::endl;
|
||||||
|
}
|
||||||
std::cout << (TIMER_MSEC(routes) / NUM) << "ms/req at " << params.coordinates.size()
|
std::cout << (TIMER_MSEC(routes) / NUM) << "ms/req at " << params.coordinates.size()
|
||||||
<< " coordinate" << std::endl;
|
<< " coordinate" << std::endl;
|
||||||
std::cout << (TIMER_MSEC(routes) / NUM / params.coordinates.size()) << "ms/coordinate"
|
std::cout << (TIMER_MSEC(routes) / NUM / params.coordinates.size()) << "ms/coordinate"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto radius : std::vector<std::optional<double>>{std::nullopt, 5.0, 10.0, 15.0, 30.0})
|
||||||
|
{
|
||||||
|
run_benchmark(radius);
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ int main(int, char **)
|
|||||||
|
|
||||||
auto write_slowdown = result_packed.random_write_ms / result_plain.random_write_ms;
|
auto write_slowdown = result_packed.random_write_ms / result_plain.random_write_ms;
|
||||||
auto read_slowdown = result_packed.random_read_ms / result_plain.random_read_ms;
|
auto read_slowdown = result_packed.random_read_ms / result_plain.random_read_ms;
|
||||||
util::Log() << "random write: std::vector " << result_plain.random_write_ms
|
std::cout << "random write:\nstd::vector " << result_plain.random_write_ms
|
||||||
<< " ms, util::packed_vector " << result_packed.random_write_ms << " ms. "
|
<< " ms\nutil::packed_vector " << result_packed.random_write_ms << " ms\n"
|
||||||
<< write_slowdown;
|
<< "slowdown: " << write_slowdown << std::endl;
|
||||||
util::Log() << "random read: std::vector " << result_plain.random_read_ms
|
std::cout << "random read:\nstd::vector " << result_plain.random_read_ms
|
||||||
<< " ms, util::packed_vector " << result_packed.random_read_ms << " ms. "
|
<< " ms\nutil::packed_vector " << result_packed.random_read_ms << " ms\n"
|
||||||
<< read_slowdown;
|
<< "slowdown: " << read_slowdown << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ void benchmarkQuery(const std::vector<util::Coordinate> &queries,
|
|||||||
const std::string &name,
|
const std::string &name,
|
||||||
QueryT query)
|
QueryT query)
|
||||||
{
|
{
|
||||||
std::cout << "Running " << name << " with " << queries.size() << " coordinates: " << std::flush;
|
|
||||||
|
|
||||||
TIMER_START(query);
|
TIMER_START(query);
|
||||||
for (const auto &q : queries)
|
for (const auto &q : queries)
|
||||||
{
|
{
|
||||||
@@ -46,11 +44,9 @@ void benchmarkQuery(const std::vector<util::Coordinate> &queries,
|
|||||||
}
|
}
|
||||||
TIMER_STOP(query);
|
TIMER_STOP(query);
|
||||||
|
|
||||||
std::cout << "Took " << TIMER_SEC(query) << " seconds "
|
std::cout << name << ":\n"
|
||||||
<< "(" << TIMER_MSEC(query) << "ms"
|
<< TIMER_MSEC(query) << "ms"
|
||||||
<< ") -> " << TIMER_MSEC(query) / queries.size() << " ms/query "
|
<< " -> " << TIMER_MSEC(query) / queries.size() << " ms/query" << std::endl;
|
||||||
<< "(" << TIMER_MSEC(query) << "ms"
|
|
||||||
<< ")" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
void benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
||||||
@@ -65,12 +61,11 @@ void benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
|||||||
util::FixedLatitude{lat_udist(mt_rand)});
|
util::FixedLatitude{lat_udist(mt_rand)});
|
||||||
}
|
}
|
||||||
|
|
||||||
benchmarkQuery(queries, "raw RTree queries (1 result)", [&rtree](const util::Coordinate &q) {
|
benchmarkQuery(
|
||||||
return rtree.Nearest(q, 1);
|
queries, "1 result", [&rtree](const util::Coordinate &q) { return rtree.Nearest(q, 1); });
|
||||||
});
|
benchmarkQuery(queries,
|
||||||
benchmarkQuery(queries, "raw RTree queries (10 results)", [&rtree](const util::Coordinate &q) {
|
"10 results",
|
||||||
return rtree.Nearest(q, 10);
|
[&rtree](const util::Coordinate &q) { return rtree.Nearest(q, 10); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} // namespace osrm::benchmarks
|
} // namespace osrm::benchmarks
|
||||||
|
|
||||||
|
|||||||
@@ -619,7 +619,8 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
util::UnbufferedLog log;
|
util::UnbufferedLog log;
|
||||||
log << "initializing node priorities...";
|
log << "initializing node priorities...";
|
||||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, remaining_nodes.size(), PQGrainSize),
|
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, remaining_nodes.size(), PQGrainSize),
|
||||||
[&](const auto &range) {
|
[&](const auto &range)
|
||||||
|
{
|
||||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||||
for (auto x = range.begin(), end = range.end(); x != end; ++x)
|
for (auto x = range.begin(), end = range.end(); x != end; ++x)
|
||||||
{
|
{
|
||||||
@@ -656,7 +657,8 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
|
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<NodeID>(0, remaining_nodes.size(), IndependentGrainSize),
|
tbb::blocked_range<NodeID>(0, remaining_nodes.size(), IndependentGrainSize),
|
||||||
[&](const auto &range) {
|
[&](const auto &range)
|
||||||
|
{
|
||||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||||
// determine independent node set
|
// determine independent node set
|
||||||
for (auto i = range.begin(), end = range.end(); i != end; ++i)
|
for (auto i = range.begin(), end = range.end(); i != end; ++i)
|
||||||
@@ -669,9 +671,9 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
|
|
||||||
// sort all remaining nodes to the beginning of the sequence
|
// sort all remaining nodes to the beginning of the sequence
|
||||||
const auto begin_independent_nodes = std::stable_partition(
|
const auto begin_independent_nodes = std::stable_partition(
|
||||||
remaining_nodes.begin(), remaining_nodes.end(), [](RemainingNodeData node_data) {
|
remaining_nodes.begin(),
|
||||||
return !node_data.is_independent;
|
remaining_nodes.end(),
|
||||||
});
|
[](RemainingNodeData node_data) { return !node_data.is_independent; });
|
||||||
auto begin_independent_nodes_idx =
|
auto begin_independent_nodes_idx =
|
||||||
std::distance(remaining_nodes.begin(), begin_independent_nodes);
|
std::distance(remaining_nodes.begin(), begin_independent_nodes);
|
||||||
auto end_independent_nodes_idx = remaining_nodes.size();
|
auto end_independent_nodes_idx = remaining_nodes.size();
|
||||||
@@ -680,7 +682,8 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<NodeID>(
|
tbb::blocked_range<NodeID>(
|
||||||
begin_independent_nodes_idx, end_independent_nodes_idx, ContractGrainSize),
|
begin_independent_nodes_idx, end_independent_nodes_idx, ContractGrainSize),
|
||||||
[&](const auto &range) {
|
[&](const auto &range)
|
||||||
|
{
|
||||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||||
for (auto position = range.begin(), end = range.end(); position != end; ++position)
|
for (auto position = range.begin(), end = range.end(); position != end; ++position)
|
||||||
{
|
{
|
||||||
@@ -699,7 +702,8 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<NodeID>(
|
tbb::blocked_range<NodeID>(
|
||||||
begin_independent_nodes_idx, end_independent_nodes_idx, DeleteGrainSize),
|
begin_independent_nodes_idx, end_independent_nodes_idx, DeleteGrainSize),
|
||||||
[&](const auto &range) {
|
[&](const auto &range)
|
||||||
|
{
|
||||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||||
for (auto position = range.begin(), end = range.end(); position != end; ++position)
|
for (auto position = range.begin(), end = range.end(); position != end; ++position)
|
||||||
{
|
{
|
||||||
@@ -709,9 +713,12 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
});
|
});
|
||||||
|
|
||||||
// make sure we really sort each block
|
// make sure we really sort each block
|
||||||
tbb::parallel_for(thread_data_list.data.range(), [&](const auto &range) {
|
tbb::parallel_for(thread_data_list.data.range(),
|
||||||
|
[&](const auto &range)
|
||||||
|
{
|
||||||
for (auto &data : range)
|
for (auto &data : range)
|
||||||
tbb::parallel_sort(data->inserted_edges.begin(), data->inserted_edges.end());
|
tbb::parallel_sort(data->inserted_edges.begin(),
|
||||||
|
data->inserted_edges.end());
|
||||||
});
|
});
|
||||||
|
|
||||||
// insert new edges
|
// insert new edges
|
||||||
@@ -743,7 +750,8 @@ std::vector<bool> contractGraph(ContractorGraph &graph,
|
|||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<NodeID>(
|
tbb::blocked_range<NodeID>(
|
||||||
begin_independent_nodes_idx, end_independent_nodes_idx, NeighboursGrainSize),
|
begin_independent_nodes_idx, end_independent_nodes_idx, NeighboursGrainSize),
|
||||||
[&](const auto &range) {
|
[&](const auto &range)
|
||||||
|
{
|
||||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||||
for (auto position = range.begin(), end = range.end(); position != end; ++position)
|
for (auto position = range.begin(), end = range.end(); position != end; ++position)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,17 +47,18 @@ void printUnreachableStatistics(const Partition &partition,
|
|||||||
for (auto node : cell.GetSourceNodes())
|
for (auto node : cell.GetSourceNodes())
|
||||||
{
|
{
|
||||||
const auto &weights = cell.GetOutWeight(node);
|
const auto &weights = cell.GetOutWeight(node);
|
||||||
invalid_sources += std::all_of(weights.begin(), weights.end(), [](auto weight) {
|
invalid_sources +=
|
||||||
return weight == INVALID_EDGE_WEIGHT;
|
std::all_of(weights.begin(),
|
||||||
});
|
weights.end(),
|
||||||
|
[](auto weight) { return weight == INVALID_EDGE_WEIGHT; });
|
||||||
}
|
}
|
||||||
for (auto node : cell.GetDestinationNodes())
|
for (auto node : cell.GetDestinationNodes())
|
||||||
{
|
{
|
||||||
const auto &weights = cell.GetInWeight(node);
|
const auto &weights = cell.GetInWeight(node);
|
||||||
invalid_destinations +=
|
invalid_destinations +=
|
||||||
std::all_of(weights.begin(), weights.end(), [](auto weight) {
|
std::all_of(weights.begin(),
|
||||||
return weight == INVALID_EDGE_WEIGHT;
|
weights.end(),
|
||||||
});
|
[](auto weight) { return weight == INVALID_EDGE_WEIGHT; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,8 @@ util::json::Object makeIntersection(const guidance::IntermediateIntersection &in
|
|||||||
std::transform(intersection.entry.begin(),
|
std::transform(intersection.entry.begin(),
|
||||||
intersection.entry.end(),
|
intersection.entry.end(),
|
||||||
std::back_inserter(entry.values),
|
std::back_inserter(entry.values),
|
||||||
[](const bool has_entry) -> util::json::Value {
|
[](const bool has_entry) -> util::json::Value
|
||||||
|
{
|
||||||
if (has_entry)
|
if (has_entry)
|
||||||
return util::json::True();
|
return util::json::True();
|
||||||
else
|
else
|
||||||
@@ -151,11 +152,11 @@ util::json::Object makeIntersection(const guidance::IntermediateIntersection &in
|
|||||||
{
|
{
|
||||||
util::json::Array classes;
|
util::json::Array classes;
|
||||||
classes.values.reserve(intersection.classes.size());
|
classes.values.reserve(intersection.classes.size());
|
||||||
std::transform(
|
std::transform(intersection.classes.begin(),
|
||||||
intersection.classes.begin(),
|
|
||||||
intersection.classes.end(),
|
intersection.classes.end(),
|
||||||
std::back_inserter(classes.values),
|
std::back_inserter(classes.values),
|
||||||
[](const std::string &class_name) { return util::json::String{class_name}; });
|
[](const std::string &class_name)
|
||||||
|
{ return util::json::String{class_name}; });
|
||||||
result.values["classes"] = std::move(classes);
|
result.values["classes"] = std::move(classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,9 +43,11 @@ std::vector<util::Coordinate> douglasPeucker(std::vector<util::Coordinate>::cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<util::FloatCoordinate> projected_coordinates(size);
|
std::vector<util::FloatCoordinate> projected_coordinates(size);
|
||||||
std::transform(begin, end, projected_coordinates.begin(), [](const util::Coordinate coord) {
|
std::transform(begin,
|
||||||
return util::web_mercator::fromWGS84(coord);
|
end,
|
||||||
});
|
projected_coordinates.begin(),
|
||||||
|
[](const util::Coordinate coord)
|
||||||
|
{ return util::web_mercator::fromWGS84(coord); });
|
||||||
|
|
||||||
std::vector<bool> is_necessary(size, false);
|
std::vector<bool> is_necessary(size, false);
|
||||||
BOOST_ASSERT(is_necessary.size() >= 2);
|
BOOST_ASSERT(is_necessary.size() >= 2);
|
||||||
|
|||||||
@@ -9,9 +9,8 @@ bool EngineConfig::IsValid() const
|
|||||||
// leads to an empty path
|
// leads to an empty path
|
||||||
const bool all_path_are_empty = storage_config.GetPath("").empty();
|
const bool all_path_are_empty = storage_config.GetPath("").empty();
|
||||||
|
|
||||||
const auto unlimited_or_more_than = [](const auto v, const auto limit) {
|
const auto unlimited_or_more_than = [](const auto v, const auto limit)
|
||||||
return v == -1 || v > limit;
|
{ return v == -1 || v > limit; };
|
||||||
};
|
|
||||||
|
|
||||||
const bool limits_valid =
|
const bool limits_valid =
|
||||||
unlimited_or_more_than(max_locations_distance_table, 2) &&
|
unlimited_or_more_than(max_locations_distance_table, 2) &&
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user