Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c5167d4ade | |||
| 1548803a77 | |||
| 2b2906f97a | |||
| ca464fcd5d | |||
| e9b7b68427 | |||
| 6b8ae24df6 | |||
| 65385b55e9 | |||
| f20dda55c0 | |||
| ff7f8557e3 | |||
| eff1d4e622 | |||
| f82908d509 | |||
| b3b6e16940 | |||
| f9fb0b84a8 | |||
| 83acb46390 | |||
| f36b3fb4bc | |||
| e7be271c43 | |||
| 790b574114 | |||
| b3f59ab92c | |||
| f2333eb31a | |||
| a862e5fb3a | |||
| 2715e5758b | |||
| 454487dd41 | |||
| 2ed4f6eb0c | |||
| d7bcafcb59 | |||
| c37a8ddd83 | |||
| fc3f96abcb | |||
| c37ea441fc | |||
| fa1a4e8bf6 | |||
| 2532d56b85 | |||
| 00fd869224 | |||
| 5661726e2e | |||
| cfa5d7e172 | |||
| fd7791a0e2 | |||
| e32b8bae00 | |||
| 966139cde9 | |||
| ee19383f4d | |||
| 172a8bdcdb | |||
| 543048efcc | |||
| 67c85ffa4c | |||
| c065335882 | |||
| f6313fcbfb | |||
| 6a3ea876b5 | |||
| 64ad308e9d | |||
| 94169a20de | |||
| 5ca38eee3a | |||
| f4f65f62ee | |||
| f89ada7f61 | |||
| ff3b398e23 | |||
| 84cb7865ab | |||
| 75bdf114be | |||
| c2fd64d3cc | |||
| 580c5e39ae | |||
| 8da6281dcd | |||
| f79bcc6b8d | |||
| f2b63ba0aa | |||
| a253111cbe | |||
| a5776288f6 | |||
| dbcf4cab16 | |||
| 4ea3f33376 | |||
| e4cdfb50cd | |||
| c2dc7e9cd0 | |||
| 0fc1aa2711 | |||
| 89cf6d9e74 | |||
| 61c430c098 | |||
| 4b75cb8b0e | |||
| 53f87c08b5 | |||
| e23dc8977f | |||
| 421dc5b6ec | |||
| 247f1c120f | |||
| e011c60e12 | |||
| 26c909b64b | |||
| acb7916996 | |||
| 40b5045a0a | |||
| b17f40862c | |||
| 7702ebde61 | |||
| 6951eadc18 | |||
| cf2573157f | |||
| 80c55119d2 | |||
| 7323221e3b | |||
| fb5bd818d9 | |||
| 43a4e8db12 | |||
| 302390696e | |||
| 2508629d6c | |||
| 90c390d7a6 | |||
| 28178b12c7 | |||
| 95442d45aa | |||
| 6eb4f090f9 | |||
| b4ad6588ed | |||
| 56282b0e3f | |||
| 2385602500 | |||
| 628a154d7f | |||
| efaed59b9b | |||
| bdee13dea8 | |||
| c615910874 | |||
| 9e1398c68a | |||
| af10692d2d | |||
| e7abe37b10 | |||
| bc8617a9f4 | |||
| 00e243b23b | |||
| 27324d0270 | |||
| 0c838fb60c | |||
| 0713ef5862 | |||
| bee1ba8854 | |||
| da252c7597 | |||
| a4460abc83 | |||
| 261636febb | |||
| 21f15f0a29 | |||
| bd068ff2a6 | |||
| d09f5c0e3a | |||
| 45140ca9f7 | |||
| c6be2e768a | |||
| 6339395cba | |||
| bd6492bb38 | |||
| f93b331817 | |||
| 20e4096c4b | |||
| 97952a9289 | |||
| 960a595268 | |||
| a3c94ef632 | |||
| 84fd38ac9c | |||
| 303a8fae32 | |||
| 21686ee8a9 | |||
| c8b142a676 | |||
| 58061a68c4 | |||
| 9c11197768 | |||
| f347efb006 | |||
| af8ddac2af | |||
| b1358de9bb | |||
| f4dc93ae66 | |||
| 20a77f6d51 |
@@ -13,3 +13,4 @@
|
|||||||
!profiles/*
|
!profiles/*
|
||||||
!profiles/lib/*
|
!profiles/lib/*
|
||||||
!profiles/examples/*
|
!profiles/examples/*
|
||||||
|
!scripts/node_install.sh
|
||||||
|
|||||||
+37
-27
@@ -7,10 +7,6 @@ git:
|
|||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
node_js:
|
|
||||||
- "4"
|
|
||||||
- "6"
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
|
||||||
@@ -72,7 +68,7 @@ matrix:
|
|||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
@@ -82,15 +78,15 @@ matrix:
|
|||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000 LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang-4.0-debug"
|
compiler: "clang-4.0-debug"
|
||||||
addons: &clang40
|
addons: &clang40
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
packages: ['libstdc++-4.9-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@@ -98,8 +94,8 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-4.9-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
|
||||||
|
|
||||||
# Release Builds
|
# Release Builds
|
||||||
- os: linux
|
- os: linux
|
||||||
@@ -107,7 +103,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-4.9-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@@ -115,7 +111,7 @@ matrix:
|
|||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@@ -129,7 +125,7 @@ matrix:
|
|||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
@@ -137,14 +133,22 @@ matrix:
|
|||||||
addons: &gcc49
|
addons: &gcc49
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev', 'ccache']
|
||||||
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
|
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
|
||||||
|
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode8.2
|
osx_image: xcode8.2
|
||||||
compiler: "mason-osx-release"
|
compiler: "mason-osx-release"
|
||||||
# we use the xcode provides clang and don't install our own
|
# we use the xcode provides clang and don't install our own
|
||||||
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
|
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="4"
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode8.2
|
||||||
|
compiler: "mason-osx-release"
|
||||||
|
# we use the xcode provides clang and don't install our own
|
||||||
|
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="6"
|
||||||
after_success:
|
after_success:
|
||||||
- ./scripts/travis/publish.sh
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
@@ -154,7 +158,7 @@ matrix:
|
|||||||
#- addons: &clang40
|
#- addons: &clang40
|
||||||
#- apt:
|
#- apt:
|
||||||
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
|
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
|
||||||
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release'
|
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release'
|
||||||
|
|
||||||
# Shared Library
|
# Shared Library
|
||||||
@@ -163,7 +167,7 @@ matrix:
|
|||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||||
|
|
||||||
# Disabled because CI slowness
|
# Disabled because CI slowness
|
||||||
@@ -172,7 +176,7 @@ matrix:
|
|||||||
#- addons: &clang40
|
#- addons: &clang40
|
||||||
#- apt:
|
#- apt:
|
||||||
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
|
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
|
||||||
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
|
||||||
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||||
|
|
||||||
# Node build jobs. These skip running the tests.
|
# Node build jobs. These skip running the tests.
|
||||||
@@ -182,7 +186,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-4.9-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
@@ -191,7 +195,8 @@ matrix:
|
|||||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
-DENABLE_CCACHE=ON \
|
-DENABLE_CCACHE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||||
|
-DENABLE_GLIBC_WORKAROUND=ON
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- popd
|
- popd
|
||||||
script:
|
script:
|
||||||
@@ -205,7 +210,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-4.9-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
@@ -214,7 +219,8 @@ matrix:
|
|||||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
-DENABLE_CCACHE=ON \
|
-DENABLE_CCACHE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||||
|
-DENABLE_GLIBC_WORKAROUND=ON
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- popd
|
- popd
|
||||||
script:
|
script:
|
||||||
@@ -228,7 +234,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-4.9-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
@@ -237,7 +243,8 @@ matrix:
|
|||||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
-DENABLE_CCACHE=ON \
|
-DENABLE_CCACHE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||||
|
-DENABLE_GLIBC_WORKAROUND=ON
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- popd
|
- popd
|
||||||
script:
|
script:
|
||||||
@@ -251,7 +258,7 @@ matrix:
|
|||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-4.9-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
@@ -260,7 +267,8 @@ matrix:
|
|||||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
-DENABLE_CCACHE=ON \
|
-DENABLE_CCACHE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||||
|
-DENABLE_GLIBC_WORKAROUND=ON
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- popd
|
- popd
|
||||||
script:
|
script:
|
||||||
@@ -334,7 +342,8 @@ install:
|
|||||||
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
|
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
|
||||||
-DBUILD_TOOLS=ON \
|
-DBUILD_TOOLS=ON \
|
||||||
-DENABLE_CCACHE=ON \
|
-DENABLE_CCACHE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||||
|
-DENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-OFF}
|
||||||
- echo "travis_fold:start:MAKE"
|
- echo "travis_fold:start:MAKE"
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- make tests --jobs=${JOBS}
|
- make tests --jobs=${JOBS}
|
||||||
@@ -361,6 +370,7 @@ script:
|
|||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
- ./unit_tests/library-tests
|
- ./unit_tests/library-tests
|
||||||
- ./unit_tests/extractor-tests
|
- ./unit_tests/extractor-tests
|
||||||
|
- ./unit_tests/contractor-tests
|
||||||
- ./unit_tests/engine-tests
|
- ./unit_tests/engine-tests
|
||||||
- ./unit_tests/util-tests
|
- ./unit_tests/util-tests
|
||||||
- ./unit_tests/server-tests
|
- ./unit_tests/server-tests
|
||||||
|
|||||||
@@ -1,3 +1,36 @@
|
|||||||
|
# UNRELEASED
|
||||||
|
- Profile:
|
||||||
|
- New function to support relations: `process_relation`. Read more in profiles documentation.
|
||||||
|
- Support of `distance` weight in foot and bicycle profiles
|
||||||
|
- Infrastructure:
|
||||||
|
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
|
||||||
|
- Node.js Bindings:
|
||||||
|
- Exposes `use_threads_number=Number` parameter of `EngineConfig` to limit a number of threads in a TBB internal pool
|
||||||
|
- Internals
|
||||||
|
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices
|
||||||
|
|
||||||
|
# 5.12.0
|
||||||
|
- Guidance
|
||||||
|
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways)
|
||||||
|
- Adds new instruction types at the exit of roundabouts and rotaries `exit roundabout` and `exit rotary`.
|
||||||
|
- HTTP:
|
||||||
|
- New query parameter for route/table/match/trip plugings:
|
||||||
|
`exclude=` that can be used to exclude certain classes (e.g. exclude=motorway, exclude=toll).
|
||||||
|
This is configurable in the profile.
|
||||||
|
- NodeJS:
|
||||||
|
- New query option `exclude` for the route/table/match/trip plugins. (e.g. `exclude: ["motorway", "toll"]`)
|
||||||
|
- Profile:
|
||||||
|
- New property for profile table: `excludable` that can be used to configure which classes are excludable at query time.
|
||||||
|
- New optional property for profile table: `classes` that allows you to specify which classes you expect to be used.
|
||||||
|
We recommend this for better error messages around classes, otherwise the possible class names are infered automatically.
|
||||||
|
- Traffic:
|
||||||
|
- If traffic data files contain an empty 4th column, they will update edge durations but not modify the edge weight. This is useful for
|
||||||
|
updating ETAs returned, without changing route selection (for example, in a distance-based profile with traffic data loaded).
|
||||||
|
- Infrastructure:
|
||||||
|
- New file `.osrm.cell_metrics` created by `osrm-customize`.
|
||||||
|
- Debug tiles:
|
||||||
|
- Added new properties `type` and `modifier` to `turns` layer, useful for viewing guidance calculated turn types on the map
|
||||||
|
|
||||||
# 5.11.0
|
# 5.11.0
|
||||||
- Changes from 5.10:
|
- Changes from 5.10:
|
||||||
- Features
|
- Features
|
||||||
|
|||||||
+17
-31
@@ -31,12 +31,13 @@ option(ENABLE_LTO "Use LTO if available" OFF)
|
|||||||
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
|
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
|
||||||
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
|
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
|
||||||
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
|
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
|
||||||
|
option(ENABLE_GLIBC_WORKAROUND "Workaround GLIBC symbol exports" OFF)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
if(ENABLE_MASON)
|
if(ENABLE_MASON)
|
||||||
# versions in use
|
# versions in use
|
||||||
set(MASON_BOOST_VERSION "1.63.0")
|
set(MASON_BOOST_VERSION "1.65.1")
|
||||||
set(MASON_STXXL_VERSION "1.4.1-1")
|
set(MASON_STXXL_VERSION "1.4.1-1")
|
||||||
set(MASON_EXPAT_VERSION "2.2.0")
|
set(MASON_EXPAT_VERSION "2.2.0")
|
||||||
set(MASON_LUA_VERSION "5.2.4")
|
set(MASON_LUA_VERSION "5.2.4")
|
||||||
@@ -60,7 +61,7 @@ if (POLICY CMP0048)
|
|||||||
endif()
|
endif()
|
||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
set(OSRM_VERSION_MAJOR 5)
|
||||||
set(OSRM_VERSION_MINOR 11)
|
set(OSRM_VERSION_MINOR 13)
|
||||||
set(OSRM_VERSION_PATCH 0)
|
set(OSRM_VERSION_PATCH 0)
|
||||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||||
|
|
||||||
@@ -379,8 +380,8 @@ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|||||||
|
|
||||||
# Activate C++1y
|
# Activate C++1y
|
||||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||||
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y")
|
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++14")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Configuring other platform dependencies
|
# Configuring other platform dependencies
|
||||||
@@ -468,7 +469,7 @@ if(ENABLE_MASON)
|
|||||||
install(FILES ${TBBGlob} DESTINATION lib)
|
install(FILES ${TBBGlob} DESTINATION lib)
|
||||||
endforeach()
|
endforeach()
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} -Wl,-rpath -Wl,@executable_path")
|
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} -Wl,-rpath -Wl,@loader_path")
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} '-Wl,-rpath,$ORIGIN' -Wl,-z,origin")
|
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} '-Wl,-rpath,$ORIGIN' -Wl,-z,origin")
|
||||||
endif()
|
endif()
|
||||||
@@ -517,29 +518,10 @@ else()
|
|||||||
find_package(BZip2 REQUIRED)
|
find_package(BZip2 REQUIRED)
|
||||||
add_dependency_includes(${BZIP2_INCLUDE_DIR})
|
add_dependency_includes(${BZIP2_INCLUDE_DIR})
|
||||||
|
|
||||||
FIND_PACKAGE(Lua 5.2 EXACT)
|
find_package(Lua 5.2 REQUIRED)
|
||||||
IF (LUA_FOUND)
|
if (LUA_FOUND)
|
||||||
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
|
message(STATUS "Using Lua ${LUA_VERSION_STRING}")
|
||||||
ELSE()
|
endif()
|
||||||
FIND_PACKAGE(Lua 5.1 EXACT)
|
|
||||||
IF (LUA_FOUND)
|
|
||||||
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
|
|
||||||
ELSE()
|
|
||||||
# Now fall back to a lua verison without exact
|
|
||||||
# in case this cmake version also forces patch versions
|
|
||||||
FIND_PACKAGE(Lua 5.2)
|
|
||||||
IF (LUA_FOUND)
|
|
||||||
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
|
|
||||||
ELSE()
|
|
||||||
FIND_PACKAGE(Lua 5.1)
|
|
||||||
IF (LUA_FOUND)
|
|
||||||
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
|
|
||||||
ELSE()
|
|
||||||
MESSAGE(FATAL_ERROR "Lua 5.1 or 5.2 was not found.")
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
|
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
|
||||||
add_dependency_includes(${LUA_INCLUDE_DIR})
|
add_dependency_includes(${LUA_INCLUDE_DIR})
|
||||||
@@ -692,10 +674,10 @@ set(UTIL_LIBRARIES
|
|||||||
# Libraries
|
# Libraries
|
||||||
target_link_libraries(osrm ${ENGINE_LIBRARIES})
|
target_link_libraries(osrm ${ENGINE_LIBRARIES})
|
||||||
target_link_libraries(osrm_update ${UPDATER_LIBRARIES})
|
target_link_libraries(osrm_update ${UPDATER_LIBRARIES})
|
||||||
target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES} osrm_update)
|
target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES} osrm_update osrm_store)
|
||||||
target_link_libraries(osrm_extract ${EXTRACTOR_LIBRARIES})
|
target_link_libraries(osrm_extract ${EXTRACTOR_LIBRARIES})
|
||||||
target_link_libraries(osrm_partition ${PARTITIONER_LIBRARIES})
|
target_link_libraries(osrm_partition ${PARTITIONER_LIBRARIES})
|
||||||
target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update)
|
target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update osrm_store)
|
||||||
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
||||||
|
|
||||||
# BUILD_COMPONENTS
|
# BUILD_COMPONENTS
|
||||||
@@ -738,7 +720,7 @@ file(GLOB VariantGlob third_party/variant/include/mapbox/*.hpp)
|
|||||||
file(GLOB LibraryGlob include/osrm/*.hpp)
|
file(GLOB LibraryGlob include/osrm/*.hpp)
|
||||||
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
|
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
|
||||||
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/approach.hpp include/engine/phantom_node.hpp)
|
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/approach.hpp include/engine/phantom_node.hpp)
|
||||||
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/alias.hpp include/util/exception.hpp)
|
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/alias.hpp include/util/exception.hpp include/util/bearing.hpp)
|
||||||
set(ExtractorHeader include/extractor/extractor.hpp include/storage/io_config.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
set(ExtractorHeader include/extractor/extractor.hpp include/storage/io_config.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
||||||
set(PartitionerHeader include/partition/partitioner.hpp include/partition/partition_config.hpp)
|
set(PartitionerHeader include/partition/partitioner.hpp include/partition/partition_config.hpp)
|
||||||
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
||||||
@@ -829,6 +811,10 @@ add_custom_target(uninstall
|
|||||||
add_subdirectory(unit_tests)
|
add_subdirectory(unit_tests)
|
||||||
add_subdirectory(src/benchmarks)
|
add_subdirectory(src/benchmarks)
|
||||||
|
|
||||||
|
if (ENABLE_GLIBC_WORKAROUND)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLIBC_WORKAROUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (ENABLE_NODE_BINDINGS)
|
if (ENABLE_NODE_BINDINGS)
|
||||||
add_subdirectory(src/nodejs)
|
add_subdirectory(src/nodejs)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ to always force building the Node.js bindings from source.
|
|||||||
|
|
||||||
For usage details have a look [these API docs](docs/nodejs/api.md).
|
For usage details have a look [these API docs](docs/nodejs/api.md).
|
||||||
|
|
||||||
|
An exemplary implementation by a 3rd party with Docker and Node.js can be found [here](https://github.com/door2door-io/osrm-express-server-demo).
|
||||||
|
|
||||||
|
|
||||||
## References in publications
|
## References in publications
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -7,19 +7,22 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||||||
SET PROJECT_DIR=%CD%
|
SET PROJECT_DIR=%CD%
|
||||||
ECHO PROJECT_DIR^: %PROJECT_DIR%
|
ECHO PROJECT_DIR^: %PROJECT_DIR%
|
||||||
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
|
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
|
||||||
|
|
||||||
|
|
||||||
|
:: Check CMake version
|
||||||
|
SET CMAKE_VERSION=3.9.2
|
||||||
|
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
|
||||||
ECHO cmake^: && cmake --version
|
ECHO cmake^: && cmake --version
|
||||||
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK
|
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK
|
||||||
|
|
||||||
cmake --version | findstr /C:"3.7.1" && GOTO CMAKE_OK
|
cmake --version | findstr /C:%CMAKE_VERSION% && GOTO CMAKE_OK
|
||||||
|
|
||||||
:CMAKE_NOT_OK
|
:CMAKE_NOT_OK
|
||||||
SET CMAKE_VERSION=3.7.1
|
|
||||||
ECHO CMAKE NOT OK - downloading new CMake %CMAKE_VERSION%
|
ECHO CMAKE NOT OK - downloading new CMake %CMAKE_VERSION%
|
||||||
IF NOT EXIST cm.zip powershell Invoke-WebRequest https://cmake.org/files/v3.7/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
|
powershell Invoke-WebRequest https://cmake.org/files/v3.9/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
IF NOT EXIST cmake-%CMAKE_VERSION%-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
|
IF NOT EXIST cmake-%CMAKE_VERSION%-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
|
|
||||||
|
|
||||||
:CMAKE_OK
|
:CMAKE_OK
|
||||||
ECHO CMAKE_OK
|
ECHO CMAKE_OK
|
||||||
@@ -37,7 +40,7 @@ ECHO msbuild version
|
|||||||
msbuild /version
|
msbuild /version
|
||||||
|
|
||||||
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
|
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
|
||||||
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
|
SET DEPSPKG=osrm-deps-win-x64-14.0-2017.09.7z
|
||||||
|
|
||||||
:: local development
|
:: local development
|
||||||
ECHO.
|
ECHO.
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
# This is because, the lua location is not standardized and may exist in
|
# This is because, the lua location is not standardized and may exist in
|
||||||
# locations other than lua/
|
# locations other than lua/
|
||||||
|
|
||||||
|
include(FindPkgConfig)
|
||||||
|
|
||||||
unset(_lua_include_subdirs)
|
unset(_lua_include_subdirs)
|
||||||
unset(_lua_library_names)
|
unset(_lua_library_names)
|
||||||
unset(_lua_append_versions)
|
unset(_lua_append_versions)
|
||||||
@@ -81,6 +83,7 @@ function(_lua_set_version_vars)
|
|||||||
lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||||
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||||
)
|
)
|
||||||
|
pkg_check_modules(LUA QUIET "lua${ver}")
|
||||||
endforeach ()
|
endforeach ()
|
||||||
|
|
||||||
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
|
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
|
||||||
|
|||||||
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
default: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions',
|
default: '--strict --tags ~@stress --tags ~@mld --tags ~@todo --require features/support --require features/step_definitions',
|
||||||
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
verify: '--strict --tags ~@stress --tags ~@mld --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
||||||
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||||
all: '--strict --require features/support --require features/step_definitions',
|
all: '--strict --require features/support --require features/step_definitions',
|
||||||
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --require features/support --require features/step_definitions -f progress'
|
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@ch --require features/support --require features/step_definitions -f progress'
|
||||||
}
|
};
|
||||||
|
|||||||
+3
-3
@@ -7,7 +7,7 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
|||||||
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
||||||
apk update && \
|
apk update && \
|
||||||
apk upgrade && \
|
apk upgrade && \
|
||||||
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.1-dev libtbb@testing libtbb-dev@testing && \
|
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.2-dev libtbb@testing libtbb-dev@testing && \
|
||||||
\
|
\
|
||||||
echo "Building libstxxl" && \
|
echo "Building libstxxl" && \
|
||||||
cd /opt && \
|
cd /opt && \
|
||||||
@@ -46,8 +46,8 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
|||||||
rm /usr/local/lib/libstxxl* && \
|
rm /usr/local/lib/libstxxl* && \
|
||||||
cd /opt && \
|
cd /opt && \
|
||||||
apk del boost-dev && \
|
apk del boost-dev && \
|
||||||
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.1-dev git make gcc && \
|
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.2-dev git make gcc && \
|
||||||
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.1 expat && \
|
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat && \
|
||||||
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
|
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
|
||||||
|
|
||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ A guard (ScopedGeojsonLoggerGuard) requires a logging policy. Per default we pro
|
|||||||
|
|
||||||
The initialisation to do so looks like this:
|
The initialisation to do so looks like this:
|
||||||
`util::ScopedGeojsonLoggerGuard<util::NodeIdVectorToLineString> geojson_guard( "debug.geojson", data-for-conversion);`
|
`util::ScopedGeojsonLoggerGuard<util::NodeIdVectorToLineString> geojson_guard( "debug.geojson", data-for-conversion);`
|
||||||
Make sure to give the guar a name, so it actually gets a lifetime.
|
Make sure to give the guard a name, so it actually gets a lifetime.
|
||||||
|
|
||||||
The field `data-for-conversion` can be an arbitrary long set of features and needs to match the parameters used for constructing our policy (in this case `util::NodeIdVectorToLineString`).
|
The field `data-for-conversion` can be an arbitrary long set of features and needs to match the parameters used for constructing our policy (in this case `util::NodeIdVectorToLineString`).
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -31,6 +31,7 @@ To pass parameters to each location some options support an array like encoding:
|
|||||||
|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. |
|
|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. |
|
||||||
|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. |
|
|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. |
|
||||||
|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curb side. |
|
|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curb side. |
|
||||||
|
|exclude |`{class}[,{class}]` |Additive list of classes to avoid, order does not matter. |
|
||||||
|
|
||||||
Where the elements follow the following format:
|
Where the elements follow the following format:
|
||||||
|
|
||||||
@@ -40,12 +41,13 @@ Where the elements follow the following format:
|
|||||||
|radius |`double >= 0` or `unlimited` (default) |
|
|radius |`double >= 0` or `unlimited` (default) |
|
||||||
|hint |Base64 `string` |
|
|hint |Base64 `string` |
|
||||||
|approach |`curb` or `unrestricted` (default) |
|
|approach |`curb` or `unrestricted` (default) |
|
||||||
|
|class |A class name determined by the profile or `none`. |
|
||||||
|
|
||||||
```
|
```
|
||||||
{option}={element};{element}[;{element} ... ]
|
{option}={element};{element}[;{element} ... ]
|
||||||
```
|
```
|
||||||
|
|
||||||
The number of elements must match exactly the number of locations. If you don't want to pass a value but instead use the default you can pass an empty `element`.
|
The number of elements must match exactly the number of locations (except for `generate_hints` and `exclude`). If you don't want to pass a value but instead use the default you can pass an empty `element`.
|
||||||
|
|
||||||
Example: 2nd location use the default value for `option`:
|
Example: 2nd location use the default value for `option`:
|
||||||
|
|
||||||
@@ -59,6 +61,9 @@ Example: 2nd location use the default value for `option`:
|
|||||||
# Query on Berlin with three coordinates:
|
# Query on Berlin with three coordinates:
|
||||||
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false'
|
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false'
|
||||||
|
|
||||||
|
# Query on Berlin excluding the usage of motorways:
|
||||||
|
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407?exclude=motorway'
|
||||||
|
|
||||||
# Using polyline:
|
# Using polyline:
|
||||||
curl 'http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false'
|
curl 'http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false'
|
||||||
```
|
```
|
||||||
@@ -432,6 +437,8 @@ Vector tiles contain two layers:
|
|||||||
| `turn_angle` | `integer` | the angle of the turn, relative to the `bearing_in`. -180 to +180, 0 = straight ahead, 90 = 90-degrees to the right |
|
| `turn_angle` | `integer` | the angle of the turn, relative to the `bearing_in`. -180 to +180, 0 = straight ahead, 90 = 90-degrees to the right |
|
||||||
| `cost` | `float` | the time we think it takes to make that turn, in seconds. May be negative, depending on how the data model is constructed (some turns get a "bonus"). |
|
| `cost` | `float` | the time we think it takes to make that turn, in seconds. May be negative, depending on how the data model is constructed (some turns get a "bonus"). |
|
||||||
| `weight` | `float` | the weight we think it takes to make that turn. May be negative, depending on how the data model is constructed (some turns get a "bonus"). ACTUAL ROUTING USES THIS VALUE |
|
| `weight` | `float` | the weight we think it takes to make that turn. May be negative, depending on how the data model is constructed (some turns get a "bonus"). ACTUAL ROUTING USES THIS VALUE |
|
||||||
|
| `type` | `string` | the type of this turn - values like `turn`, `continue`, etc. See the `StepManeuver` for a partial list, this field also exposes internal turn types that are never returned with an API response |
|
||||||
|
| `modifier` | `string` | the direction modifier of the turn (`left`, `sharp left`, etc) |
|
||||||
|
|
||||||
|
|
||||||
## Result objects
|
## Result objects
|
||||||
@@ -661,6 +668,8 @@ step.
|
|||||||
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
|
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
|
||||||
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
|
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
|
||||||
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode or classes. If the road takes a turn itself, the `modifier` describes the direction |
|
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode or classes. If the road takes a turn itself, the `modifier` describes the direction |
|
||||||
|
| `exit roundabout`| Describes a maneuver exiting a roundabout (usually preceeded by a `roundabout` instruction) |
|
||||||
|
| `exit rotary` | Describes the maneuver exiting a rotary (large named roundabout) |
|
||||||
|
|
||||||
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
|
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
|
||||||
between all instructions. They only offer a fallback in case nothing else is to report.
|
between all instructions. They only offer a fallback in case nothing else is to report.
|
||||||
|
|||||||
+64
-2
@@ -104,7 +104,17 @@ max_speed_for_map_matching | Float | Maximum vehicle speed to be as
|
|||||||
max_turn_weight | Float | Maximum turn penalty weight
|
max_turn_weight | Float | Maximum turn penalty weight
|
||||||
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `process_segment` will be called for all segments (default `false`)
|
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `process_segment` will be called for all segments (default `false`)
|
||||||
|
|
||||||
### process_node(profile, node, result)
|
The following additional global properties can be set in the hash you return in the `setup` function:
|
||||||
|
|
||||||
|
Attribute | Type | Notes
|
||||||
|
-------------------------------------|------------------|----------------------------------------------------------------------------
|
||||||
|
excludable | Sequence of Sets | Determines which class-combinations are supported by the `exclude` option at query time.
|
||||||
|
| | E.g. `Sequence{Set{"ferry", "motorway"}, Set{"motorway"}}` will allow you to exclude ferries and motorways, or only motorways.
|
||||||
|
classes | Sequence | Determines the allowed classes that can be referenced using `{forward,backward}_classes` on the way in the `process_way` function.
|
||||||
|
restrictions | Sequence | Determines which turn restrictions will be used for this profile.
|
||||||
|
suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES".
|
||||||
|
|
||||||
|
### process_node(profile, node, result, relations)
|
||||||
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
|
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
|
||||||
|
|
||||||
Argument | Description
|
Argument | Description
|
||||||
@@ -112,6 +122,7 @@ Argument | Description
|
|||||||
profile | The configuration table you returned in `setup`.
|
profile | The configuration table you returned in `setup`.
|
||||||
node | The input node to process (read-only).
|
node | The input node to process (read-only).
|
||||||
result | The output that you will modify.
|
result | The output that you will modify.
|
||||||
|
relations| The list of relation attributes passed from `process_relation` function for this node.
|
||||||
|
|
||||||
The following attributes can be set on `result`:
|
The following attributes can be set on `result`:
|
||||||
|
|
||||||
@@ -120,7 +131,7 @@ Attribute | Type | Notes
|
|||||||
barrier | Boolean | Is it an impassable barrier?
|
barrier | Boolean | Is it an impassable barrier?
|
||||||
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
|
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
|
||||||
|
|
||||||
## process_way(profile, way, result)
|
### process_way(profile, way, result, relations)
|
||||||
Given an OpenStreetMap way, the `process_way` function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash.
|
Given an OpenStreetMap way, the `process_way` function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash.
|
||||||
|
|
||||||
Argument | Description
|
Argument | Description
|
||||||
@@ -128,6 +139,7 @@ Argument | Description
|
|||||||
profile | The configuration table you returned in `setup`.
|
profile | The configuration table you returned in `setup`.
|
||||||
node | The input way to process (read-only).
|
node | The input way to process (read-only).
|
||||||
result | The output that you will modify.
|
result | The output that you will modify.
|
||||||
|
relations| The list of relation attributes passed from `process_relation` function for this way.
|
||||||
|
|
||||||
Importantly it will set `result.forward_mode` and `result.backward_mode` to indicate the travel mode in each direction, as well as set `result.forward_speed` and `result.backward_speed` to integer values representing the speed for traversing the way.
|
Importantly it will set `result.forward_mode` and `result.backward_mode` to indicate the travel mode in each direction, as well as set `result.forward_speed` and `result.backward_speed` to integer values representing the speed for traversing the way.
|
||||||
|
|
||||||
@@ -167,6 +179,56 @@ road_classification.road_priority_class | Enum | Guidance: order in priority
|
|||||||
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
||||||
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
||||||
|
|
||||||
|
### process_relation(profile, relation, result)
|
||||||
|
|
||||||
|
Supported since API **version 3**.
|
||||||
|
|
||||||
|
Given an OpenStreetMap relation, the `process_relation` function should setup values into result structure.
|
||||||
|
|
||||||
|
Argument | Description
|
||||||
|
---------|-------------------------------------------------------
|
||||||
|
profile | The configuration table you returned in `setup`.
|
||||||
|
node | The input relation to process (read-only).
|
||||||
|
result | The output that you will modify.
|
||||||
|
|
||||||
|
Relation process work flow consist of next steps:
|
||||||
|
1. Calls `process_relation` function for each relation. It should fill a `result` structure
|
||||||
|
2. After that each data will be passed for each member of processed relation into `process_node` and `process_way` functions
|
||||||
|
|
||||||
|
The following attributes can be set on that result in `process_relation`:
|
||||||
|
|
||||||
|
Attribute | Type | Notes
|
||||||
|
----------------------------------------|----------|--------------------------------------------------------------------------
|
||||||
|
is_restriction | Boolean | Flag to determine if relation is a turn restriction
|
||||||
|
|
||||||
|
Example processing code:
|
||||||
|
```lua
|
||||||
|
|
||||||
|
function process_way(profile, way, result, relations)
|
||||||
|
for _, r in ipairs(relations) do
|
||||||
|
for k, v in pairs(r) do
|
||||||
|
print('data_' .. k .. '_value_' .. v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print ('process_way ' .. way:id() .. ' ' .. result.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_relation(profile, relation, result)
|
||||||
|
local t = relation:get_value_by_key("type")
|
||||||
|
if t == "route" then
|
||||||
|
for _, m in ipairs(relation:members()) do
|
||||||
|
if m:role == "north" then
|
||||||
|
result[m]['direction'] = 'north'
|
||||||
|
print('direction_north')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print('route_relation')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### process_segment(profile, segment)
|
### process_segment(profile, segment)
|
||||||
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
|
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
@routing @bicycle
|
||||||
|
Feature: Bike - Use distance weight
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
|
Scenario: Bike - Check distance weight
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
local functions = require('bicycle')
|
||||||
|
functions.setup_testbot = functions.setup
|
||||||
|
|
||||||
|
functions.setup = function()
|
||||||
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.weight_name = 'distance'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-b-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | residential |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | weight | time | distance |
|
||||||
|
| a | b | abc,abc | 200 | 48s | 200m +-1 |
|
||||||
|
| a | c | abc,abc | 400 | 96s | 400m +-1 |
|
||||||
@@ -122,6 +122,6 @@ Feature: Car - Mode flag
|
|||||||
| df | yes | motorway| | yes |
|
| df | yes | motorway| | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | turns | classes |
|
| from | to | route | turns | classes |
|
||||||
| a | f | ab,df,df | depart,roundabout-exit-2,arrive | [()],[(),(motorway),(toll,motorway)],[()] |
|
| a | f | ab,df,df,df | depart,roundabout-exit-2,exit roundabout slight right,arrive | [()],[(),(motorway)],[(toll,motorway)],[()] |
|
||||||
|
|
||||||
|
|||||||
@@ -47,32 +47,3 @@ Feature: Testbot - side bias
|
|||||||
| d | a | bd,ab,ab | 27s +-1 |
|
| d | a | bd,ab,ab | 27s +-1 |
|
||||||
# should be inverse of left hand bias
|
# should be inverse of left hand bias
|
||||||
| d | c | bd,bc,bc | 24s +-1 |
|
| d | c | bd,bc,bc | 24s +-1 |
|
||||||
|
|
||||||
Scenario: Roundabout exit counting for left sided driving
|
|
||||||
Given the profile file "testbot" initialized with
|
|
||||||
"""
|
|
||||||
profile.left_hand_driving = true
|
|
||||||
profile.turn_bias = 1/1.075
|
|
||||||
"""
|
|
||||||
And a grid size of 10 meters
|
|
||||||
And the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
h g c d
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
|
|
||||||
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
|
|
||||||
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
@routing @foot
|
||||||
|
Feature: Foot - Use distance weight
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
|
Scenario: Foot - Check distance weight
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
local functions = require('foot')
|
||||||
|
functions.setup_testbot = functions.setup
|
||||||
|
|
||||||
|
functions.setup = function()
|
||||||
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.weight_name = 'distance'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-b-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | residential |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | weight | time | distance |
|
||||||
|
| a | b | abc,abc | 200 | 144s | 200m +-1 |
|
||||||
|
| a | c | abc,abc | 400 | 288s | 400m +-1 |
|
||||||
@@ -553,8 +553,8 @@ Feature: Turn Lane Guidance
|
|||||||
| fy | | primary | |
|
| fy | | primary | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,h | ab,gh,gh | depart,roundabout-exit-5,arrive | ,;;;;;, |
|
| a,h | ab,gh,gh,gh | depart,roundabout-exit-5,exit roundabout right,arrive | ,;;;;,, |
|
||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
Scenario: No Lanes for Roundabouts, see #2626
|
Scenario: No Lanes for Roundabouts, see #2626
|
||||||
@@ -569,16 +569,16 @@ Feature: Turn Lane Guidance
|
|||||||
| nodes | turn:lanes:forward | highway | junction | name |
|
| nodes | turn:lanes:forward | highway | junction | name |
|
||||||
| xb | slight_right\|slight_right | primary | | xb |
|
| xb | slight_right\|slight_right | primary | | xb |
|
||||||
| dy | | primary | | dy |
|
| dy | | primary | | dy |
|
||||||
| ab | | primary | roundabout | roundabout |
|
| ab | | primary | roundabout | rotary |
|
||||||
| bc | | primary | roundabout | roundabout |
|
| bc | | primary | roundabout | rotary |
|
||||||
| cd | left\|slight_right | primary | roundabout | roundabout |
|
| cd | left\|slight_right | primary | roundabout | rotary |
|
||||||
| da | | primary | roundabout | roundabout |
|
| da | | primary | roundabout | rotary |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| x,y | xb,dy,dy | depart,roundabout-exit-1,arrive | ,;, |
|
| x,y | xb,dy,dy,dy | depart,rotary-exit-1,exit rotary right,arrive | ,,, |
|
||||||
| x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,, |
|
| x,c | xb,rotary,rotary | depart,rotary-exit-undefined,arrive | ,, |
|
||||||
| x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,;, |
|
| x,a | xb,rotary,rotary | depart,rotary-exit-undefined,arrive | ,;, |
|
||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
Scenario: No Lanes for Roundabouts, see #2626
|
Scenario: No Lanes for Roundabouts, see #2626
|
||||||
@@ -614,8 +614,8 @@ Feature: Turn Lane Guidance
|
|||||||
| fy | | primary | |
|
| fy | | primary | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,h | ab,ch,ch | depart,roundabout-exit-5,arrive | ,;;;;;, |
|
| a,h | ab,ch,ch,ch | depart,roundabout-exit-5,exit roundabout left,arrive | ,;;;;,, |
|
||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
Scenario: No Lanes for Roundabouts, see #2626
|
Scenario: No Lanes for Roundabouts, see #2626
|
||||||
@@ -635,16 +635,16 @@ Feature: Turn Lane Guidance
|
|||||||
| nodes | turn:lanes:forward | highway | junction | name |
|
| nodes | turn:lanes:forward | highway | junction | name |
|
||||||
| xb | slight_right\|slight_right | primary | | xb |
|
| xb | slight_right\|slight_right | primary | | xb |
|
||||||
| dy | | primary | | dy |
|
| dy | | primary | | dy |
|
||||||
| ab | | primary | roundabout | roundabout |
|
| ab | | primary | roundabout | rotary |
|
||||||
| bc | | primary | roundabout | roundabout |
|
| bc | | primary | roundabout | rotary |
|
||||||
| cd | left\|slight_right | primary | roundabout | roundabout |
|
| cd | left\|slight_right | primary | roundabout | rotary |
|
||||||
| da | | primary | roundabout | roundabout |
|
| da | | primary | roundabout | rotary |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| x,y | xb,dy,dy | depart,roundabout-exit-1,arrive | ,;, |
|
| x,y | xb,dy,dy,dy | depart,rotary-exit-1,exit rotary right,arrive | ,,, |
|
||||||
| x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,, |
|
| x,c | xb,rotary,rotary | depart,rotary-exit-undefined,arrive | ,, |
|
||||||
| x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,;, |
|
| x,a | xb,rotary,rotary | depart,rotary-exit-undefined,arrive | ,;, |
|
||||||
|
|
||||||
@anticipate @todo @2032
|
@anticipate @todo @2032
|
||||||
Scenario: No Lanes for Roundabouts, see #2626
|
Scenario: No Lanes for Roundabouts, see #2626
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
@routing @guidance
|
@routing @guidance
|
||||||
Feature: Rotary
|
Feature: Circular
|
||||||
|
|
||||||
|
# Circular tags are treated just as rotaries. We can rely on the rotary tests for their handling on special cases.
|
||||||
|
# Here we only ensure that the `circular` tag is handled and assigned a rotary type
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "car"
|
Given the profile "car"
|
||||||
@@ -24,259 +27,16 @@ Feature: Rotary
|
|||||||
| bgecb | circular |
|
| bgecb | circular |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,bgecb-exit-3,arrive |
|
| a,d | ab,cd,cd,cd | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| a,f | ab,ef,ef | depart,bgecb-exit-2,arrive |
|
| a,f | ab,ef,ef,ef | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| a,h | ab,gh,gh | depart,bgecb-exit-1,arrive |
|
| a,h | ab,gh,gh,gh | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
| d,f | cd,ef,ef | depart,bgecb-exit-3,arrive |
|
| d,f | cd,ef,ef,ef | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| d,h | cd,gh,gh | depart,bgecb-exit-2,arrive |
|
| d,h | cd,gh,gh,gh | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| d,a | cd,ab,ab | depart,bgecb-exit-1,arrive |
|
| d,a | cd,ab,ab,ab | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
| f,h | ef,gh,gh | depart,bgecb-exit-3,arrive |
|
| f,h | ef,gh,gh,gh | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| f,a | ef,ab,ab | depart,bgecb-exit-2,arrive |
|
| f,a | ef,ab,ab,ab | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| f,d | ef,cd,cd | depart,bgecb-exit-1,arrive |
|
| f,d | ef,cd,cd,cd | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
| h,a | gh,ab,ab | depart,bgecb-exit-3,arrive |
|
| h,a | gh,ab,ab,ab | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| h,d | gh,cd,cd | depart,bgecb-exit-2,arrive |
|
| h,d | gh,cd,cd,cd | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| h,f | gh,ef,ef | depart,bgecb-exit-1,arrive |
|
| h,f | gh,ef,ef,ef | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
|
|
||||||
Scenario: Only Enter
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | circular |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,c | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| a,e | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| a,g | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| d,e | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| d,g | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| d,b | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| f,g | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| f,b | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| f,c | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| h,b | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| h,c | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| h,e | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
|
|
||||||
Scenario: Only Exit
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | circular |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| b,d | bcegb,cd,cd | depart,bcegb-exit-1,arrive |
|
|
||||||
| b,f | bcegb,ef,ef | depart,bcegb-exit-2,arrive |
|
|
||||||
| b,h | bcegb,gh,gh | depart,bcegb-exit-3,arrive |
|
|
||||||
| c,f | bcegb,ef,ef | depart,bcegb-exit-1,arrive |
|
|
||||||
| c,h | bcegb,gh,gh | depart,bcegb-exit-2,arrive |
|
|
||||||
| c,a | bcegb,ab,ab | depart,bcegb-exit-3,arrive |
|
|
||||||
| e,h | bcegb,gh,gh | depart,bcegb-exit-1,arrive |
|
|
||||||
| e,a | bcegb,ab,ab | depart,bcegb-exit-2,arrive |
|
|
||||||
| e,d | bcegb,cd,cd | depart,bcegb-exit-3,arrive |
|
|
||||||
| g,a | bcegb,ab,ab | depart,bcegb-exit-1,arrive |
|
|
||||||
| g,d | bcegb,cd,cd | depart,bcegb-exit-2,arrive |
|
|
||||||
| g,f | bcegb,ef,ef | depart,bcegb-exit-3,arrive |
|
|
||||||
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
|
||||||
|
|
||||||
Scenario: Drive Around
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | circular |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| b,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| b,e | bcegb,bcegb | depart,arrive |
|
|
||||||
| b,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,e | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,e | bcegb,bcegb | depart,arrive |
|
|
||||||
|
|
||||||
#needs to be adjusted when name-discovery works for entrys
|
|
||||||
Scenario: Mixed Entry and Exit
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
c a
|
|
||||||
j b f
|
|
||||||
k e
|
|
||||||
l h d
|
|
||||||
g i
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction | oneway |
|
|
||||||
| abc | | yes |
|
|
||||||
| def | | yes |
|
|
||||||
| ghi | | yes |
|
|
||||||
| jkl | | yes |
|
|
||||||
| bkheb | circular | yes |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,c | abc,abc,abc | depart,rotary-exit-1,arrive |
|
|
||||||
| a,l | abc,jkl,jkl | depart,bkheb-exit-2,arrive |
|
|
||||||
| a,i | abc,ghi,ghi | depart,bkheb-exit-3,arrive |
|
|
||||||
| a,f | abc,def,def | depart,bkheb-exit-4,arrive |
|
|
||||||
| d,f | def,def,def | depart,rotary-exit-1,arrive |
|
|
||||||
| d,c | def,abc,abc | depart,bkheb-exit-2,arrive |
|
|
||||||
| d,l | def,jkl,jkl | depart,bkheb-exit-3,arrive |
|
|
||||||
| d,i | def,ghi,ghi | depart,bkheb-exit-4,arrive |
|
|
||||||
| g,i | ghi,ghi,ghi | depart,rotary-exit-1,arrive |
|
|
||||||
| g,f | ghi,def,def | depart,bkheb-exit-2,arrive |
|
|
||||||
| g,c | ghi,abc,abc | depart,bkheb-exit-3,arrive |
|
|
||||||
| g,l | ghi,jkl,jkl | depart,bkheb-exit-4,arrive |
|
|
||||||
| j,l | jkl,jkl,jkl | depart,rotary-exit-1,arrive |
|
|
||||||
| j,i | jkl,ghi,ghi | depart,bkheb-exit-2,arrive |
|
|
||||||
| j,f | jkl,def,def | depart,bkheb-exit-3,arrive |
|
|
||||||
| j,c | jkl,abc,abc | depart,bkheb-exit-4,arrive |
|
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
c d f
|
|
||||||
e
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| bcdb | circular |
|
|
||||||
| ce | |
|
|
||||||
| df | |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
|
|
||||||
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
|
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
d
|
|
||||||
b c f
|
|
||||||
e
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ad | |
|
|
||||||
| bcdb | circular |
|
|
||||||
| be | |
|
|
||||||
| cf | |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,e | ad,be,be | depart,bcdb-exit-1,arrive |
|
|
||||||
| a,f | ad,cf,cf | depart,bcdb-exit-2,arrive |
|
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
c
|
|
||||||
d b f
|
|
||||||
e
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ac | |
|
|
||||||
| bcdb | circular |
|
|
||||||
| de | |
|
|
||||||
| bf | |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,e | ac,de,de | depart,bcdb-exit-1,arrive |
|
|
||||||
| a,f | ac,bf,bf | depart,bcdb-exit-2,arrive |
|
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
f
|
|
||||||
d c e
|
|
||||||
b
|
|
||||||
a
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| bcdb | circular |
|
|
||||||
| ce | |
|
|
||||||
| df | |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
|
|
||||||
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
|
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
f
|
|
||||||
d c e
|
|
||||||
b
|
|
||||||
a
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| bcdb | circular |
|
|
||||||
| ce | |
|
|
||||||
| df | |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
|
|
||||||
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
|
|
||||||
|
|||||||
@@ -905,8 +905,8 @@ Feature: Slipways and Dedicated Turn Lanes
|
|||||||
| restriction | yb | be | b | only_straight |
|
| restriction | yb | be | b | only_straight |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| z,t | through,,out,out | depart,off ramp slight right,round-exit-3,arrive | z,s,c,t |
|
| z,t | through,,out,out,out | depart,off ramp slight right,round-exit-3,exit rotary right,arrive | z,s,c,e,t |
|
||||||
|
|
||||||
Scenario: Sliproad before a roundabout
|
Scenario: Sliproad before a roundabout
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -942,8 +942,8 @@ Feature: Slipways and Dedicated Turn Lanes
|
|||||||
| restriction | bc | cd | c | only_straight |
|
| restriction | bc | cd | c | only_straight |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,k | road,,, | depart,turn right,roundabout turn right exit-1,arrive | a,b,h,k |
|
| a,k | road,,, | depart,turn right,roundabout turn right exit-1,arrive | a,b,h,k |
|
||||||
|
|
||||||
@sliproads
|
@sliproads
|
||||||
Scenario: Sliproad with 4 roads at target
|
Scenario: Sliproad with 4 roads at target
|
||||||
|
|||||||
@@ -24,6 +24,25 @@ Feature: End Of Road Instructions
|
|||||||
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
|
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
|
||||||
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |
|
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |
|
||||||
|
|
||||||
|
# http://map.project-osrm.org/?z=18¢er=38.906632%2C-77.008265&loc=38.906463%2C-77.007621&loc=38.906822%2C-77.008860&hl=en&alt=0
|
||||||
|
Scenario: End of Road, unnamed oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
c
|
||||||
|
a e b
|
||||||
|
f d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway |
|
||||||
|
| aeb | primary | road | yes |
|
||||||
|
| cbd | primary | | yes |
|
||||||
|
| ef | primary | turn | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | road,, | depart,end of road right,arrive |
|
||||||
|
|
||||||
@3605
|
@3605
|
||||||
Scenario: End of Road with oneway through street
|
Scenario: End of Road with oneway through street
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@@ -140,9 +140,9 @@ Feature: Intersections Data
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | intersections |
|
| waypoints | route | intersections |
|
||||||
| e,f | ea,fb,fb | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 |
|
| e,f | ea,fb,fb,fb | true:180;false:0 false:150 true:210;false:30 true:150 true:270;true:90 |
|
||||||
| e,g | ea,gc,gc | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0 |
|
| e,g | ea,gc,gc,gc | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:30 true:180 false:330;true:0 |
|
||||||
| e,h | ea,hd,hd | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 |
|
| e,h | ea,hd,hd,hd | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:90 false:210 true:330;true:270 |
|
||||||
| e,2 | ea,abcda,abcda | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1 |
|
| e,2 | ea,abcda,abcda | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1 |
|
||||||
| 1,g | abcda,gc,gc | true:214;false:30 true:150 true:270,true:30 true:180 false:330;true:0 |
|
| 1,g | abcda,gc,gc | true:214,false:30 true:150 true:270;true:30 true:180 false:330;true:0 |
|
||||||
| 1,3 | abcda,abcda | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214 |
|
| 1,3 | abcda,abcda | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214 |
|
||||||
|
|||||||
@@ -1,177 +0,0 @@
|
|||||||
@routing @guidance
|
|
||||||
Feature: Rotary
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the profile "bicycle"
|
|
||||||
Given a grid size of 30 meters
|
|
||||||
|
|
||||||
Scenario: Enter and Exit
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
h g c d
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bgecb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,d | ab,cd,cd | depart,bgecb-exit-3,arrive |
|
|
||||||
| a,f | ab,ef,ef | depart,bgecb-exit-2,arrive |
|
|
||||||
| a,h | ab,gh,gh | depart,bgecb-exit-1,arrive |
|
|
||||||
| d,f | cd,ef,ef | depart,bgecb-exit-3,arrive |
|
|
||||||
| d,h | cd,gh,gh | depart,bgecb-exit-2,arrive |
|
|
||||||
| d,a | cd,ab,ab | depart,bgecb-exit-1,arrive |
|
|
||||||
| f,h | ef,gh,gh | depart,bgecb-exit-3,arrive |
|
|
||||||
| f,a | ef,ab,ab | depart,bgecb-exit-2,arrive |
|
|
||||||
| f,d | ef,cd,cd | depart,bgecb-exit-1,arrive |
|
|
||||||
| h,a | gh,ab,ab | depart,bgecb-exit-3,arrive |
|
|
||||||
| h,d | gh,cd,cd | depart,bgecb-exit-2,arrive |
|
|
||||||
| h,f | gh,ef,ef | depart,bgecb-exit-1,arrive |
|
|
||||||
|
|
||||||
Scenario: Only Enter
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,c | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| a,e | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| a,g | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| d,e | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| d,g | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| d,b | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| f,g | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| f,b | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| f,c | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| h,b | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| h,c | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
| h,e | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
|
|
||||||
|
|
||||||
Scenario: Only Exit
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| b,d | bcegb,cd,cd | depart,bcegb-exit-1,arrive |
|
|
||||||
| b,f | bcegb,ef,ef | depart,bcegb-exit-2,arrive |
|
|
||||||
| b,h | bcegb,gh,gh | depart,bcegb-exit-3,arrive |
|
|
||||||
| c,f | bcegb,ef,ef | depart,bcegb-exit-1,arrive |
|
|
||||||
| c,h | bcegb,gh,gh | depart,bcegb-exit-2,arrive |
|
|
||||||
| c,a | bcegb,ab,ab | depart,bcegb-exit-3,arrive |
|
|
||||||
| e,h | bcegb,gh,gh | depart,bcegb-exit-1,arrive |
|
|
||||||
| e,a | bcegb,ab,ab | depart,bcegb-exit-2,arrive |
|
|
||||||
| e,d | bcegb,cd,cd | depart,bcegb-exit-3,arrive |
|
|
||||||
| g,a | bcegb,ab,ab | depart,bcegb-exit-1,arrive |
|
|
||||||
| g,d | bcegb,cd,cd | depart,bcegb-exit-2,arrive |
|
|
||||||
| g,f | bcegb,ef,ef | depart,bcegb-exit-3,arrive |
|
|
||||||
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
|
||||||
|
|
||||||
Scenario: Drive Around
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| b,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| b,e | bcegb,bcegb | depart,arrive |
|
|
||||||
| b,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,e | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,e | bcegb,bcegb | depart,arrive |
|
|
||||||
|
|
||||||
#needs to be adjusted when name-discovery works for entrys
|
|
||||||
Scenario: Mixed Entry and Exit
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
c a
|
|
||||||
j b f
|
|
||||||
k e
|
|
||||||
l h d
|
|
||||||
g i
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction | oneway |
|
|
||||||
| abc | | yes |
|
|
||||||
| def | | yes |
|
|
||||||
| ghi | | yes |
|
|
||||||
| jkl | | yes |
|
|
||||||
| bkheb | roundabout | yes |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,c | abc,abc,abc | depart,rotary-exit-1,arrive |
|
|
||||||
| a,l | abc,jkl,jkl | depart,bkheb-exit-2,arrive |
|
|
||||||
| a,i | abc,ghi,ghi | depart,bkheb-exit-3,arrive |
|
|
||||||
| a,f | abc,def,def | depart,bkheb-exit-4,arrive |
|
|
||||||
| d,f | def,def,def | depart,rotary-exit-1,arrive |
|
|
||||||
| d,c | def,abc,abc | depart,bkheb-exit-2,arrive |
|
|
||||||
| d,l | def,jkl,jkl | depart,bkheb-exit-3,arrive |
|
|
||||||
| d,i | def,ghi,ghi | depart,bkheb-exit-4,arrive |
|
|
||||||
| g,i | ghi,ghi,ghi | depart,rotary-exit-1,arrive |
|
|
||||||
| g,f | ghi,def,def | depart,bkheb-exit-2,arrive |
|
|
||||||
| g,c | ghi,abc,abc | depart,bkheb-exit-3,arrive |
|
|
||||||
| g,l | ghi,jkl,jkl | depart,bkheb-exit-4,arrive |
|
|
||||||
| j,l | jkl,jkl,jkl | depart,rotary-exit-1,arrive |
|
|
||||||
| j,i | jkl,ghi,ghi | depart,bkheb-exit-2,arrive |
|
|
||||||
| j,f | jkl,def,def | depart,bkheb-exit-3,arrive |
|
|
||||||
| j,c | jkl,abc,abc | depart,bkheb-exit-4,arrive |
|
|
||||||
@@ -24,19 +24,19 @@ Feature: Rotary
|
|||||||
| bgecb | roundabout |
|
| bgecb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,bgecb-exit-3,arrive |
|
| a,d | ab,cd,cd,cd | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| a,f | ab,ef,ef | depart,bgecb-exit-2,arrive |
|
| a,f | ab,ef,ef,ef | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| a,h | ab,gh,gh | depart,bgecb-exit-1,arrive |
|
| a,h | ab,gh,gh,gh | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
| d,f | cd,ef,ef | depart,bgecb-exit-3,arrive |
|
| d,f | cd,ef,ef,ef | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| d,h | cd,gh,gh | depart,bgecb-exit-2,arrive |
|
| d,h | cd,gh,gh,gh | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| d,a | cd,ab,ab | depart,bgecb-exit-1,arrive |
|
| d,a | cd,ab,ab,ab | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
| f,h | ef,gh,gh | depart,bgecb-exit-3,arrive |
|
| f,h | ef,gh,gh,gh | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| f,a | ef,ab,ab | depart,bgecb-exit-2,arrive |
|
| f,a | ef,ab,ab,ab | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| f,d | ef,cd,cd | depart,bgecb-exit-1,arrive |
|
| f,d | ef,cd,cd,cd | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
| h,a | gh,ab,ab | depart,bgecb-exit-3,arrive |
|
| h,a | gh,ab,ab,ab | depart,bgecb-exit-3,exit rotary right,arrive |
|
||||||
| h,d | gh,cd,cd | depart,bgecb-exit-2,arrive |
|
| h,d | gh,cd,cd,cd | depart,bgecb-exit-2,exit rotary right,arrive |
|
||||||
| h,f | gh,ef,ef | depart,bgecb-exit-1,arrive |
|
| h,f | gh,ef,ef,ef | depart,bgecb-exit-1,exit rotary right,arrive |
|
||||||
|
|
||||||
Scenario: Only Enter
|
Scenario: Only Enter
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -90,19 +90,19 @@ Feature: Rotary
|
|||||||
| bcegb | roundabout |
|
| bcegb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| b,d | bcegb,cd,cd | depart,bcegb-exit-1,arrive |
|
| b,d | bcegb,cd,cd | depart,exit rotary right,arrive |
|
||||||
| b,f | bcegb,ef,ef | depart,bcegb-exit-2,arrive |
|
| b,f | bcegb,ef,ef | depart,exit rotary right,arrive |
|
||||||
| b,h | bcegb,gh,gh | depart,bcegb-exit-3,arrive |
|
| b,h | bcegb,gh,gh | depart,exit rotary right,arrive |
|
||||||
| c,f | bcegb,ef,ef | depart,bcegb-exit-1,arrive |
|
| c,f | bcegb,ef,ef | depart,exit rotary right,arrive |
|
||||||
| c,h | bcegb,gh,gh | depart,bcegb-exit-2,arrive |
|
| c,h | bcegb,gh,gh | depart,exit rotary right,arrive |
|
||||||
| c,a | bcegb,ab,ab | depart,bcegb-exit-3,arrive |
|
| c,a | bcegb,ab,ab | depart,exit rotary right,arrive |
|
||||||
| e,h | bcegb,gh,gh | depart,bcegb-exit-1,arrive |
|
| e,h | bcegb,gh,gh | depart,exit rotary right,arrive |
|
||||||
| e,a | bcegb,ab,ab | depart,bcegb-exit-2,arrive |
|
| e,a | bcegb,ab,ab | depart,exit rotary right,arrive |
|
||||||
| e,d | bcegb,cd,cd | depart,bcegb-exit-3,arrive |
|
| e,d | bcegb,cd,cd | depart,exit rotary right,arrive |
|
||||||
| g,a | bcegb,ab,ab | depart,bcegb-exit-1,arrive |
|
| g,a | bcegb,ab,ab | depart,exit rotary right,arrive |
|
||||||
| g,d | bcegb,cd,cd | depart,bcegb-exit-2,arrive |
|
| g,d | bcegb,cd,cd | depart,exit rotary right,arrive |
|
||||||
| g,f | bcegb,ef,ef | depart,bcegb-exit-3,arrive |
|
| g,f | bcegb,ef,ef | depart,exit rotary right,arrive |
|
||||||
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
||||||
|
|
||||||
Scenario: Drive Around
|
Scenario: Drive Around
|
||||||
@@ -158,23 +158,23 @@ Feature: Rotary
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,rotary-exit-1,arrive |
|
| a,c | abc,abc,abc | depart,exit rotary right,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,bkheb-exit-2,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,bkheb-exit-2,exit rotary straight,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,bkheb-exit-3,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,bkheb-exit-3,exit rotary straight,arrive |
|
||||||
| a,f | abc,def,def | depart,bkheb-exit-4,arrive |
|
| a,f | abc,def,def,def | depart,bkheb-exit-4,exit rotary straight,arrive |
|
||||||
| d,f | def,def,def | depart,rotary-exit-1,arrive |
|
| d,f | def,def,def | depart,exit rotary right,arrive |
|
||||||
| d,c | def,abc,abc | depart,bkheb-exit-2,arrive |
|
| d,c | def,abc,abc,abc | depart,bkheb-exit-2,exit rotary straight,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,bkheb-exit-3,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,bkheb-exit-3,exit rotary straight,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,bkheb-exit-4,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,bkheb-exit-4,exit rotary straight,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,rotary-exit-1,arrive |
|
| g,i | ghi,ghi,ghi | depart,exit rotary right,arrive |
|
||||||
| g,f | ghi,def,def | depart,bkheb-exit-2,arrive |
|
| g,f | ghi,def,def,def | depart,bkheb-exit-2,exit rotary straight,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,bkheb-exit-3,arrive |
|
| g,c | ghi,abc,abc,abc | depart,bkheb-exit-3,exit rotary straight,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,bkheb-exit-4,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,bkheb-exit-4,exit rotary straight,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,rotary-exit-1,arrive |
|
| j,l | jkl,jkl,jkl | depart,exit rotary right,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,bkheb-exit-2,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,bkheb-exit-2,exit rotary straight,arrive |
|
||||||
| j,f | jkl,def,def | depart,bkheb-exit-3,arrive |
|
| j,f | jkl,def,def,def | depart,bkheb-exit-3,exit rotary straight,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,bkheb-exit-4,arrive |
|
| j,c | jkl,abc,abc,abc | depart,bkheb-exit-4,exit rotary straight,arrive |
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
Scenario: Collinear in X,Y
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -193,9 +193,9 @@ Feature: Rotary
|
|||||||
| df | |
|
| df | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
|
| a,e | ab,ce,ce,ce | depart,bcdb-exit-1,exit rotary straight,arrive |
|
||||||
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
|
| a,f | ab,df,df,df | depart,bcdb-exit-2,exit rotary straight,arrive |
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
Scenario: Collinear in X,Y
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -214,9 +214,9 @@ Feature: Rotary
|
|||||||
| cf | |
|
| cf | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,e | ad,be,be | depart,bcdb-exit-1,arrive |
|
| a,e | ad,be,be,be | depart,bcdb-exit-1,exit rotary straight,arrive |
|
||||||
| a,f | ad,cf,cf | depart,bcdb-exit-2,arrive |
|
| a,f | ad,cf,cf,cf | depart,bcdb-exit-2,exit rotary straight,arrive |
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
Scenario: Collinear in X,Y
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -235,9 +235,9 @@ Feature: Rotary
|
|||||||
| bf | |
|
| bf | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,e | ac,de,de | depart,bcdb-exit-1,arrive |
|
| a,e | ac,de,de,de | depart,bcdb-exit-1,exit rotary straight,arrive |
|
||||||
| a,f | ac,bf,bf | depart,bcdb-exit-2,arrive |
|
| a,f | ac,bf,bf,bf | depart,bcdb-exit-2,exit rotary straight,arrive |
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
Scenario: Collinear in X,Y
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -256,9 +256,9 @@ Feature: Rotary
|
|||||||
| df | |
|
| df | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
|
| a,e | ab,ce,ce,ce | depart,bcdb-exit-1,exit rotary right,arrive |
|
||||||
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
|
| a,f | ab,df,df,df | depart,bcdb-exit-2,exit rotary right,arrive |
|
||||||
|
|
||||||
Scenario: Collinear in X,Y
|
Scenario: Collinear in X,Y
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -277,6 +277,6 @@ Feature: Rotary
|
|||||||
| df | |
|
| df | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
|
| a,e | ab,ce,ce,ce | depart,bcdb-exit-1,exit rotary right,arrive |
|
||||||
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
|
| a,f | ab,df,df,df | depart,bcdb-exit-2,exit rotary right,arrive |
|
||||||
|
|||||||
@@ -5,39 +5,6 @@ Feature: Basic Roundabout
|
|||||||
Given the profile "bicycle"
|
Given the profile "bicycle"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
|
|
||||||
Scenario: Only Enter
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,c | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| a,e | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| a,g | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| d,e | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| d,g | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| d,b | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| f,g | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| f,b | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| f,c | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| h,b | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| h,c | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
| h,e | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
|
|
||||||
|
|
||||||
Scenario: Only Exit
|
Scenario: Only Exit
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@@ -57,54 +24,21 @@ Feature: Basic Roundabout
|
|||||||
| bcegb | roundabout |
|
| bcegb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| b,d | bcegb,cd,cd | depart,roundabout-exit-1,arrive |
|
| b,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive |
|
| b,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
| b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive |
|
| b,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive |
|
| c,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
| c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive |
|
| c,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive |
|
| c,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive |
|
| e,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive |
|
| e,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive |
|
| e,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive |
|
| g,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive |
|
| g,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| g,f | bcegb,ef,ef | depart,roundabout-exit-3,arrive |
|
| g,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
||||||
|
|
||||||
Scenario: Drive Around
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
d c g h
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bcegb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| b,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| b,e | bcegb,bcegb | depart,arrive |
|
|
||||||
| b,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,e | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| c,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,g | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| e,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,b | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,c | bcegb,bcegb | depart,arrive |
|
|
||||||
| g,e | bcegb,bcegb | depart,arrive |
|
|
||||||
|
|
||||||
Scenario: Mixed Entry and Exit
|
Scenario: Mixed Entry and Exit
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@@ -124,20 +58,20 @@ Feature: Basic Roundabout
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,roundabout-exit-1,arrive |
|
| a,c | abc,abc,abc | depart,exit roundabout right,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| a,f | abc,def,def | depart,roundabout-exit-4,arrive |
|
| a,f | abc,def,def,def | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| d,f | def,def,def | depart,roundabout-exit-1,arrive |
|
| d,f | def,def,def | depart,exit roundabout right,arrive |
|
||||||
| d,c | def,abc,abc | depart,roundabout-exit-2,arrive |
|
| d,c | def,abc,abc,abc | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive |
|
| g,i | ghi,ghi,ghi | depart,exit roundabout right,arrive |
|
||||||
| g,f | ghi,def,def | depart,roundabout-exit-2,arrive |
|
| g,f | ghi,def,def,def | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive |
|
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive |
|
| j,l | jkl,jkl,jkl | depart,exit roundabout right,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
|
| j,f | jkl,def,def,def | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
|
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ Feature: Basic Roundabout
|
|||||||
| behkb | roundabout | yes |
|
| behkb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| c,a | cba,cba,cba | depart,roundabout-exit-1,arrive |
|
| c,a | cba,cba,cba | depart,exit roundabout left,arrive |
|
||||||
| l,a | lkj,cba,cba | depart,roundabout-exit-2,arrive |
|
| l,a | lkj,cba,cba,cba | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| i,a | ihg,cba,cba | depart,roundabout-exit-3,arrive |
|
| i,a | ihg,cba,cba,cba | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
|
|||||||
@@ -5,39 +5,6 @@ Feature: Basic Roundabout
|
|||||||
Given the profile "bicycle"
|
Given the profile "bicycle"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
|
|
||||||
Scenario: Enter and Exit
|
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a
|
|
||||||
b
|
|
||||||
h g c d
|
|
||||||
e
|
|
||||||
f
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes | junction |
|
|
||||||
| ab | |
|
|
||||||
| cd | |
|
|
||||||
| ef | |
|
|
||||||
| gh | |
|
|
||||||
| bgecb | roundabout |
|
|
||||||
|
|
||||||
When I route I should get
|
|
||||||
| waypoints | route | turns |
|
|
||||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
|
|
||||||
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
|
|
||||||
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
|
|
||||||
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
|
|
||||||
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
|
|
||||||
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
|
|
||||||
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
|
|
||||||
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
|
|
||||||
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
|
|
||||||
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
|
|
||||||
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
|
|
||||||
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
|
|
||||||
|
|
||||||
# https://www.openstreetmap.org/way/223225602
|
# https://www.openstreetmap.org/way/223225602
|
||||||
Scenario: Enter and Exit with changing mode
|
Scenario: Enter and Exit with changing mode
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -58,16 +25,16 @@ Feature: Basic Roundabout
|
|||||||
| bgecb | roundabout | residential |
|
| bgecb | roundabout | residential |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
|
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
|
||||||
| a,f | ab,ef,ef,ef | depart,roundabout turn left exit-1,notification right,arrive |
|
| a,f | ab,ef,ef,ef | depart,roundabout turn straight exit-1,exit roundabout right,arrive |
|
||||||
| a,h | ab,bgecb,gh,gh | depart,roundabout turn right exit-1,notification right,arrive |
|
| a,h | ab,gh,gh,gh | depart,roundabout turn right exit-1,exit roundabout right,arrive |
|
||||||
| d,f | cd,ef,ef,ef | depart,roundabout turn sharp left exit-2,notification right,arrive |
|
| d,f | cd,ef,ef,ef | depart,roundabout turn left exit-2,exit roundabout right,arrive |
|
||||||
| d,h | cd,gh,gh,gh | depart,roundabout turn left exit-2,notification right,arrive |
|
| d,h | cd,gh,gh,gh | depart,roundabout turn straight exit-2,exit roundabout right,arrive |
|
||||||
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
|
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
|
||||||
| f,h | ef,gh,gh,gh | depart,roundabout turn sharp left exit-3,notification right,arrive |
|
| f,h | ef,gh,gh,gh | depart,roundabout turn left exit-3,exit roundabout right,arrive |
|
||||||
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
|
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
|
||||||
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
|
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
|
||||||
| h,a | gh,ab,ab | depart,roundabout turn left exit-2,arrive |
|
| h,a | gh,ab,ab | depart,roundabout turn left exit-2,arrive |
|
||||||
| h,d | gh,cd,cd | depart,roundabout turn straight exit-1,arrive |
|
| h,d | gh,cd,cd | depart,roundabout turn straight exit-1,arrive |
|
||||||
| h,f | gh,bgecb,ef,ef | depart,roundabout turn right exit-1,notification right,arrive |
|
| h,f | gh,ef,ef,ef | depart,roundabout turn right exit-1,exit roundabout right,arrive |
|
||||||
|
|||||||
@@ -56,19 +56,19 @@ Feature: Basic Roundabout
|
|||||||
| bgecb | roundabout |
|
| bgecb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
|
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
|
||||||
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
|
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
|
||||||
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
|
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
|
||||||
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
|
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
|
||||||
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
|
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
|
||||||
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
|
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
|
||||||
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
|
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
|
||||||
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
|
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
|
||||||
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
|
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
|
||||||
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
|
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
|
||||||
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
|
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
|
||||||
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
|
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
|
||||||
|
|
||||||
Scenario: Only Enter
|
Scenario: Only Enter
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -122,19 +122,19 @@ Feature: Basic Roundabout
|
|||||||
| bcegb | roundabout |
|
| bcegb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| b,d | bcegb,cd,cd | depart,roundabout-exit-1,arrive |
|
| b,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive |
|
| b,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
| b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive |
|
| b,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive |
|
| c,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
| c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive |
|
| c,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive |
|
| c,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive |
|
| e,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive |
|
| e,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive |
|
| e,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive |
|
| g,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive |
|
| g,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| g,f | bcegb,ef,ef | depart,roundabout-exit-3,arrive |
|
| g,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
||||||
|
|
||||||
Scenario: Drive Around
|
Scenario: Drive Around
|
||||||
@@ -189,23 +189,23 @@ Feature: Basic Roundabout
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,roundabout-exit-1,arrive |
|
| a,c | abc,abc,abc | depart,exit roundabout right,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| a,f | abc,def,def | depart,roundabout-exit-4,arrive |
|
| a,f | abc,def,def,def | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| d,f | def,def,def | depart,roundabout-exit-1,arrive |
|
| d,f | def,def,def | depart,exit roundabout right,arrive |
|
||||||
| d,c | def,abc,abc | depart,roundabout-exit-2,arrive |
|
| d,c | def,abc,abc,abc | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive |
|
| g,i | ghi,ghi,ghi | depart,exit roundabout right,arrive |
|
||||||
| g,f | ghi,def,def | depart,roundabout-exit-2,arrive |
|
| g,f | ghi,def,def,def | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive |
|
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive |
|
| j,l | jkl,jkl,jkl | depart,exit roundabout right,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
|
| j,f | jkl,def,def,def | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
|
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
|
|
||||||
Scenario: Segregated roads - Not an intersection
|
Scenario: Segregated roads - Not an intersection
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -226,23 +226,23 @@ Feature: Basic Roundabout
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
|
| a,c | abc,abc,abc,abc | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
|
| a,f | abc,def,def,def | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
| d,f | def,def,def,def | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
|
| d,c | def,abc,abc,abc | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
| g,i | ghi,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
|
| g,f | ghi,def,def,def | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
| j,l | jkl,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
| j,f | jkl,def,def,def | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
|
|
||||||
Scenario: Collinear in X
|
Scenario: Collinear in X
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -368,19 +368,19 @@ Feature: Basic Roundabout
|
|||||||
| bigecb | roundabout |
|
| bigecb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,roundabout-exit-4,arrive |
|
| a,d | ab,cd,cd,cd | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
|
| a,f | ab,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| a,h | ab,gh,gh | depart,roundabout-exit-2,arrive |
|
| a,h | ab,gh,gh,gh | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| d,f | cd,ef,ef | depart,roundabout-exit-4,arrive |
|
| d,f | cd,ef,ef,ef | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| d,h | cd,gh,gh | depart,roundabout-exit-3,arrive |
|
| d,h | cd,gh,gh,gh | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
|
| d,a | cd,ab,ab,ab | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| f,h | ef,gh,gh | depart,roundabout-exit-4,arrive |
|
| f,h | ef,gh,gh,gh | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
|
| f,a | ef,ab,ab,ab | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
|
| f,d | ef,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
|
| h,a | gh,ab,ab,ab | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
|
| h,d | gh,cd,cd,cd | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
| h,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
|
|
||||||
Scenario: Enter and Exit -- Non-Distinct
|
Scenario: Enter and Exit -- Non-Distinct
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -401,19 +401,19 @@ Feature: Basic Roundabout
|
|||||||
| bgecb | roundabout |
|
| bgecb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,roundabout-exit-3,arrive |
|
| a,d | ab,cd,cd,cd | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive |
|
| a,f | ab,ef,ef,ef | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| a,h | ab,gh,gh | depart,roundabout-exit-1,arrive |
|
| a,h | ab,gh,gh,gh | depart,roundabout-exit-1,exit roundabout straight,arrive |
|
||||||
| d,f | cd,ef,ef | depart,roundabout-exit-3,arrive |
|
| d,f | cd,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| d,h | cd,gh,gh | depart,roundabout-exit-2,arrive |
|
| d,h | cd,gh,gh,gh | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
|
| d,a | cd,ab,ab,ab | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| f,h | ef,gh,gh | depart,roundabout-exit-3,arrive |
|
| f,h | ef,gh,gh,gh | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
|
| f,a | ef,ab,ab,ab | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
|
| f,d | ef,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
|
| h,a | gh,ab,ab,ab | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
|
| h,d | gh,cd,cd,cd | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
| h,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
|
|
||||||
Scenario: Enter and Exit -- Bearing
|
Scenario: Enter and Exit -- Bearing
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@@ -57,10 +57,10 @@ Feature: Basic Roundabout
|
|||||||
| bcegb | roundabout | primary |
|
| bcegb | roundabout | primary |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,roundabout-exit-1,arrive |
|
| a,d | ab,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| a,h | ab,gh,gh | depart,roundabout-exit-2,arrive |
|
| a,h | ab,gh,gh,gh | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive |
|
| a,f | ab,ef,ef,ef | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
|
|
||||||
#2927
|
#2927
|
||||||
Scenario: Only Roundabout
|
Scenario: Only Roundabout
|
||||||
@@ -98,19 +98,19 @@ Feature: Basic Roundabout
|
|||||||
| bcegb | roundabout |
|
| bcegb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| b,d | bcegb,cd,cd | depart,roundabout-exit-1,arrive |
|
| b,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive |
|
| b,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
| b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive |
|
| b,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive |
|
| c,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
| c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive |
|
| c,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive |
|
| c,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive |
|
| e,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
|
||||||
| e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive |
|
| e,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive |
|
| e,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive |
|
| g,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
|
||||||
| g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive |
|
| g,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
|
||||||
| g,f | bcegb,ef,ef | depart,roundabout-exit-3,arrive |
|
| g,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
|
||||||
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
|
||||||
|
|
||||||
Scenario: Drive Around
|
Scenario: Drive Around
|
||||||
@@ -165,23 +165,23 @@ Feature: Basic Roundabout
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,roundabout-exit-1,arrive |
|
| a,c | abc,abc,abc | depart,exit roundabout right,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| a,f | abc,def,def | depart,roundabout-exit-4,arrive |
|
| a,f | abc,def,def,def | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| d,f | def,def,def | depart,roundabout-exit-1,arrive |
|
| d,f | def,def,def | depart,exit roundabout right,arrive |
|
||||||
| d,c | def,abc,abc | depart,roundabout-exit-2,arrive |
|
| d,c | def,abc,abc,abc | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive |
|
| g,i | ghi,ghi,ghi | depart,exit roundabout right,arrive |
|
||||||
| g,f | ghi,def,def | depart,roundabout-exit-2,arrive |
|
| g,f | ghi,def,def,def | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive |
|
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive |
|
| j,l | jkl,jkl,jkl | depart,exit roundabout right,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
|
| j,f | jkl,def,def,def | depart,roundabout-exit-3,exit roundabout straight,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
|
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
|
|
||||||
Scenario: Mixed Entry and Exit - segregated roads
|
Scenario: Mixed Entry and Exit - segregated roads
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -204,23 +204,23 @@ Feature: Basic Roundabout
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
|
| a,c | abc,abc,abc,abc | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
|
| a,f | abc,def,def,def | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
| d,f | def,def,def,def | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
|
| d,c | def,abc,abc,abc | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
| g,i | ghi,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
|
| g,f | ghi,def,def,def | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
| j,l | jkl,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
| j,f | jkl,def,def,def | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
|
|
||||||
Scenario: Mixed Entry and Exit - clockwise order
|
Scenario: Mixed Entry and Exit - clockwise order
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -241,23 +241,23 @@ Feature: Basic Roundabout
|
|||||||
| behkb | roundabout | yes |
|
| behkb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
|
| a,c | abc,abc,abc,abc | depart,roundabout-exit-4,exit roundabout left,arrive |
|
||||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-3,arrive |
|
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout left,arrive |
|
||||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout left,arrive |
|
||||||
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
|
| a,f | abc,def,def,def | depart,roundabout-exit-1,exit roundabout left,arrive |
|
||||||
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
| d,f | def,def,def,def | depart,roundabout-exit-4,exit roundabout left,arrive |
|
||||||
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
|
| d,c | def,abc,abc,abc | depart,roundabout-exit-3,exit roundabout left,arrive |
|
||||||
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout left,arrive |
|
||||||
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
|
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-1,exit roundabout left,arrive |
|
||||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
| g,i | ghi,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout left,arrive |
|
||||||
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
|
| g,f | ghi,def,def,def | depart,roundabout-exit-3,exit roundabout left,arrive |
|
||||||
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-2,exit roundabout left,arrive |
|
||||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
|
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-1,exit roundabout left,arrive |
|
||||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
| j,l | jkl,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout left,arrive |
|
||||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
|
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout left,arrive |
|
||||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
| j,f | jkl,def,def,def | depart,roundabout-exit-2,exit roundabout left,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
|
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-1,exit roundabout left,arrive |
|
||||||
|
|
||||||
Scenario: Mixed Entry and Exit - segregated roads, different names
|
Scenario: Mixed Entry and Exit - segregated roads, different names
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -284,23 +284,23 @@ Feature: Basic Roundabout
|
|||||||
| bkheb | roundabout | yes |
|
| bkheb | roundabout | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,c | ab,bc,bc | depart,roundabout-exit-4,arrive |
|
| a,c | ab,bc,bc,bc | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| a,l | ab,kl,kl | depart,roundabout-exit-1,arrive |
|
| a,l | ab,kl,kl,kl | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| a,i | ab,hi,hi | depart,roundabout-exit-2,arrive |
|
| a,i | ab,hi,hi,hi | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
|
| a,f | ab,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| d,f | de,ef,ef | depart,roundabout-exit-4,arrive |
|
| d,f | de,ef,ef,ef | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| d,c | de,bc,bc | depart,roundabout-exit-1,arrive |
|
| d,c | de,bc,bc,bc | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| d,l | de,kl,kl | depart,roundabout-exit-2,arrive |
|
| d,l | de,kl,kl,kl | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| d,i | de,hi,hi | depart,roundabout-exit-3,arrive |
|
| d,i | de,hi,hi,hi | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| g,i | gh,hi,hi | depart,roundabout-exit-4,arrive |
|
| g,i | gh,hi,hi,hi | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| g,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
| g,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| g,c | gh,bc,bc | depart,roundabout-exit-2,arrive |
|
| g,c | gh,bc,bc,bc | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| g,l | gh,kl,kl | depart,roundabout-exit-3,arrive |
|
| g,l | gh,kl,kl,kl | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| j,l | jk,kl,kl | depart,roundabout-exit-4,arrive |
|
| j,l | jk,kl,kl,kl | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| j,i | jk,hi,hi | depart,roundabout-exit-1,arrive |
|
| j,i | jk,hi,hi,hi | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| j,f | jk,ef,ef | depart,roundabout-exit-2,arrive |
|
| j,f | jk,ef,ef,ef | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| j,c | jk,bc,bc | depart,roundabout-exit-3,arrive |
|
| j,c | jk,bc,bc,bc | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
|
|
||||||
Scenario: Motorway Roundabout
|
Scenario: Motorway Roundabout
|
||||||
#See 39.933742 -75.082345
|
#See 39.933742 -75.082345
|
||||||
@@ -338,11 +338,10 @@ Feature: Basic Roundabout
|
|||||||
| dmg | roundabout | | trunk_link | yes | |
|
| dmg | roundabout | | trunk_link | yes | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | ref |
|
| waypoints | route | turns | ref |
|
||||||
| a,e | crescent,crescent,crescent | depart,roundabout-exit-3,arrive | US 130,US 130,US 130 |
|
| a,e | crescent,crescent,crescent,crescent | depart,roundabout-exit-3,exit roundabout straight,arrive | US 130,US 130,US 130,US 130 |
|
||||||
| j,l | ,, | depart,roundabout-exit-2,arrive | NJ 38,NJ 38,NJ 38 |
|
| j,l | ,,, | depart,roundabout-exit-2,exit roundabout straight,arrive | NJ 38,NJ 38,NJ 38,NJ 38 |
|
||||||
|
|
||||||
@todo
|
|
||||||
# this test previously only passed by accident. We need to handle throughabouts correctly, since staying on massachusetts is actually
|
# this test previously only passed by accident. We need to handle throughabouts correctly, since staying on massachusetts is actually
|
||||||
# the desired setting. Rotary instructions here are not wanted but rather no instruction at all to go through the roundabout (or add
|
# the desired setting. Rotary instructions here are not wanted but rather no instruction at all to go through the roundabout (or add
|
||||||
# a throughabout instruction)
|
# a throughabout instruction)
|
||||||
@@ -389,8 +388,8 @@ Feature: Basic Roundabout
|
|||||||
| restriction | pi | ij | i | no_left_turn |
|
| restriction | pi | ij | i | no_left_turn |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,k | massachusetts,massachusetts,massachusetts,massachusetts | depart,sheridan circle-exit-2,rotary-exit-1,arrive |
|
| a,k | massachusetts,massachusetts,massachusetts,massachusetts | depart,sheridan circle-exit-2,exit rotary right,arrive |
|
||||||
|
|
||||||
#2856 - http://www.openstreetmap.org/#map=19/47.23318/-1.56563
|
#2856 - http://www.openstreetmap.org/#map=19/47.23318/-1.56563
|
||||||
Scenario: Linked Roundabouts
|
Scenario: Linked Roundabouts
|
||||||
@@ -477,8 +476,8 @@ Feature: Basic Roundabout
|
|||||||
| cdefib | roundabout | roundabout | yes | |
|
| cdefib | roundabout | roundabout | yes | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| 1,h | roundabout,right-bot-out,right-bot-out | depart,roundabout-exit-1,arrive |
|
| 1,h | roundabout,right-bot-out,right-bot-out | depart,exit rotary straight,arrive |
|
||||||
|
|
||||||
@3254
|
@3254
|
||||||
Scenario: Driving up to and through a roundabout
|
Scenario: Driving up to and through a roundabout
|
||||||
@@ -495,15 +494,15 @@ Feature: Basic Roundabout
|
|||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | junction | name | highway |
|
| nodes | junction | name | highway |
|
||||||
| abcda | roundabout | roundabout | residential |
|
| abcda | roundabout | rotary | residential |
|
||||||
| gfi | | side | residential |
|
| gfi | | side | residential |
|
||||||
| efb | | left | residential |
|
| efb | | left | residential |
|
||||||
| dh | | right | residential |
|
| dh | | right | residential |
|
||||||
| ck | | bottom | residential |
|
| ck | | bottom | residential |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| e,h | left,right,right | depart,roundabout-exit-2,arrive |
|
| e,h | left,right,right,right | depart,rotary-exit-2,exit rotary right,arrive |
|
||||||
|
|
||||||
@3254
|
@3254
|
||||||
Scenario: Driving up to and through a roundabout
|
Scenario: Driving up to and through a roundabout
|
||||||
@@ -520,15 +519,15 @@ Feature: Basic Roundabout
|
|||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | junction | name | highway |
|
| nodes | junction | name | highway |
|
||||||
| abcda | roundabout | roundabout | residential |
|
| abcda | roundabout | rotary | residential |
|
||||||
| gfi | | side | residential |
|
| gfi | | side | residential |
|
||||||
| efb | | left | residential |
|
| efb | | left | residential |
|
||||||
| dh | | right | residential |
|
| dh | | right | residential |
|
||||||
| ck | | bottom | residential |
|
| ck | | bottom | residential |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| e,h | left,right,right | depart,roundabout-exit-2,arrive |
|
| e,h | left,right,right,right | depart,rotary-exit-2,exit rotary right,arrive |
|
||||||
|
|
||||||
@3361
|
@3361
|
||||||
Scenario: Bersarinplatz (Not a Roundabout)
|
Scenario: Bersarinplatz (Not a Roundabout)
|
||||||
@@ -565,13 +564,13 @@ Feature: Basic Roundabout
|
|||||||
| mn | | Petersburger Strasse | B 96a | primary | yes |
|
| mn | | Petersburger Strasse | B 96a | primary | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,g | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-2,arrive |
|
| a,g | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-2,exit rotary straight,arrive |
|
||||||
| d,g | Weidenweg,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-1,arrive |
|
| d,g | Weidenweg,Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-1,exit rotary straight,arrive |
|
||||||
| i,k | Petersburger Strasse,Rigaer Strasse,Rigaer Strasse | depart,Bersarinplatz-exit-1,arrive |
|
| i,k | Petersburger Strasse,Rigaer Strasse,Rigaer Strasse,Rigaer Strasse | depart,Bersarinplatz-exit-1,exit rotary right,arrive |
|
||||||
| i,n | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-2,arrive |
|
| i,n | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-2,exit rotary straight,arrive |
|
||||||
| i,d | Petersburger Strasse,Weidenweg,Weidenweg | depart,Bersarinplatz-exit-3,arrive |
|
| i,d | Petersburger Strasse,Weidenweg,Weidenweg,Weidenweg | depart,Bersarinplatz-exit-3,exit rotary right,arrive |
|
||||||
| i,g | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-4,arrive |
|
| i,g | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-4,exit rotary straight,arrive |
|
||||||
|
|
||||||
@turboroundabout
|
@turboroundabout
|
||||||
# http://www.openstreetmap.org/?mlat=48.782118&mlon=8.194456&zoom=16#map=19/48.78216/8.19457
|
# http://www.openstreetmap.org/?mlat=48.782118&mlon=8.194456&zoom=16#map=19/48.78216/8.19457
|
||||||
@@ -606,11 +605,11 @@ Feature: Basic Roundabout
|
|||||||
| ob | trunk | yes | roundabout | Europaplatz | |
|
| ob | trunk | yes | roundabout | Europaplatz | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ,Europastrasse,Europastrasse | depart,Europaplatz-exit-1,arrive |
|
| a,d | ,Europastrasse,Europastrasse,Europastrasse | depart,Europaplatz-exit-1,exit rotary right,arrive |
|
||||||
| a,h | ,Allee Cite,Allee Cite | depart,Europaplatz-exit-2,arrive |
|
| a,h | ,Allee Cite,Allee Cite,Allee Cite | depart,Europaplatz-exit-2,exit rotary right,arrive |
|
||||||
| a,l | ,Europastrasse,Europastrasse | depart,Europaplatz-exit-3,arrive |
|
| a,l | ,Europastrasse,Europastrasse,Europastrasse | depart,Europaplatz-exit-3,exit rotary right,arrive |
|
||||||
| a,p | ,, | depart,Europaplatz-exit-4,arrive |
|
| a,p | ,,, | depart,Europaplatz-exit-4,exit rotary right,arrive |
|
||||||
|
|
||||||
@turboroundabout
|
@turboroundabout
|
||||||
# http://www.openstreetmap.org/?mlat=50.180039&mlon=8.474939&zoom=16#map=19/50.17999/8.47506
|
# http://www.openstreetmap.org/?mlat=50.180039&mlon=8.474939&zoom=16#map=19/50.17999/8.47506
|
||||||
@@ -658,14 +657,14 @@ Feature: Basic Roundabout
|
|||||||
| wb | primary | yes | roundabout | | through\|through;right |
|
| wb | primary | yes | roundabout | | through\|through;right |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,w | Le-Cannet-Rocheville-Strasse,, | depart,roundabout-exit-undefined,arrive |
|
| a,w | Le-Cannet-Rocheville-Strasse,, | depart,roundabout-exit-undefined,arrive |
|
||||||
| a,r | Le-Cannet-Rocheville-Strasse,, | depart,roundabout-exit-4,arrive |
|
| a,r | Le-Cannet-Rocheville-Strasse,,, | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| a,f | Le-Cannet-Rocheville-Strasse,Frankfurter Strasse,Frankfurter Strasse | depart,roundabout-exit-1,arrive |
|
| a,f | Le-Cannet-Rocheville-Strasse,Frankfurter Strasse,Frankfurter Strasse,Frankfurter Strasse | depart,roundabout-exit-1,exit roundabout right,arrive |
|
||||||
| a,h | Le-Cannet-Rocheville-Strasse,Bischof-Kaller-Strasse,Bischof-Kaller-Strasse | depart,roundabout-exit-2,arrive |
|
| a,h | Le-Cannet-Rocheville-Strasse,Bischof-Kaller-Strasse,Bischof-Kaller-Strasse,Bischof-Kaller-Strasse | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| u,r | ,, | depart,roundabout-exit-5,arrive |
|
| u,r | ,,, | depart,roundabout-exit-5,exit roundabout right,arrive |
|
||||||
| j,h | Bischof-Kaller-Strasse,Bischof-Kaller-Strasse,Bischof-Kaller-Strasse | depart,roundabout-exit-5,arrive |
|
| j,h | Bischof-Kaller-Strasse,Bischof-Kaller-Strasse,Bischof-Kaller-Strasse,Bischof-Kaller-Strasse | depart,roundabout-exit-5,exit roundabout right,arrive |
|
||||||
| n,m | , | depart,arrive |
|
| n,m | , | depart,arrive |
|
||||||
|
|
||||||
@turboroundabout
|
@turboroundabout
|
||||||
# http://www.openstreetmap.org/?mlat=47.57723&mlon=7.796765&zoom=16#map=19/47.57720/7.79711
|
# http://www.openstreetmap.org/?mlat=47.57723&mlon=7.796765&zoom=16#map=19/47.57720/7.79711
|
||||||
@@ -708,17 +707,16 @@ Feature: Basic Roundabout
|
|||||||
| la | primary | yes | roundabout |
|
| la | primary | yes | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| w,r | wk,ar,ar | depart,roundabout-exit-1,arrive |
|
| w,r | wk,ar,ar,ar | depart,roundabout-exit-1,exit roundabout slight right,arrive |
|
||||||
| w,s | wk,ds,ds | depart,roundabout-exit-2,arrive |
|
| w,s | wk,ds,ds,ds | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| w,t | wk,ft,ft | depart,roundabout-exit-3,arrive |
|
| w,t | wk,ft,ft,ft | depart,roundabout-exit-3,exit roundabout right,arrive |
|
||||||
| w,v | wk,hv,hv | depart,roundabout-exit-4,arrive |
|
| w,v | wk,hv,hv,hv | depart,roundabout-exit-4,exit roundabout straight,arrive |
|
||||||
| u,v | ug,hv,hv | depart,roundabout-exit-1,arrive |
|
| u,v | ug,hv,hv,hv | depart,roundabout-exit-1,exit roundabout straight,arrive |
|
||||||
| u,w | ug,jw,jw | depart,roundabout-exit-2,arrive |
|
| u,w | ug,jw,jw,jw | depart,roundabout-exit-2,exit roundabout slight right,arrive |
|
||||||
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
|
| u,r | ug,ar,ar,ar | depart,roundabout-exit-3,exit roundabout slight right,arrive |
|
||||||
| u,s | ug,ds,ds | depart,roundabout-exit-4,arrive |
|
| u,s | ug,ds,ds,ds | depart,roundabout-exit-4,exit roundabout right,arrive |
|
||||||
| u,t | ug,ft,ft | depart,roundabout-exit-5,arrive |
|
| u,t | ug,ft,ft,ft | depart,roundabout-exit-5,exit roundabout right,arrive |
|
||||||
|
|
||||||
|
|
||||||
@3762
|
@3762
|
||||||
Scenario: Only Enter
|
Scenario: Only Enter
|
||||||
@@ -742,8 +740,8 @@ Feature: Basic Roundabout
|
|||||||
| bcjdeb | roundabout | |
|
| bcjdeb | roundabout | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
|
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,exit roundabout slight right,notification straight,arrive |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Drive through roundabout
|
Scenario: Drive through roundabout
|
||||||
@@ -762,12 +760,12 @@ Feature: Basic Roundabout
|
|||||||
| gch | | yes |
|
| gch | | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | bearings | route | turns |
|
| waypoints | bearings | route | turns |
|
||||||
| e,f | 90 90 | edf,edf | depart,arrive |
|
| e,f | 90 90 | edf,edf | depart,arrive |
|
||||||
| e,h | 90 135 | edf,gch,gch | depart,roundabout-exit-2,arrive |
|
| e,h | 90 135 | edf,gch,gch,gch | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||||
| g,f | 45 90 | gch,edf,edf | depart,roundabout-exit-2,arrive |
|
| g,f | 45 90 | gch,edf,edf,edf | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||||
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
|
| g,h | 45 135 | gch,gch,gch | depart,exit roundabout right,arrive |
|
||||||
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |
|
| e,e | 90 270 | edf,edf,edf,edf | depart,roundabout-exit-3,exit roundabout sharp left,arrive |
|
||||||
|
|
||||||
Scenario: CCW and CW roundabouts with overlaps
|
Scenario: CCW and CW roundabouts with overlaps
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -787,12 +785,13 @@ Feature: Basic Roundabout
|
|||||||
| kg | tertiary | |
|
| kg | tertiary | |
|
||||||
| hl | tertiary | |
|
| hl | tertiary | |
|
||||||
|
|
||||||
|
# the turn angles here are quite strange, so we do get uturns for exiting
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | turns | distance |
|
| from | to | route | turns | distance |
|
||||||
| e | f | ed,af,af | depart,roundabout-exit-1,arrive | 80.1m |
|
| e | f | ed,af,af,af | depart,roundabout-exit-1,exit roundabout left,arrive | 80.1m |
|
||||||
| f | e | af,ed,ed | depart,roundabout-exit-1,arrive | 120.1m |
|
| f | e | af,ed,ed,ed | depart,roundabout-exit-1,exit roundabout uturn,arrive | 120.1m |
|
||||||
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
|
| k | l | kg,hl,hl,hl | depart,roundabout-exit-1,exit roundabout right,arrive | 80.1m |
|
||||||
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |
|
| l | k | hl,kg,kg,kg | depart,roundabout-exit-1,exit roundabout uturn,arrive | 120.1m |
|
||||||
|
|
||||||
@4030 @4075
|
@4030 @4075
|
||||||
Scenario: Service roundabout with service exits
|
Scenario: Service roundabout with service exits
|
||||||
@@ -811,11 +810,11 @@ Feature: Basic Roundabout
|
|||||||
| bh | service | |
|
| bh | service | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | turns |
|
| from | to | route | turns |
|
||||||
| 1 | e | abcda,ce,ce | depart,roundabout-exit-1,arrive |
|
| 1 | e | abcda,ce,ce | depart,exit roundabout straight,arrive |
|
||||||
| 1 | f | abcda,df,df | depart,roundabout-exit-2,arrive |
|
| 1 | f | abcda,df,df | depart,exit roundabout right,arrive |
|
||||||
| 1 | g | abcda,ag,ag | depart,roundabout-exit-3,arrive |
|
| 1 | g | abcda,ag,ag | depart,exit roundabout straight,arrive |
|
||||||
| 1 | h | abcda,bh,bh | depart,roundabout-exit-4,arrive |
|
| 1 | h | abcda,bh,bh | depart,exit roundabout right,arrive |
|
||||||
|
|
||||||
Scenario: Collapsing a sliproad step after roundabouts
|
Scenario: Collapsing a sliproad step after roundabouts
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -843,6 +842,6 @@ Feature: Basic Roundabout
|
|||||||
|
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | turns | distance |
|
| from | to | route | turns | distance |
|
||||||
| e | k | ebds,ufghl,jhik,jhik | depart,rstur-exit-2,turn right,arrive | 189.1m |
|
| e | k | ebds,ufghl,ufghl,jhik,jhik | depart,rstur-exit-2,exit rotary right,turn right,arrive | 189.1m |
|
||||||
| 1 | k | ebds,ufghl,jhik,jhik | depart,rstur-exit-2,turn right,arrive | 159.1m |
|
| 1 | k | ebds,ufghl,ufghl,jhik,jhik | depart,rstur-exit-2,exit rotary right,turn right,arrive | 159.1m |
|
||||||
|
|||||||
@@ -248,8 +248,8 @@ Feature: Simple Turns
|
|||||||
| bcdefghijklmnob | residential | road | 1 | yes | roundabout |
|
| bcdefghijklmnob | residential | road | 1 | yes | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | intersections |
|
| waypoints | route | turns | intersections |
|
||||||
| a,p | road,road,road | depart,roundabout turn straight exit-1,arrive | true:90;true:165 false:270 false:345,true:90 false:180 true:345;true:270 |
|
| a,p | road,road,road | depart,roundabout turn straight exit-1,arrive | true:90;true:165 false:270 false:345,true:90 false:180 true:345;true:270 |
|
||||||
|
|
||||||
Scenario: Splitting Road with many lanes
|
Scenario: Splitting Road with many lanes
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -280,6 +280,35 @@ Feature: Simple Turns
|
|||||||
| a,d | road,road | depart,arrive |
|
| a,d | road,road | depart,arrive |
|
||||||
| e,a | road,road | depart,arrive |
|
| e,a | road,road | depart,arrive |
|
||||||
|
|
||||||
|
Scenario: Splitting Road with many lanes; same as above makes sure len(turn:lanes) work as expected
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
f - - - - - - - - - - - - - - - - - - - - e
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'
|
||||||
|
a - - - - - b
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'
|
||||||
|
c - - - - - - - - - - - - - - - - - - - - d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | turn:lanes | oneway |
|
||||||
|
| ab | primary | road | left\|left\|right\|right | no |
|
||||||
|
| bcd | primary | road | through\|through | yes |
|
||||||
|
| efb | primary | road | through\|through | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | road,road | depart,arrive |
|
||||||
|
| e,a | road,road | depart,arrive |
|
||||||
|
|
||||||
@todo
|
@todo
|
||||||
# currently the intersections don't match up do to the `merging` process.
|
# currently the intersections don't match up do to the `merging` process.
|
||||||
# The intermediate intersection is technically no-turn at all, since the road continues.
|
# The intermediate intersection is technically no-turn at all, since the road continues.
|
||||||
@@ -1317,11 +1346,11 @@ Feature: Simple Turns
|
|||||||
|
|
||||||
#https://github.com/Project-OSRM/osrm-backend/pull/3469#issuecomment-270806580
|
#https://github.com/Project-OSRM/osrm-backend/pull/3469#issuecomment-270806580
|
||||||
Scenario: Oszillating Lower Priority Road
|
Scenario: Oszillating Lower Priority Road
|
||||||
#Given the node map
|
#Given the node map
|
||||||
# """
|
# """
|
||||||
# a -db c
|
# a -db c
|
||||||
# f
|
# f
|
||||||
# """
|
# """
|
||||||
Given the node locations
|
Given the node locations
|
||||||
| node | lat | lon | # |
|
| node | lat | lon | # |
|
||||||
| a | 1.0 | 1.0 | |
|
| a | 1.0 | 1.0 | |
|
||||||
|
|||||||
@@ -1349,3 +1349,24 @@ Feature: Simple Turns
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,dc,dc | depart,turn left,arrive |
|
| a,d | ab,dc,dc | depart,turn left,arrive |
|
||||||
|
|
||||||
|
|
||||||
|
# https://www.openstreetmap.org/node/1332083066
|
||||||
|
Scenario: Turns ordering must respect initial bearings
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a . be .
|
||||||
|
\ c.
|
||||||
|
d/ .f . g
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | oneway |
|
||||||
|
| ab | primary | yes |
|
||||||
|
| bcd | primary | yes |
|
||||||
|
| befg | primary | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
|
||||||
|
| a,g | ab,befg,befg | depart,fork slight left,arrive |
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ Feature: osrm-contract command line options: files
|
|||||||
Scenario: osrm-contract - Missing input file
|
Scenario: osrm-contract - Missing input file
|
||||||
When I try to run "osrm-contract over-the-rainbow.osrm"
|
When I try to run "osrm-contract over-the-rainbow.osrm"
|
||||||
And stderr should contain "over-the-rainbow.osrm"
|
And stderr should contain "over-the-rainbow.osrm"
|
||||||
And stderr should contain "not found"
|
And stderr should contain "Missing/Broken"
|
||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Feature: osrm-contract command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--core"
|
And stdout should contain "--core"
|
||||||
@@ -22,6 +23,7 @@ Feature: osrm-contract command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--core"
|
And stdout should contain "--core"
|
||||||
@@ -36,6 +38,7 @@ Feature: osrm-contract command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--core"
|
And stdout should contain "--core"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Feature: osrm-contract command line options: version
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-contract - Version, short
|
Scenario: osrm-contract - Version, short
|
||||||
When I run "osrm-contract --v"
|
When I run "osrm-contract -v"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ Feature: osrm-contract command line options: files
|
|||||||
Scenario: osrm-customize - Missing input file
|
Scenario: osrm-customize - Missing input file
|
||||||
When I try to run "osrm-customize over-the-rainbow.osrm"
|
When I try to run "osrm-customize over-the-rainbow.osrm"
|
||||||
And stderr should contain "over-the-rainbow.osrm"
|
And stderr should contain "over-the-rainbow.osrm"
|
||||||
And stderr should contain "not found"
|
And stderr should contain "Missing/Broken"
|
||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Feature: osrm-customize command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
@@ -19,6 +20,7 @@ Feature: osrm-customize command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And it should exit successfully
|
And it should exit successfully
|
||||||
@@ -30,6 +32,7 @@ Feature: osrm-customize command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And it should exit successfully
|
And it should exit successfully
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Feature: osrm-customize command line options: version
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-customize - Version, short
|
Scenario: osrm-customize - Version, short
|
||||||
When I run "osrm-customize --v"
|
When I run "osrm-customize -v"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ Feature: osrm-extract command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--profile"
|
And stdout should contain "--profile"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
@@ -24,6 +25,7 @@ Feature: osrm-extract command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--profile"
|
And stdout should contain "--profile"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
@@ -37,6 +39,7 @@ Feature: osrm-extract command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--profile"
|
And stdout should contain "--profile"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
@extract
|
||||||
|
Feature: osrm-extract must be silent with NONE
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
Scenario: osrm-extract - Passing base file with verbosity NONE
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
functions = require('testbot')
|
||||||
|
|
||||||
|
function way_function(profile, way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.forward_speed = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = way_function
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file} --verbosity NONE"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should not contain "[info]"
|
||||||
|
And stdout should not contain "[error]"
|
||||||
|
And stdout should not contain "10%"
|
||||||
|
And stderr should be empty
|
||||||
@@ -8,7 +8,7 @@ Feature: osrm-extract command line options: version
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-extract - Version, short
|
Scenario: osrm-extract - Version, short
|
||||||
When I run "osrm-extract --v"
|
When I run "osrm-extract -v"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Feature: osrm-partition command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--balance"
|
And stdout should contain "--balance"
|
||||||
@@ -24,6 +25,7 @@ Feature: osrm-partition command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--balance"
|
And stdout should contain "--balance"
|
||||||
@@ -40,6 +42,7 @@ Feature: osrm-partition command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--balance"
|
And stdout should contain "--balance"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Feature: osrm-partition command line options: version
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-partition - Version, short
|
Scenario: osrm-partition - Version, short
|
||||||
When I run "osrm-partition --v"
|
When I run "osrm-partition -v"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Feature: Invalid profile API versions
|
|||||||
Scenario: Profile API version too high
|
Scenario: Profile API version too high
|
||||||
Given the profile file
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 3
|
api_version = 4
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
Feature: Profile API version 3
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
|
Scenario: Basic profile function calls and property values
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = 3
|
||||||
|
|
||||||
|
Set = require('lib/set')
|
||||||
|
Sequence = require('lib/sequence')
|
||||||
|
Handlers = require("lib/way_handlers")
|
||||||
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
|
limit = require("lib/maxspeed").limit
|
||||||
|
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
return {
|
||||||
|
properties = {
|
||||||
|
max_speed_for_map_matching = 180/3.6,
|
||||||
|
use_turn_restrictions = true,
|
||||||
|
continue_straight_at_waypoint = true,
|
||||||
|
weight_name = 'test_version2',
|
||||||
|
weight_precision = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_node(profile, node, result, relations)
|
||||||
|
print ('process_node ' .. node:id())
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_way(profile, way, result, relations)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
|
result.weight = 10
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.forward_speed = 36
|
||||||
|
result.backward_speed = 36
|
||||||
|
|
||||||
|
for _, r in ipairs(relations) do
|
||||||
|
for k, v in pairs(r) do
|
||||||
|
print('data_' .. k .. '_value_' .. v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print ('process_way ' .. way:id() .. ' ' .. result.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_relation(profile, relation, result)
|
||||||
|
local t = relation:get_value_by_key("type")
|
||||||
|
if t == "route" then
|
||||||
|
for _, m in ipairs(relation:members()) do
|
||||||
|
if m:role() == "north" then
|
||||||
|
result[m]['direction'] = 'north'
|
||||||
|
print('direction_north')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print('route_relation')
|
||||||
|
end
|
||||||
|
|
||||||
|
print ('process_relation ' .. relation:id())
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_turn (profile, turn)
|
||||||
|
print('process_turn', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
|
||||||
|
turn.weight = turn.angle == 0 and 0 or 4.2
|
||||||
|
turn.duration = turn.weight
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_segment (profile, segment)
|
||||||
|
print ('process_segment ' .. segment.source.lon .. ' ' .. segment.source.lat)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_node = process_node,
|
||||||
|
process_way = process_way,
|
||||||
|
process_relation = process_relation,
|
||||||
|
process_segment = process_segment,
|
||||||
|
process_turn = process_turn
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
bcd
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ac |
|
||||||
|
| cb |
|
||||||
|
| cd |
|
||||||
|
| ce |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:north | route |
|
||||||
|
| route | ac | road |
|
||||||
|
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should contain "process_relation"
|
||||||
|
And stdout should contain "route_relation"
|
||||||
|
And stdout should contain "direction_north"
|
||||||
|
And stdout should contain "data_direction_value_north"
|
||||||
|
And stdout should contain "process_node"
|
||||||
|
And stdout should contain "process_way"
|
||||||
|
And stdout should contain "process_turn"
|
||||||
|
And stdout should contain "process_segment"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time |
|
||||||
|
| a | b | ac,cb,cb | 19.2s |
|
||||||
|
| a | d | ac,cd,cd | 19.2s |
|
||||||
|
| a | e | ac,ce | 20s |
|
||||||
@@ -11,6 +11,7 @@ Feature: osrm-routed command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "--trial"
|
And stdout should contain "--trial"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--ip"
|
And stdout should contain "--ip"
|
||||||
@@ -30,6 +31,7 @@ Feature: osrm-routed command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "--trial"
|
And stdout should contain "--trial"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--ip"
|
And stdout should contain "--ip"
|
||||||
@@ -49,6 +51,7 @@ Feature: osrm-routed command line options: help
|
|||||||
And stdout should contain "Options:"
|
And stdout should contain "Options:"
|
||||||
And stdout should contain "--version"
|
And stdout should contain "--version"
|
||||||
And stdout should contain "--help"
|
And stdout should contain "--help"
|
||||||
|
And stdout should contain "--verbosity"
|
||||||
And stdout should contain "--trial"
|
And stdout should contain "--trial"
|
||||||
And stdout should contain "Configuration:"
|
And stdout should contain "Configuration:"
|
||||||
And stdout should contain "--ip"
|
And stdout should contain "--ip"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Feature: osrm-routed command line options: version
|
|||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: osrm-routed - Version, short
|
Scenario: osrm-routed - Version, short
|
||||||
When I run "osrm-routed --v"
|
When I run "osrm-routed -v"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module.exports = function () {
|
|||||||
var waypoints = [],
|
var waypoints = [],
|
||||||
columnHeaders = tableRows[0].slice(1),
|
columnHeaders = tableRows[0].slice(1),
|
||||||
rowHeaders = tableRows.map((h) => h[0]).slice(1),
|
rowHeaders = tableRows.map((h) => h[0]).slice(1),
|
||||||
symmetric = columnHeaders.every((ele, i) => ele === rowHeaders[i]);
|
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
|
||||||
|
|
||||||
if (symmetric) {
|
if (symmetric) {
|
||||||
columnHeaders.forEach((nodeName) => {
|
columnHeaders.forEach((nodeName) => {
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ Feature: Alternative route
|
|||||||
| 5 | 6 | dc,ca,ab,bd,dc,dc | |
|
| 5 | 6 | dc,ca,ab,bd,dc,dc | |
|
||||||
| 7 | 8 | ca,ab,bd,dc,ca,ca | |
|
| 7 | 8 | ca,ab,bd,dc,ca,ca | |
|
||||||
|
|
||||||
@4111
|
# This test case does not work in a platform independent way
|
||||||
|
# since it depends on a specific CH structure that is only
|
||||||
|
# present on linux it seems.
|
||||||
|
@4111 @todo
|
||||||
Scenario: Alternative Loop Paths with single node path
|
Scenario: Alternative Loop Paths with single node path
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ Feature: Approach parameter
|
|||||||
| s | e | unrestricted curb | |
|
| s | e | unrestricted curb | |
|
||||||
|
|
||||||
|
|
||||||
Scenario: UTurn test, router can found a route because he can use the roundabout
|
Scenario: UTurn test, router can find a route because he can use the roundabout
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
h
|
h
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ Feature: Bearing parameter
|
|||||||
| from | to | bearings | route | bearing |
|
| from | to | bearings | route | bearing |
|
||||||
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
|
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
|
||||||
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
|
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
|
||||||
| 0 | b | 170 170 | da,da | 0->0,0->0 |
|
| 0 | b | 170 170 | da,da | 0->180,180->0 |
|
||||||
| 0 | b | 189 189 | da,da | 0->0,0->0 |
|
| 0 | b | 189 189 | da,da | 0->180,180->0 |
|
||||||
| 0 | 1 | 90 270 | ab,cd,cd | 0->90,90->0,270->0 |
|
| 0 | 1 | 90 270 | ab,cd,cd | 0->90,90->0,270->0 |
|
||||||
| 1 | 2 | 10 10 | bc,bc | 0->0,0->0 |
|
| 1 | 2 | 10 10 | bc,bc | 0->0,0->0 |
|
||||||
| 1 | 2 | 90 90 | ab,cd,ab,ab | 0->90,90->0,270->180,90->0 |
|
| 1 | 2 | 90 90 | ab,cd,ab,ab | 0->90,90->0,270->180,90->0 |
|
||||||
@@ -108,12 +108,12 @@ Feature: Bearing parameter
|
|||||||
| ha | yes | ring |
|
| ha | yes | ring |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | bearings | route | bearing |
|
| from | to | bearings | route | bearing |
|
||||||
| 0 | q | 0 90 | ia,ring,ring | 0->0,0->90,90->0 |
|
| 0 | q | 0 90 | ia,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,90->0 |
|
||||||
| 0 | a | 45 90 | jb,ring,ring | 0->45,45->180,90->0 |
|
| 0 | a | 45 90 | jb,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,90->0 |
|
||||||
| 0 | q | 90 90 | kc,ring,ring | 0->90,90->180,90->0 |
|
| 0 | q | 90 90 | kc,ring,ring,ring | 0->90,90->180,270->0,90->0 |
|
||||||
| 0 | a | 135 90 | ld,ring,ring | 0->135,135->270,90->0 |
|
| 0 | a | 135 90 | ld,ring,ring,ring | 0->135,135->270,270->0,90->0 |
|
||||||
| 0 | a | 180 90 | me,ring,ring | 0->180,180->270,90->0 |
|
| 0 | a | 180 90 | me,ring,ring,ring | 0->180,180->270,270->0,90->0 |
|
||||||
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
|
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
|
||||||
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
|
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
|
||||||
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
|
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
|
||||||
|
|||||||
@@ -41,6 +41,17 @@ Feature: Basic Distance Matrix
|
|||||||
| c | 30 | 20 | 0 | 30 |
|
| c | 30 | 20 | 0 | 30 |
|
||||||
| d | 60 | 50 | 30 | 0 |
|
| d | 60 | 50 | 30 | 0 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 10 | 30 | 60 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 10 |
|
||||||
|
| c | 30 |
|
||||||
|
| d | 60 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix with fuzzy match
|
Scenario: Testbot - Travel time matrix with fuzzy match
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@@ -132,6 +143,13 @@ Feature: Basic Distance Matrix
|
|||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 10 |
|
||||||
|
| e | 20 |
|
||||||
|
| f | 30 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time 3x2 matrix
|
Scenario: Testbot - Travel time 3x2 matrix
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@@ -308,3 +326,52 @@ Feature: Basic Distance Matrix
|
|||||||
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
|
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
|
||||||
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
|
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
|
||||||
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
|
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix with ties
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
local functions = require('testbot')
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
|
segment.weight = 1
|
||||||
|
segment.duration = 1
|
||||||
|
end
|
||||||
|
functions.process_turn = function(profile, turn)
|
||||||
|
if turn.angle >= 0 then
|
||||||
|
turn.duration = 16
|
||||||
|
else
|
||||||
|
turn.duration = 4
|
||||||
|
end
|
||||||
|
turn.weight = 0
|
||||||
|
end
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| ac |
|
||||||
|
| bd |
|
||||||
|
| dc |
|
||||||
|
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | distance | time | weight |
|
||||||
|
| a | c | ac,ac | 200m | 5s | 5 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 1 | 5 | 10 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 1 |
|
||||||
|
| c | 15 |
|
||||||
|
| d | 10 |
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
@routing @testbot @exclude
|
||||||
|
Feature: Testbot - Exclude flags
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a....b-----c-$-$-d
|
||||||
|
$ $ :
|
||||||
|
e.$.$.f.....g
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | toll | # |
|
||||||
|
| ab | primary | | always drivable |
|
||||||
|
| bc | motorway | | not drivable for exclude=motorway and exclude=motorway,toll |
|
||||||
|
| be | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
| ef | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
| fc | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
| cd | motorway | yes | not drivable for exclude=motorway exclude=toll and exclude=motorway,toll |
|
||||||
|
| fg | primary | | always drivable |
|
||||||
|
| gd | primary | | always drivable |
|
||||||
|
|
||||||
|
Scenario: Testbot - exclude nothing
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | d | ab,bc,cd,cd |
|
||||||
|
| a | g | ab,be,ef,fg,fg |
|
||||||
|
| a | c | ab,bc,bc |
|
||||||
|
| a | f | ab,be,ef,ef |
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | matchings | duration |
|
||||||
|
| ad | ad | 115 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | d |
|
||||||
|
| a | 0 | 115 |
|
||||||
|
| d | 115 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - exclude motorway
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | d | ab,be,ef,fg,gd,gd |
|
||||||
|
| a | g | ab,be,ef,fg,fg |
|
||||||
|
| a | c | ab,be,ef,fc,fc |
|
||||||
|
| a | f | ab,be,ef,ef |
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | matchings | duration |
|
||||||
|
| ad | ad | 125 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | d |
|
||||||
|
| a | 0 | 125 |
|
||||||
|
| d | 125 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - exclude toll
|
||||||
|
Given the query options
|
||||||
|
| exclude | toll |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | d | |
|
||||||
|
| a | g | |
|
||||||
|
| a | c | ab,bc,bc |
|
||||||
|
| a | f | |
|
||||||
|
| f | d | fg,gd,gd |
|
||||||
|
|
||||||
|
Scenario: Testbot - exclude motorway and toll
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway,toll |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | d | |
|
||||||
|
| a | g | |
|
||||||
|
| a | c | |
|
||||||
|
| a | f | |
|
||||||
|
| f | d | fg,gd,gd |
|
||||||
|
|
||||||
|
Scenario: Testbot - exclude with unsupported exclude combination
|
||||||
|
Given the query options
|
||||||
|
| exclude | TwoWords2 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | status | message |
|
||||||
|
| a | d | 400 | Exclude flag combination is not supported. |
|
||||||
|
|
||||||
|
Scenario: Testbot - exclude with invalid exclude class name
|
||||||
|
Given the query options
|
||||||
|
| exclude | foo |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | status | message |
|
||||||
|
| a | d | 400 | Exclude flag combination is not supported. |
|
||||||
|
|
||||||
@@ -167,4 +167,3 @@ Feature: Traffic - speeds
|
|||||||
And the data has been extracted
|
And the data has been extracted
|
||||||
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
And it should exit successfully
|
And it should exit successfully
|
||||||
|
|
||||||
|
|||||||
@@ -379,3 +379,36 @@ Feature: Weight tests
|
|||||||
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
||||||
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
||||||
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
||||||
|
|
||||||
|
@traffic @speed
|
||||||
|
Scenario: Updating speeds without affecting weights.
|
||||||
|
Given the profile file "testbot" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.weight_precision = 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a-----------b
|
||||||
|
\ /
|
||||||
|
c----d
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed |
|
||||||
|
| ab | living_street | 5 |
|
||||||
|
| acdb | motorway | 100 |
|
||||||
|
|
||||||
|
# Note the comma on the last column - this indicates 'keep existing weight value'
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
1,2,100,
|
||||||
|
1,3,5,,junk
|
||||||
|
3,4,5,,
|
||||||
|
4,2,5,
|
||||||
|
"""
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | weights | times |
|
||||||
|
| a,b | acdb,acdb | 78.3m | 11.744,0 | 56.4s,0s |
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#ifndef OSRM_CONTRACTOR_CONTRACT_EXCLUDABLE_GRAPH_HPP
|
||||||
|
#define OSRM_CONTRACTOR_CONTRACT_EXCLUDABLE_GRAPH_HPP
|
||||||
|
|
||||||
|
#include "contractor/contracted_edge_container.hpp"
|
||||||
|
#include "contractor/contractor_graph.hpp"
|
||||||
|
#include "contractor/graph_contractor.hpp"
|
||||||
|
#include "contractor/graph_contractor_adaptors.hpp"
|
||||||
|
#include "contractor/query_graph.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace contractor
|
||||||
|
{
|
||||||
|
|
||||||
|
using GraphFilterAndCore =
|
||||||
|
std::tuple<QueryGraph, std::vector<std::vector<bool>>, std::vector<std::vector<bool>>>;
|
||||||
|
|
||||||
|
inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
|
||||||
|
std::vector<EdgeWeight> node_weights,
|
||||||
|
const std::vector<std::vector<bool>> &filters,
|
||||||
|
const float core_factor = 1.0)
|
||||||
|
{
|
||||||
|
auto num_nodes = contractor_graph_.GetNumberOfNodes();
|
||||||
|
ContractedEdgeContainer edge_container;
|
||||||
|
ContractorGraph shared_core_graph;
|
||||||
|
std::vector<bool> is_shared_core;
|
||||||
|
{
|
||||||
|
ContractorGraph contractor_graph = std::move(contractor_graph_);
|
||||||
|
std::vector<bool> always_allowed(num_nodes, true);
|
||||||
|
for (const auto &filter : filters)
|
||||||
|
{
|
||||||
|
for (const auto node : util::irange<NodeID>(0, num_nodes))
|
||||||
|
{
|
||||||
|
always_allowed[node] = always_allowed[node] && filter[node];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// By not contracting all contractable nodes we avoid creating
|
||||||
|
// a very dense core. This increases the overall graph sizes a little bit
|
||||||
|
// but increases the final CH quality and contraction speed.
|
||||||
|
constexpr float BASE_CORE = 0.9;
|
||||||
|
is_shared_core = contractGraph(contractor_graph,
|
||||||
|
std::move(always_allowed),
|
||||||
|
node_weights,
|
||||||
|
std::min<float>(BASE_CORE, core_factor));
|
||||||
|
|
||||||
|
// Add all non-core edges to container
|
||||||
|
{
|
||||||
|
auto non_core_edges = toEdges<QueryEdge>(contractor_graph);
|
||||||
|
auto new_end =
|
||||||
|
std::remove_if(non_core_edges.begin(), non_core_edges.end(), [&](const auto &edge) {
|
||||||
|
return is_shared_core[edge.source] && is_shared_core[edge.target];
|
||||||
|
});
|
||||||
|
non_core_edges.resize(new_end - non_core_edges.begin());
|
||||||
|
edge_container.Insert(std::move(non_core_edges));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract core graph for further contraction
|
||||||
|
shared_core_graph = contractor_graph.Filter(
|
||||||
|
[&is_shared_core](const NodeID node) { return is_shared_core[node]; });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<bool>> cores;
|
||||||
|
for (const auto &filter : filters)
|
||||||
|
{
|
||||||
|
auto filtered_core_graph =
|
||||||
|
shared_core_graph.Filter([&filter](const NodeID node) { return filter[node]; });
|
||||||
|
|
||||||
|
auto core = contractGraph(
|
||||||
|
filtered_core_graph, is_shared_core, is_shared_core, node_weights, core_factor);
|
||||||
|
if (core_factor == 1.0)
|
||||||
|
{
|
||||||
|
core.clear();
|
||||||
|
}
|
||||||
|
cores.push_back(std::move(core));
|
||||||
|
|
||||||
|
edge_container.Merge(toEdges<QueryEdge>(std::move(filtered_core_graph)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return GraphFilterAndCore{QueryGraph{num_nodes, std::move(edge_container.edges)},
|
||||||
|
edge_container.MakeEdgeFilters(),
|
||||||
|
std::move(cores)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
#ifndef OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
|
||||||
|
#define OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
|
||||||
|
|
||||||
|
#include "contractor/query_edge.hpp"
|
||||||
|
#include "util/deallocating_vector.hpp"
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace contractor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ContractedEdgeContainer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using MergedFlags = std::uint8_t;
|
||||||
|
static constexpr auto ALL_FLAGS = 0xFF;
|
||||||
|
|
||||||
|
static bool mergeCompare(const QueryEdge &lhs, const QueryEdge &rhs)
|
||||||
|
{
|
||||||
|
return std::tie(lhs.source,
|
||||||
|
lhs.target,
|
||||||
|
lhs.data.shortcut,
|
||||||
|
lhs.data.turn_id,
|
||||||
|
lhs.data.weight,
|
||||||
|
lhs.data.duration,
|
||||||
|
lhs.data.forward,
|
||||||
|
lhs.data.backward) < std::tie(rhs.source,
|
||||||
|
rhs.target,
|
||||||
|
rhs.data.shortcut,
|
||||||
|
rhs.data.turn_id,
|
||||||
|
rhs.data.weight,
|
||||||
|
rhs.data.duration,
|
||||||
|
rhs.data.forward,
|
||||||
|
rhs.data.backward);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mergable(const QueryEdge &lhs, const QueryEdge &rhs)
|
||||||
|
{
|
||||||
|
// only true if both are equal
|
||||||
|
return !mergeCompare(lhs, rhs) && !mergeCompare(rhs, lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Insert(util::DeallocatingVector<QueryEdge> new_edges)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(edges.size() == 0);
|
||||||
|
BOOST_ASSERT(flags.empty());
|
||||||
|
|
||||||
|
edges = std::move(new_edges);
|
||||||
|
flags.resize(edges.size(), ALL_FLAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Merge(util::DeallocatingVector<QueryEdge> new_edges)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT);
|
||||||
|
|
||||||
|
const MergedFlags flag = 1 << index++;
|
||||||
|
|
||||||
|
std::vector<MergedFlags> merged_flags;
|
||||||
|
merged_flags.reserve(flags.size() * 1.1);
|
||||||
|
util::DeallocatingVector<QueryEdge> merged_edges;
|
||||||
|
merged_edges.reserve(edges.size() * 1.1);
|
||||||
|
|
||||||
|
auto flags_iter = flags.begin();
|
||||||
|
// destructive iterators, this is single-pass only
|
||||||
|
// FIXME using dbegin() dend() will result in segfaults.
|
||||||
|
auto edges_iter = edges.dbegin();
|
||||||
|
auto edges_end = edges.dend();
|
||||||
|
auto new_edges_iter = new_edges.dbegin();
|
||||||
|
auto new_edges_end = new_edges.dend();
|
||||||
|
|
||||||
|
while (edges_iter != edges_end && new_edges_iter != new_edges_end)
|
||||||
|
{
|
||||||
|
while (edges_iter != edges_end && mergeCompare(*edges_iter, *new_edges_iter))
|
||||||
|
{
|
||||||
|
merged_edges.push_back(*edges_iter);
|
||||||
|
merged_flags.push_back(*flags_iter);
|
||||||
|
edges_iter++;
|
||||||
|
flags_iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edges_iter == edges_end)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (new_edges_iter != new_edges_end && mergeCompare(*new_edges_iter, *edges_iter))
|
||||||
|
{
|
||||||
|
merged_edges.push_back(*new_edges_iter);
|
||||||
|
merged_flags.push_back(flag);
|
||||||
|
new_edges_iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_edges_iter == new_edges_end)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (edges_iter != edges_end && new_edges_iter != new_edges_end &&
|
||||||
|
mergable(*edges_iter, *new_edges_iter))
|
||||||
|
{
|
||||||
|
merged_edges.push_back(*edges_iter);
|
||||||
|
merged_flags.push_back(*flags_iter | flag);
|
||||||
|
|
||||||
|
edges_iter++;
|
||||||
|
flags_iter++;
|
||||||
|
new_edges_iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (edges_iter != edges_end)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(new_edges_iter == new_edges_end);
|
||||||
|
merged_edges.push_back(*edges_iter++);
|
||||||
|
merged_flags.push_back(*flags_iter++);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (new_edges_iter != new_edges_end)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(edges_iter == edges_end);
|
||||||
|
merged_edges.push_back(*new_edges_iter++);
|
||||||
|
merged_flags.push_back(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = std::move(merged_flags);
|
||||||
|
edges = std::move(merged_edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MakeEdgeFilters() const
|
||||||
|
{
|
||||||
|
std::vector<std::vector<bool>> filters(index);
|
||||||
|
for (const auto flag_index : util::irange<std::size_t>(0, index))
|
||||||
|
{
|
||||||
|
MergedFlags mask = 1 << flag_index;
|
||||||
|
for (const auto flag : flags)
|
||||||
|
{
|
||||||
|
filters[flag_index].push_back(flag & mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t index = 0;
|
||||||
|
std::vector<MergedFlags> flags;
|
||||||
|
util::DeallocatingVector<QueryEdge> edges;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -43,12 +43,9 @@ namespace contractor
|
|||||||
struct ContractorConfig final : storage::IOConfig
|
struct ContractorConfig final : storage::IOConfig
|
||||||
{
|
{
|
||||||
ContractorConfig()
|
ContractorConfig()
|
||||||
: IOConfig(
|
: IOConfig({".osrm.ebg", ".osrm.ebg_nodes", ".osrm.properties"},
|
||||||
{
|
{},
|
||||||
".osrm",
|
{".osrm.level", ".osrm.core", ".osrm.hsgr", ".osrm.enw"}),
|
||||||
},
|
|
||||||
{},
|
|
||||||
{".osrm.level", ".osrm.core", ".osrm.hsgr", ".osrm.enw"}),
|
|
||||||
requested_num_threads(0)
|
requested_num_threads(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
#ifndef OSRM_CONTRACTOR_DIJKSTRA_HPP
|
|
||||||
#define OSRM_CONTRACTOR_DIJKSTRA_HPP
|
|
||||||
|
|
||||||
#include "contractor/contractor_graph.hpp"
|
|
||||||
#include "contractor/contractor_heap.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace contractor
|
|
||||||
{
|
|
||||||
|
|
||||||
// allow access to the heap itself, add Dijkstra functionality on top
|
|
||||||
class ContractorDijkstra
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ContractorDijkstra(std::size_t heap_size);
|
|
||||||
|
|
||||||
// search the graph up
|
|
||||||
void Run(const unsigned number_of_targets,
|
|
||||||
const int node_limit,
|
|
||||||
const int weight_limit,
|
|
||||||
const NodeID forbidden_node,
|
|
||||||
const ContractorGraph &graph);
|
|
||||||
|
|
||||||
// adaption of the heap interface
|
|
||||||
void Clear();
|
|
||||||
bool WasInserted(const NodeID node) const;
|
|
||||||
void Insert(const NodeID node,
|
|
||||||
const ContractorHeap::WeightType weight,
|
|
||||||
const ContractorHeap::DataType &data);
|
|
||||||
|
|
||||||
// cannot be const due to node-hash access in the binary heap :(
|
|
||||||
ContractorHeap::WeightType GetKey(const NodeID node);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RelaxNode(const NodeID node,
|
|
||||||
const int node_weight,
|
|
||||||
const NodeID forbidden_node,
|
|
||||||
const ContractorGraph &graph);
|
|
||||||
|
|
||||||
ContractorHeap heap;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace contractor
|
|
||||||
} // namespace osrm
|
|
||||||
|
|
||||||
#endif // OSRM_CONTRACTOR_DIJKSTRA_HPP
|
|
||||||
@@ -12,8 +12,7 @@ namespace contractor
|
|||||||
struct ContractorEdgeData
|
struct ContractorEdgeData
|
||||||
{
|
{
|
||||||
ContractorEdgeData()
|
ContractorEdgeData()
|
||||||
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0),
|
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
|
||||||
is_original_via_node_ID(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ContractorEdgeData(EdgeWeight weight,
|
ContractorEdgeData(EdgeWeight weight,
|
||||||
@@ -24,18 +23,17 @@ struct ContractorEdgeData
|
|||||||
bool forward,
|
bool forward,
|
||||||
bool backward)
|
bool backward)
|
||||||
: weight(weight), duration(duration), id(id),
|
: weight(weight), duration(duration), id(id),
|
||||||
originalEdges(std::min((1u << 28) - 1u, original_edges)), shortcut(shortcut),
|
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
|
||||||
forward(forward), backward(backward), is_original_via_node_ID(false)
|
forward(forward), backward(backward)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned originalEdges : 28;
|
unsigned originalEdges : 29;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
bool is_original_via_node_ID : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using ContractorGraph = util::DynamicGraph<ContractorEdgeData>;
|
using ContractorGraph = util::DynamicGraph<ContractorEdgeData>;
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef OSRM_CONTRACTOR_SEARCH_HPP
|
||||||
|
#define OSRM_CONTRACTOR_SEARCH_HPP
|
||||||
|
|
||||||
|
#include "contractor/contractor_graph.hpp"
|
||||||
|
#include "contractor/contractor_heap.hpp"
|
||||||
|
|
||||||
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace contractor
|
||||||
|
{
|
||||||
|
|
||||||
|
void search(ContractorHeap &heap,
|
||||||
|
const ContractorGraph &graph,
|
||||||
|
const unsigned number_of_targets,
|
||||||
|
const int node_limit,
|
||||||
|
const EdgeWeight weight_limit,
|
||||||
|
const NodeID forbidden_node);
|
||||||
|
|
||||||
|
} // namespace contractor
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif // OSRM_CONTRACTOR_DIJKSTRA_HPP
|
||||||
@@ -16,54 +16,85 @@ namespace files
|
|||||||
{
|
{
|
||||||
// reads .osrm.core
|
// reads .osrm.core
|
||||||
template <typename CoreVectorT>
|
template <typename CoreVectorT>
|
||||||
void readCoreMarker(const boost::filesystem::path &path, CoreVectorT &is_core_node)
|
void readCoreMarker(const boost::filesystem::path &path, std::vector<CoreVectorT> &cores)
|
||||||
{
|
{
|
||||||
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
|
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
|
||||||
"is_core_node must be a vector");
|
"cores must be a vector of boolean vectors");
|
||||||
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
||||||
|
|
||||||
storage::serialization::read(reader, is_core_node);
|
auto num_cores = reader.ReadElementCount64();
|
||||||
|
cores.resize(num_cores);
|
||||||
|
for (const auto index : util::irange<std::size_t>(0, num_cores))
|
||||||
|
{
|
||||||
|
storage::serialization::read(reader, cores[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.core
|
// writes .osrm.core
|
||||||
template <typename CoreVectorT>
|
template <typename CoreVectorT>
|
||||||
void writeCoreMarker(const boost::filesystem::path &path, const CoreVectorT &is_core_node)
|
void writeCoreMarker(const boost::filesystem::path &path, const std::vector<CoreVectorT> &cores)
|
||||||
{
|
{
|
||||||
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
|
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
|
||||||
"is_core_node must be a vector");
|
"cores must be a vector of boolean vectors");
|
||||||
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
||||||
|
|
||||||
storage::serialization::write(writer, is_core_node);
|
writer.WriteElementCount64(cores.size());
|
||||||
|
for (const auto &core : cores)
|
||||||
|
{
|
||||||
|
storage::serialization::write(writer, core);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.hsgr file
|
// reads .osrm.hsgr file
|
||||||
template <typename QueryGraphT>
|
template <typename QueryGraphT, typename EdgeFilterT>
|
||||||
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
|
inline void readGraph(const boost::filesystem::path &path,
|
||||||
|
unsigned &checksum,
|
||||||
|
QueryGraphT &graph,
|
||||||
|
std::vector<EdgeFilterT> &edge_filter)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
||||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
std::is_same<QueryGraph, QueryGraphT>::value,
|
||||||
"graph must be of type QueryGraph<>");
|
"graph must be of type QueryGraph<>");
|
||||||
|
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
|
||||||
|
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
|
||||||
|
"edge_filter must be a container of vector<bool> or vector_view<bool>");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::io::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
reader.ReadInto(checksum);
|
reader.ReadInto(checksum);
|
||||||
util::serialization::read(reader, graph);
|
util::serialization::read(reader, graph);
|
||||||
|
auto count = reader.ReadElementCount64();
|
||||||
|
edge_filter.resize(count);
|
||||||
|
for (const auto index : util::irange<std::size_t>(0, count))
|
||||||
|
{
|
||||||
|
storage::serialization::read(reader, edge_filter[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.hsgr file
|
// writes .osrm.hsgr file
|
||||||
template <typename QueryGraphT>
|
template <typename QueryGraphT, typename EdgeFilterT>
|
||||||
inline void
|
inline void writeGraph(const boost::filesystem::path &path,
|
||||||
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
|
unsigned checksum,
|
||||||
|
const QueryGraphT &graph,
|
||||||
|
const std::vector<EdgeFilterT> &edge_filter)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
||||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
std::is_same<QueryGraph, QueryGraphT>::value,
|
||||||
"graph must be of type QueryGraph<>");
|
"graph must be of type QueryGraph<>");
|
||||||
|
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
|
||||||
|
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
|
||||||
|
"edge_filter must be a container of vector<bool> or vector_view<bool>");
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::io::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
writer.WriteOne(checksum);
|
writer.WriteOne(checksum);
|
||||||
util::serialization::write(writer, graph);
|
util::serialization::write(writer, graph);
|
||||||
|
writer.WriteElementCount64(edge_filter.size());
|
||||||
|
for (const auto &filter : edge_filter)
|
||||||
|
{
|
||||||
|
storage::serialization::write(writer, filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .levels file
|
// reads .levels file
|
||||||
|
|||||||
@@ -1,427 +1,41 @@
|
|||||||
#ifndef OSRM_CONTRACTOR_GRAPH_CONTRACTOR_HPP
|
#ifndef OSRM_CONTRACTOR_GRAPH_CONTRACTOR_HPP
|
||||||
#define OSRM_CONTRACTOR_GRAPH_CONTRACTOR_HPP
|
#define OSRM_CONTRACTOR_GRAPH_CONTRACTOR_HPP
|
||||||
|
|
||||||
#include "contractor/contractor_dijkstra.hpp"
|
|
||||||
#include "contractor/contractor_graph.hpp"
|
#include "contractor/contractor_graph.hpp"
|
||||||
#include "contractor/query_edge.hpp"
|
|
||||||
#include "util/deallocating_vector.hpp"
|
|
||||||
#include "util/integer_range.hpp"
|
|
||||||
#include "util/log.hpp"
|
|
||||||
#include "util/percent.hpp"
|
|
||||||
#include "util/timing_util.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
|
||||||
#include "util/xor_fast_hash.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include "util/filtered_graph.hpp"
|
||||||
|
|
||||||
#include <tbb/enumerable_thread_specific.h>
|
#include <tuple>
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/parallel_sort.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if USE_STXXL_LIBRARY
|
|
||||||
#include <stxxl/vector>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace contractor
|
namespace contractor
|
||||||
{
|
{
|
||||||
|
|
||||||
class GraphContractor
|
std::vector<bool> contractGraph(ContractorGraph &graph,
|
||||||
|
std::vector<bool> node_is_uncontracted,
|
||||||
|
std::vector<bool> node_is_contractable,
|
||||||
|
std::vector<EdgeWeight> node_weights,
|
||||||
|
double core_factor = 1.0);
|
||||||
|
|
||||||
|
// Overload for contracting all nodes
|
||||||
|
inline auto contractGraph(ContractorGraph &graph,
|
||||||
|
std::vector<EdgeWeight> node_weights,
|
||||||
|
double core_factor = 1.0)
|
||||||
{
|
{
|
||||||
private:
|
return contractGraph(graph, {}, {}, std::move(node_weights), core_factor);
|
||||||
#if USE_STXXL_LIBRARY
|
}
|
||||||
template <typename T> using ExternalVector = stxxl::vector<T>;
|
|
||||||
#else
|
|
||||||
template <typename T> using ExternalVector = std::vector<T>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ContractorThreadData
|
// Overload no contracted nodes
|
||||||
{
|
inline auto contractGraph(ContractorGraph &graph,
|
||||||
ContractorDijkstra dijkstra;
|
std::vector<bool> node_is_contractable,
|
||||||
std::vector<ContractorEdge> inserted_edges;
|
std::vector<EdgeWeight> node_weights,
|
||||||
std::vector<NodeID> neighbours;
|
double core_factor = 1.0)
|
||||||
explicit ContractorThreadData(NodeID nodes) : dijkstra(nodes) {}
|
{
|
||||||
};
|
return contractGraph(
|
||||||
|
graph, {}, std::move(node_is_contractable), std::move(node_weights), core_factor);
|
||||||
using NodeDepth = int;
|
}
|
||||||
|
|
||||||
struct ContractionStats
|
|
||||||
{
|
|
||||||
int edges_deleted_count;
|
|
||||||
int edges_added_count;
|
|
||||||
int original_edges_deleted_count;
|
|
||||||
int original_edges_added_count;
|
|
||||||
ContractionStats()
|
|
||||||
: edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0),
|
|
||||||
original_edges_added_count(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RemainingNodeData
|
|
||||||
{
|
|
||||||
RemainingNodeData() : id(0), is_independent(false) {}
|
|
||||||
NodeID id : 31;
|
|
||||||
bool is_independent : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ThreadDataContainer
|
|
||||||
{
|
|
||||||
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
|
|
||||||
|
|
||||||
inline ContractorThreadData *GetThreadData()
|
|
||||||
{
|
|
||||||
bool exists = false;
|
|
||||||
auto &ref = data.local(exists);
|
|
||||||
if (!exists)
|
|
||||||
{
|
|
||||||
// ref = std::make_shared<ContractorThreadData>(number_of_nodes);
|
|
||||||
ref = std::make_shared<ContractorThreadData>(4000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ref.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
int number_of_nodes;
|
|
||||||
using EnumerableThreadData =
|
|
||||||
tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
|
|
||||||
EnumerableThreadData data;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
GraphContractor(int nodes, std::vector<ContractorEdge> input_edge_list);
|
|
||||||
|
|
||||||
GraphContractor(int nodes,
|
|
||||||
std::vector<ContractorEdge> edges,
|
|
||||||
std::vector<float> node_levels_,
|
|
||||||
std::vector<EdgeWeight> node_weights_);
|
|
||||||
|
|
||||||
/* Flush all data from the contraction to disc and reorder stuff for better locality */
|
|
||||||
void FlushDataAndRebuildContractorGraph(ThreadDataContainer &thread_data_list,
|
|
||||||
std::vector<RemainingNodeData> &remaining_nodes,
|
|
||||||
std::vector<float> &node_priorities);
|
|
||||||
|
|
||||||
void Run(double core_factor = 1.0);
|
|
||||||
|
|
||||||
std::vector<bool> GetCoreMarker();
|
|
||||||
|
|
||||||
std::vector<float> GetNodeLevels();
|
|
||||||
|
|
||||||
template <class Edge> inline util::DeallocatingVector<Edge> GetEdges()
|
|
||||||
{
|
|
||||||
util::DeallocatingVector<Edge> edges;
|
|
||||||
|
|
||||||
util::UnbufferedLog log;
|
|
||||||
log << "Getting edges of minimized graph ";
|
|
||||||
util::Percent p(log, contractor_graph->GetNumberOfNodes());
|
|
||||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
|
||||||
if (contractor_graph->GetNumberOfNodes())
|
|
||||||
{
|
|
||||||
Edge new_edge;
|
|
||||||
for (const auto node : util::irange(0u, number_of_nodes))
|
|
||||||
{
|
|
||||||
p.PrintStatus(node);
|
|
||||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const NodeID target = contractor_graph->GetTarget(edge);
|
|
||||||
const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge);
|
|
||||||
if (!orig_node_id_from_new_node_id_map.empty())
|
|
||||||
{
|
|
||||||
new_edge.source = orig_node_id_from_new_node_id_map[node];
|
|
||||||
new_edge.target = orig_node_id_from_new_node_id_map[target];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_edge.source = node;
|
|
||||||
new_edge.target = target;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.source, "Source id invalid");
|
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
|
||||||
new_edge.data.weight = data.weight;
|
|
||||||
new_edge.data.duration = data.duration;
|
|
||||||
new_edge.data.shortcut = data.shortcut;
|
|
||||||
if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty())
|
|
||||||
{
|
|
||||||
// tranlate the _node id_ of the shortcutted node
|
|
||||||
new_edge.data.turn_id = orig_node_id_from_new_node_id_map[data.id];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_edge.data.turn_id = data.id;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
|
|
||||||
"edge id invalid");
|
|
||||||
new_edge.data.forward = data.forward;
|
|
||||||
new_edge.data.backward = data.backward;
|
|
||||||
edges.push_back(new_edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contractor_graph.reset();
|
|
||||||
orig_node_id_from_new_node_id_map.clear();
|
|
||||||
orig_node_id_from_new_node_id_map.shrink_to_fit();
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 == orig_node_id_from_new_node_id_map.capacity());
|
|
||||||
|
|
||||||
edges.append(external_edge_list.begin(), external_edge_list.end());
|
|
||||||
external_edge_list.clear();
|
|
||||||
|
|
||||||
// sort and remove duplicates
|
|
||||||
tbb::parallel_sort(edges.begin(), edges.end());
|
|
||||||
auto new_end = std::unique(edges.begin(), edges.end());
|
|
||||||
edges.resize(new_end - edges.begin());
|
|
||||||
|
|
||||||
return edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float EvaluateNodePriority(ContractorThreadData *const data,
|
|
||||||
const NodeDepth node_depth,
|
|
||||||
const NodeID node);
|
|
||||||
|
|
||||||
template <bool RUNSIMULATION>
|
|
||||||
bool
|
|
||||||
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
|
|
||||||
{
|
|
||||||
auto &dijkstra = data->dijkstra;
|
|
||||||
std::size_t inserted_edges_size = data->inserted_edges.size();
|
|
||||||
std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
|
|
||||||
constexpr bool SHORTCUT_ARC = true;
|
|
||||||
constexpr bool FORWARD_DIRECTION_ENABLED = true;
|
|
||||||
constexpr bool FORWARD_DIRECTION_DISABLED = false;
|
|
||||||
constexpr bool REVERSE_DIRECTION_ENABLED = true;
|
|
||||||
constexpr bool REVERSE_DIRECTION_DISABLED = false;
|
|
||||||
|
|
||||||
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
|
|
||||||
const NodeID source = contractor_graph->GetTarget(in_edge);
|
|
||||||
if (source == node)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(stats != nullptr);
|
|
||||||
++stats->edges_deleted_count;
|
|
||||||
stats->original_edges_deleted_count += in_data.originalEdges;
|
|
||||||
}
|
|
||||||
if (!in_data.backward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dijkstra.Clear();
|
|
||||||
dijkstra.Insert(source, 0, ContractorHeapData{});
|
|
||||||
EdgeWeight max_weight = 0;
|
|
||||||
unsigned number_of_targets = 0;
|
|
||||||
|
|
||||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
|
|
||||||
if (!out_data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
|
||||||
if (node == target)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const EdgeWeight path_weight = in_data.weight + out_data.weight;
|
|
||||||
if (target == source)
|
|
||||||
{
|
|
||||||
if (path_weight < node_weights[node])
|
|
||||||
{
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
// make sure to prune better, but keep inserting this loop if it should
|
|
||||||
// still be the best
|
|
||||||
// CAREFUL: This only works due to the independent node-setting. This
|
|
||||||
// guarantees that source is not connected to another node that is
|
|
||||||
// contracted
|
|
||||||
node_weights[source] = path_weight + 1;
|
|
||||||
BOOST_ASSERT(stats != nullptr);
|
|
||||||
stats->edges_added_count += 2;
|
|
||||||
stats->original_edges_added_count +=
|
|
||||||
2 * (out_data.originalEdges + in_data.originalEdges);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// CAREFUL: This only works due to the independent node-setting. This
|
|
||||||
// guarantees that source is not connected to another node that is
|
|
||||||
// contracted
|
|
||||||
node_weights[source] = path_weight; // make sure to prune better
|
|
||||||
inserted_edges.emplace_back(source,
|
|
||||||
target,
|
|
||||||
path_weight,
|
|
||||||
in_data.duration + out_data.duration,
|
|
||||||
out_data.originalEdges +
|
|
||||||
in_data.originalEdges,
|
|
||||||
node,
|
|
||||||
SHORTCUT_ARC,
|
|
||||||
FORWARD_DIRECTION_ENABLED,
|
|
||||||
REVERSE_DIRECTION_DISABLED);
|
|
||||||
|
|
||||||
inserted_edges.emplace_back(target,
|
|
||||||
source,
|
|
||||||
path_weight,
|
|
||||||
in_data.duration + out_data.duration,
|
|
||||||
out_data.originalEdges +
|
|
||||||
in_data.originalEdges,
|
|
||||||
node,
|
|
||||||
SHORTCUT_ARC,
|
|
||||||
FORWARD_DIRECTION_DISABLED,
|
|
||||||
REVERSE_DIRECTION_ENABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
max_weight = std::max(max_weight, path_weight);
|
|
||||||
if (!dijkstra.WasInserted(target))
|
|
||||||
{
|
|
||||||
dijkstra.Insert(target, INVALID_EDGE_WEIGHT, ContractorHeapData{0, true});
|
|
||||||
++number_of_targets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000;
|
|
||||||
dijkstra.Run(number_of_targets,
|
|
||||||
SIMULATION_SEARCH_SPACE_SIZE,
|
|
||||||
max_weight,
|
|
||||||
node,
|
|
||||||
*contractor_graph);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const int constexpr FULL_SEARCH_SPACE_SIZE = 2000;
|
|
||||||
dijkstra.Run(
|
|
||||||
number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, *contractor_graph);
|
|
||||||
}
|
|
||||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
|
|
||||||
if (!out_data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
|
||||||
if (target == node)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const EdgeWeight path_weight = in_data.weight + out_data.weight;
|
|
||||||
const EdgeWeight weight = dijkstra.GetKey(target);
|
|
||||||
if (path_weight < weight)
|
|
||||||
{
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(stats != nullptr);
|
|
||||||
stats->edges_added_count += 2;
|
|
||||||
stats->original_edges_added_count +=
|
|
||||||
2 * (out_data.originalEdges + in_data.originalEdges);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inserted_edges.emplace_back(source,
|
|
||||||
target,
|
|
||||||
path_weight,
|
|
||||||
in_data.duration + out_data.duration,
|
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
|
||||||
node,
|
|
||||||
SHORTCUT_ARC,
|
|
||||||
FORWARD_DIRECTION_ENABLED,
|
|
||||||
REVERSE_DIRECTION_DISABLED);
|
|
||||||
|
|
||||||
inserted_edges.emplace_back(target,
|
|
||||||
source,
|
|
||||||
path_weight,
|
|
||||||
in_data.duration + out_data.duration,
|
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
|
||||||
node,
|
|
||||||
SHORTCUT_ARC,
|
|
||||||
FORWARD_DIRECTION_DISABLED,
|
|
||||||
REVERSE_DIRECTION_ENABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check For One-Way Streets to decide on the creation of self-loops
|
|
||||||
|
|
||||||
if (!RUNSIMULATION)
|
|
||||||
{
|
|
||||||
std::size_t iend = inserted_edges.size();
|
|
||||||
for (std::size_t i = inserted_edges_size; i < iend; ++i)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for (std::size_t other = i + 1; other < iend; ++other)
|
|
||||||
{
|
|
||||||
if (inserted_edges[other].source != inserted_edges[i].source)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inserted_edges[other].target != inserted_edges[i].target)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inserted_edges[other].data.weight != inserted_edges[i].data.weight)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
inserted_edges[other].data.forward |= inserted_edges[i].data.forward;
|
|
||||||
inserted_edges[other].data.backward |= inserted_edges[i].data.backward;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
inserted_edges[inserted_edges_size++] = inserted_edges[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inserted_edges.resize(inserted_edges_size);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node);
|
|
||||||
|
|
||||||
bool UpdateNodeNeighbours(std::vector<float> &priorities,
|
|
||||||
std::vector<NodeDepth> &node_depth,
|
|
||||||
ContractorThreadData *const data,
|
|
||||||
const NodeID node);
|
|
||||||
|
|
||||||
bool IsNodeIndependent(const std::vector<float> &priorities,
|
|
||||||
ContractorThreadData *const data,
|
|
||||||
NodeID node) const;
|
|
||||||
|
|
||||||
// This bias function takes up 22 assembly instructions in total on X86
|
|
||||||
bool Bias(const NodeID a, const NodeID b) const;
|
|
||||||
|
|
||||||
std::shared_ptr<ContractorGraph> contractor_graph;
|
|
||||||
ExternalVector<QueryEdge> external_edge_list;
|
|
||||||
std::vector<NodeID> orig_node_id_from_new_node_id_map;
|
|
||||||
std::vector<float> node_levels;
|
|
||||||
|
|
||||||
// A list of weights for every node in the graph.
|
|
||||||
// The weight represents the cost for a u-turn on the segment in the base-graph in addition to
|
|
||||||
// its traversal.
|
|
||||||
// During contraction, self-loops are checked against this node weight to ensure that necessary
|
|
||||||
// self-loops are added.
|
|
||||||
std::vector<EdgeWeight> node_weights;
|
|
||||||
std::vector<bool> is_core_node;
|
|
||||||
util::XORFastHash<> fast_hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace contractor
|
} // namespace contractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include "contractor/contractor_graph.hpp"
|
#include "contractor/contractor_graph.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
|
#include "util/percent.hpp"
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -13,7 +16,7 @@ namespace contractor
|
|||||||
|
|
||||||
// Make sure to move in the input edge list!
|
// Make sure to move in the input edge list!
|
||||||
template <typename InputEdgeContainer>
|
template <typename InputEdgeContainer>
|
||||||
std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge_list)
|
ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer input_edge_list)
|
||||||
{
|
{
|
||||||
std::vector<ContractorEdge> edges;
|
std::vector<ContractorEdge> edges;
|
||||||
edges.reserve(input_edge_list.size() * 2);
|
edges.reserve(input_edge_list.size() * 2);
|
||||||
@@ -52,9 +55,115 @@ std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge
|
|||||||
false,
|
false,
|
||||||
input_edge.data.backward ? true : false,
|
input_edge.data.backward ? true : false,
|
||||||
input_edge.data.forward ? true : false);
|
input_edge.data.forward ? true : false);
|
||||||
|
};
|
||||||
|
tbb::parallel_sort(edges.begin(), edges.end());
|
||||||
|
|
||||||
|
NodeID edge = 0;
|
||||||
|
for (NodeID i = 0; i < edges.size();)
|
||||||
|
{
|
||||||
|
const NodeID source = edges[i].source;
|
||||||
|
const NodeID target = edges[i].target;
|
||||||
|
const NodeID id = edges[i].data.id;
|
||||||
|
// remove eigenloops
|
||||||
|
if (source == target)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ContractorEdge forward_edge;
|
||||||
|
ContractorEdge reverse_edge;
|
||||||
|
forward_edge.source = reverse_edge.source = source;
|
||||||
|
forward_edge.target = reverse_edge.target = target;
|
||||||
|
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||||
|
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||||
|
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||||
|
forward_edge.data.id = reverse_edge.data.id = id;
|
||||||
|
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
||||||
|
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
||||||
|
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
||||||
|
// remove parallel edges
|
||||||
|
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||||
|
{
|
||||||
|
if (edges[i].data.forward)
|
||||||
|
{
|
||||||
|
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
||||||
|
forward_edge.data.duration =
|
||||||
|
std::min(edges[i].data.duration, forward_edge.data.duration);
|
||||||
|
}
|
||||||
|
if (edges[i].data.backward)
|
||||||
|
{
|
||||||
|
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
||||||
|
reverse_edge.data.duration =
|
||||||
|
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
|
if (forward_edge.data.weight == reverse_edge.data.weight)
|
||||||
|
{
|
||||||
|
if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
forward_edge.data.backward = true;
|
||||||
|
edges[edge++] = forward_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // insert seperate edges
|
||||||
|
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
edges[edge++] = forward_edge;
|
||||||
|
}
|
||||||
|
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
edges[edge++] = reverse_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// FIXME not sure if we need this
|
util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size();
|
||||||
edges.shrink_to_fit();
|
edges.resize(edge);
|
||||||
|
|
||||||
|
return ContractorGraph{number_of_nodes, edges};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Edge, typename GraphT> inline util::DeallocatingVector<Edge> toEdges(GraphT graph)
|
||||||
|
{
|
||||||
|
util::DeallocatingVector<Edge> edges;
|
||||||
|
|
||||||
|
util::UnbufferedLog log;
|
||||||
|
log << "Getting edges of minimized graph ";
|
||||||
|
util::Percent p(log, graph.GetNumberOfNodes());
|
||||||
|
const NodeID number_of_nodes = graph.GetNumberOfNodes();
|
||||||
|
if (graph.GetNumberOfNodes())
|
||||||
|
{
|
||||||
|
Edge new_edge;
|
||||||
|
for (const auto node : util::irange(0u, number_of_nodes))
|
||||||
|
{
|
||||||
|
p.PrintStatus(node);
|
||||||
|
for (auto edge : graph.GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const NodeID target = graph.GetTarget(edge);
|
||||||
|
const ContractorGraph::EdgeData &data = graph.GetEdgeData(edge);
|
||||||
|
new_edge.source = node;
|
||||||
|
new_edge.target = target;
|
||||||
|
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
||||||
|
new_edge.data.weight = data.weight;
|
||||||
|
new_edge.data.duration = data.duration;
|
||||||
|
new_edge.data.shortcut = data.shortcut;
|
||||||
|
new_edge.data.turn_id = data.id;
|
||||||
|
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
|
||||||
|
"edge id invalid");
|
||||||
|
new_edge.data.forward = data.forward;
|
||||||
|
new_edge.data.backward = data.backward;
|
||||||
|
edges.push_back(new_edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort and remove duplicates
|
||||||
|
tbb::parallel_sort(edges.begin(), edges.end());
|
||||||
|
auto new_end = std::unique(edges.begin(), edges.end());
|
||||||
|
edges.resize(new_end - edges.begin());
|
||||||
|
|
||||||
return edges;
|
return edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,17 @@ struct QueryEdge
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EdgeData(const NodeID turn_id,
|
||||||
|
const bool shortcut,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
const bool forward,
|
||||||
|
const bool backward)
|
||||||
|
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
|
||||||
|
forward(forward), backward(backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <class OtherT> EdgeData(const OtherT &other)
|
template <class OtherT> EdgeData(const OtherT &other)
|
||||||
{
|
{
|
||||||
weight = other.weight;
|
weight = other.weight;
|
||||||
|
|||||||
@@ -31,16 +31,33 @@ class CellCustomizer
|
|||||||
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
||||||
|
|
||||||
template <typename GraphT>
|
template <typename GraphT>
|
||||||
void Customize(
|
void Customize(const GraphT &graph,
|
||||||
const GraphT &graph, Heap &heap, partition::CellStorage &cells, LevelID level, CellID id)
|
Heap &heap,
|
||||||
|
const partition::CellStorage &cells,
|
||||||
|
const std::vector<bool> &allowed_nodes,
|
||||||
|
CellMetric &metric,
|
||||||
|
LevelID level,
|
||||||
|
CellID id) const
|
||||||
{
|
{
|
||||||
auto cell = cells.GetCell(level, id);
|
auto cell = cells.GetCell(metric, level, id);
|
||||||
auto destinations = cell.GetDestinationNodes();
|
auto destinations = cell.GetDestinationNodes();
|
||||||
|
|
||||||
// for each source do forward search
|
// for each source do forward search
|
||||||
for (auto source : cell.GetSourceNodes())
|
for (auto source : cell.GetSourceNodes())
|
||||||
{
|
{
|
||||||
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
|
if (!allowed_nodes[source])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<NodeID> destinations_set;
|
||||||
|
for (const auto destination : destinations)
|
||||||
|
{
|
||||||
|
if (allowed_nodes[destination])
|
||||||
|
{
|
||||||
|
destinations_set.insert(destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
heap.Clear();
|
heap.Clear();
|
||||||
heap.Insert(source, 0, {false, 0});
|
heap.Insert(source, 0, {false, 0});
|
||||||
|
|
||||||
@@ -51,10 +68,7 @@ class CellCustomizer
|
|||||||
const EdgeWeight weight = heap.GetKey(node);
|
const EdgeWeight weight = heap.GetKey(node);
|
||||||
const EdgeDuration duration = heap.GetData(node).duration;
|
const EdgeDuration duration = heap.GetData(node).duration;
|
||||||
|
|
||||||
if (level == 1)
|
RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration);
|
||||||
RelaxNode<true>(graph, cells, heap, level, node, weight, duration);
|
|
||||||
else
|
|
||||||
RelaxNode<false>(graph, cells, heap, level, node, weight, duration);
|
|
||||||
|
|
||||||
destinations_set.erase(node);
|
destinations_set.erase(node);
|
||||||
}
|
}
|
||||||
@@ -80,7 +94,11 @@ class CellCustomizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
|
template <typename GraphT>
|
||||||
|
void Customize(const GraphT &graph,
|
||||||
|
const partition::CellStorage &cells,
|
||||||
|
const std::vector<bool> &allowed_nodes,
|
||||||
|
CellMetric &metric) const
|
||||||
{
|
{
|
||||||
Heap heap_exemplar(graph.GetNumberOfNodes());
|
Heap heap_exemplar(graph.GetNumberOfNodes());
|
||||||
HeapPtr heaps(heap_exemplar);
|
HeapPtr heaps(heap_exemplar);
|
||||||
@@ -92,22 +110,26 @@ class CellCustomizer
|
|||||||
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)
|
||||||
{
|
{
|
||||||
Customize(graph, heap, cells, level, id);
|
Customize(
|
||||||
|
graph, heap, cells, allowed_nodes, metric, level, id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <bool first_level, typename GraphT>
|
template <typename GraphT>
|
||||||
void RelaxNode(const GraphT &graph,
|
void RelaxNode(const GraphT &graph,
|
||||||
const partition::CellStorage &cells,
|
const partition::CellStorage &cells,
|
||||||
|
const std::vector<bool> &allowed_nodes,
|
||||||
|
const CellMetric &metric,
|
||||||
Heap &heap,
|
Heap &heap,
|
||||||
LevelID level,
|
LevelID level,
|
||||||
NodeID node,
|
NodeID node,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration) const
|
EdgeDuration duration) const
|
||||||
{
|
{
|
||||||
|
auto first_level = level == 1;
|
||||||
BOOST_ASSERT(heap.WasInserted(node));
|
BOOST_ASSERT(heap.WasInserted(node));
|
||||||
|
|
||||||
if (!first_level)
|
if (!first_level)
|
||||||
@@ -123,7 +145,7 @@ class CellCustomizer
|
|||||||
{
|
{
|
||||||
// Relax sub-cell nodes
|
// Relax sub-cell nodes
|
||||||
auto subcell_id = partition.GetCell(level - 1, node);
|
auto subcell_id = partition.GetCell(level - 1, node);
|
||||||
auto subcell = cells.GetCell(level - 1, subcell_id);
|
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
|
||||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||||
auto subcell_duration = subcell.GetOutDuration(node).begin();
|
auto subcell_duration = subcell.GetOutDuration(node).begin();
|
||||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||||
@@ -131,15 +153,22 @@ class CellCustomizer
|
|||||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
const NodeID to = *subcell_destination;
|
const NodeID to = *subcell_destination;
|
||||||
|
if (!allowed_nodes[to])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const EdgeWeight to_weight = weight + subcell_weight;
|
const EdgeWeight to_weight = weight + subcell_weight;
|
||||||
|
const EdgeDuration to_duration = duration + *subcell_duration;
|
||||||
if (!heap.WasInserted(to))
|
if (!heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, {true, duration + *subcell_duration});
|
heap.Insert(to, to_weight, {true, to_duration});
|
||||||
}
|
}
|
||||||
else if (to_weight < heap.GetKey(to))
|
else if (std::tie(to_weight, to_duration) <
|
||||||
|
std::tie(heap.GetKey(to), heap.GetData(to).duration))
|
||||||
{
|
{
|
||||||
heap.DecreaseKey(to, to_weight);
|
heap.DecreaseKey(to, to_weight);
|
||||||
heap.GetData(to) = {true, duration + *subcell_duration};
|
heap.GetData(to) = {true, to_duration};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,20 +182,27 @@ class CellCustomizer
|
|||||||
for (auto edge : graph.GetInternalEdgeRange(level, node))
|
for (auto edge : graph.GetInternalEdgeRange(level, node))
|
||||||
{
|
{
|
||||||
const NodeID to = graph.GetTarget(edge);
|
const NodeID to = graph.GetTarget(edge);
|
||||||
|
if (!allowed_nodes[to])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &data = graph.GetEdgeData(edge);
|
const auto &data = graph.GetEdgeData(edge);
|
||||||
if (data.forward &&
|
if (data.forward &&
|
||||||
(first_level ||
|
(first_level ||
|
||||||
partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
|
partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
|
||||||
{
|
{
|
||||||
const EdgeWeight to_weight = weight + data.weight;
|
const EdgeWeight to_weight = weight + data.weight;
|
||||||
|
const EdgeDuration to_duration = duration + data.duration;
|
||||||
if (!heap.WasInserted(to))
|
if (!heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, {false, duration + data.duration});
|
heap.Insert(to, to_weight, {false, duration + data.duration});
|
||||||
}
|
}
|
||||||
else if (to_weight < heap.GetKey(to))
|
else if (std::tie(to_weight, to_duration) <
|
||||||
|
std::tie(heap.GetKey(to), heap.GetData(to).duration))
|
||||||
{
|
{
|
||||||
heap.DecreaseKey(to, to_weight);
|
heap.DecreaseKey(to, to_weight);
|
||||||
heap.GetData(to) = {false, duration + data.duration};
|
heap.GetData(to) = {false, to_duration};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef OSRM_CUSTOMIZER_CELL_METRIC_HPP
|
||||||
|
#define OSRM_CUSTOMIZER_CELL_METRIC_HPP
|
||||||
|
|
||||||
|
#include "storage/io_fwd.hpp"
|
||||||
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
|
||||||
|
#include "util/typedefs.hpp"
|
||||||
|
#include "util/vector_view.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace customizer
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// Encapsulated one metric to make it easily replacable in CelLStorage
|
||||||
|
template <storage::Ownership Ownership> struct CellMetricImpl
|
||||||
|
{
|
||||||
|
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||||
|
|
||||||
|
Vector<EdgeWeight> weights;
|
||||||
|
Vector<EdgeDuration> durations;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
using CellMetric = detail::CellMetricImpl<storage::Ownership::Container>;
|
||||||
|
using CellMetricView = detail::CellMetricImpl<storage::Ownership::View>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,12 +17,13 @@ namespace customizer
|
|||||||
struct CustomizationConfig final : storage::IOConfig
|
struct CustomizationConfig final : storage::IOConfig
|
||||||
{
|
{
|
||||||
CustomizationConfig()
|
CustomizationConfig()
|
||||||
: IOConfig(
|
: IOConfig({".osrm.ebg",
|
||||||
{
|
".osrm.partition",
|
||||||
".osrm",
|
".osrm.cells",
|
||||||
},
|
".osrm.ebg_nodes",
|
||||||
{},
|
".osrm.properties"},
|
||||||
{".osrm.ebg", ".osrm.partition", ".osrm.cells", ".osrm.mldgr"}),
|
{},
|
||||||
|
{".osrm.cell_metrics", ".osrm.mldgr"}),
|
||||||
requested_num_threads(0)
|
requested_num_threads(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#ifndef OSRM_CUSTOMIZER_FILES_HPP
|
||||||
|
#define OSRM_CUSTOMIZER_FILES_HPP
|
||||||
|
|
||||||
|
#include "customizer/serialization.hpp"
|
||||||
|
|
||||||
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
|
#include "util/integer_range.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace customizer
|
||||||
|
{
|
||||||
|
namespace files
|
||||||
|
{
|
||||||
|
|
||||||
|
// reads .osrm.cell_metrics file
|
||||||
|
template <typename CellMetricT>
|
||||||
|
inline void readCellMetrics(const boost::filesystem::path &path, std::vector<CellMetricT> &metrics)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
|
||||||
|
std::is_same<CellMetric, CellMetricT>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||||
|
storage::io::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
auto num_metrics = reader.ReadElementCount64();
|
||||||
|
metrics.resize(num_metrics);
|
||||||
|
|
||||||
|
for (auto &metric : metrics)
|
||||||
|
{
|
||||||
|
serialization::read(reader, metric);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.cell_metrics file
|
||||||
|
template <typename CellMetricT>
|
||||||
|
inline void writeCellMetrics(const boost::filesystem::path &path,
|
||||||
|
const std::vector<CellMetricT> &metrics)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
|
||||||
|
std::is_same<CellMetric, CellMetricT>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||||
|
storage::io::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
writer.WriteElementCount64(metrics.size());
|
||||||
|
for (const auto &metric : metrics)
|
||||||
|
{
|
||||||
|
serialization::write(writer, metric);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef OSRM_CUSTOMIZER_SERIALIZATION_HPP
|
||||||
|
#define OSRM_CUSTOMIZER_SERIALIZATION_HPP
|
||||||
|
|
||||||
|
#include "partition/cell_storage.hpp"
|
||||||
|
|
||||||
|
#include "storage/io.hpp"
|
||||||
|
#include "storage/serialization.hpp"
|
||||||
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace customizer
|
||||||
|
{
|
||||||
|
namespace serialization
|
||||||
|
{
|
||||||
|
|
||||||
|
template <storage::Ownership Ownership>
|
||||||
|
inline void read(storage::io::FileReader &reader, detail::CellMetricImpl<Ownership> &metric)
|
||||||
|
{
|
||||||
|
storage::serialization::read(reader, metric.weights);
|
||||||
|
storage::serialization::read(reader, metric.durations);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <storage::Ownership Ownership>
|
||||||
|
inline void write(storage::io::FileWriter &writer, const detail::CellMetricImpl<Ownership> &metric)
|
||||||
|
{
|
||||||
|
storage::serialization::write(writer, metric.weights);
|
||||||
|
storage::serialization::write(writer, metric.durations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -56,6 +56,9 @@ template <typename AlgorithmT> struct HasManyToManySearch final : std::false_typ
|
|||||||
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
|
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <typename AlgorithmT> struct HasExcludeFlags final : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
// Algorithms supported by Contraction Hierarchies
|
// Algorithms supported by Contraction Hierarchies
|
||||||
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
|
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
|
||||||
@@ -76,6 +79,9 @@ template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
|
|||||||
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
|
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <> struct HasExcludeFlags<ch::Algorithm> final : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
// Algorithms supported by Contraction Hierarchies with core
|
// Algorithms supported by Contraction Hierarchies with core
|
||||||
// the rest is disabled because of performance reasons
|
// the rest is disabled because of performance reasons
|
||||||
@@ -91,6 +97,9 @@ template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
|
|||||||
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
|
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <> struct HasExcludeFlags<corech::Algorithm> final : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
// Algorithms supported by Multi-Level Dijkstra
|
// Algorithms supported by Multi-Level Dijkstra
|
||||||
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
|
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
|
||||||
@@ -111,6 +120,9 @@ template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
|
|||||||
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
|
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <> struct HasExcludeFlags<mld::Algorithm> final : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ struct BaseParameters
|
|||||||
std::vector<boost::optional<double>> radiuses;
|
std::vector<boost::optional<double>> radiuses;
|
||||||
std::vector<boost::optional<Bearing>> bearings;
|
std::vector<boost::optional<Bearing>> bearings;
|
||||||
std::vector<boost::optional<Approach>> approaches;
|
std::vector<boost::optional<Approach>> approaches;
|
||||||
|
std::vector<std::string> exclude;
|
||||||
|
|
||||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||||
bool generate_hints = true;
|
bool generate_hints = true;
|
||||||
@@ -77,9 +78,10 @@ struct BaseParameters
|
|||||||
std::vector<boost::optional<double>> radiuses_ = {},
|
std::vector<boost::optional<double>> radiuses_ = {},
|
||||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||||
bool generate_hints_ = true)
|
bool generate_hints_ = true,
|
||||||
|
std::vector<std::string> exclude = {})
|
||||||
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
||||||
approaches(approaches_), generate_hints(generate_hints_)
|
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,15 @@ namespace detail
|
|||||||
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
|
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
|
||||||
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
|
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representing all instruction types (including internal types that
|
||||||
|
* are normally not exposed in route responses)
|
||||||
|
*
|
||||||
|
* @param type the TurnType value to convert into a string
|
||||||
|
* @return a string representing the turn type (e.g. `turn` or `continue`)
|
||||||
|
*/
|
||||||
|
std::string internalInstructionTypeToString(extractor::guidance::TurnType::Enum type);
|
||||||
|
|
||||||
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
|
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
|
||||||
|
|
||||||
std::string modeToString(const extractor::TravelMode mode);
|
std::string modeToString(const extractor::TravelMode mode);
|
||||||
|
|||||||
@@ -167,12 +167,12 @@ class RouteAPI : public BaseAPI
|
|||||||
* the overall response consistent.
|
* the overall response consistent.
|
||||||
*
|
*
|
||||||
* ⚠ CAUTION: order of post-processing steps is important
|
* ⚠ CAUTION: order of post-processing steps is important
|
||||||
* - postProcess must be called before collapseTurnInstructions that expects
|
* - handleRoundabouts must be called before collapseTurnInstructions that
|
||||||
* post-processed roundabouts without Exit instructions
|
* expects post-processed roundabouts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
guidance::trimShortSegments(steps, leg_geometry);
|
guidance::trimShortSegments(steps, leg_geometry);
|
||||||
leg.steps = guidance::postProcess(std::move(steps));
|
leg.steps = guidance::handleRoundabouts(std::move(steps));
|
||||||
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
|
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
|
||||||
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
|
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
|
||||||
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
||||||
|
|||||||
@@ -88,11 +88,17 @@ struct RouteParameters : public BaseParameters
|
|||||||
const OverviewType overview_,
|
const OverviewType overview_,
|
||||||
const boost::optional<bool> continue_straight_,
|
const boost::optional<bool> continue_straight_,
|
||||||
Args... args_)
|
Args... args_)
|
||||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one
|
||||||
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{false},
|
// below.
|
||||||
annotations_type{AnnotationsType::None}, geometries{geometries_}, overview{overview_},
|
: BaseParameters{std::forward<Args>(args_)...},
|
||||||
|
steps{steps_},
|
||||||
|
alternatives{alternatives_},
|
||||||
|
number_of_alternatives{alternatives_ ? 1u : 0u},
|
||||||
|
annotations{false},
|
||||||
|
annotations_type{AnnotationsType::None},
|
||||||
|
geometries{geometries_},
|
||||||
|
overview{overview_},
|
||||||
continue_straight{continue_straight_}
|
continue_straight{continue_straight_}
|
||||||
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one below.
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
#include "engine/datafacade/shared_memory_allocator.hpp"
|
#include "engine/datafacade/shared_memory_allocator.hpp"
|
||||||
|
#include "engine/datafacade_factory.hpp"
|
||||||
|
|
||||||
#include "storage/shared_datatype.hpp"
|
#include "storage/shared_datatype.hpp"
|
||||||
#include "storage/shared_memory.hpp"
|
#include "storage/shared_memory.hpp"
|
||||||
@@ -21,37 +22,50 @@ namespace osrm
|
|||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
|
|
||||||
// This class monitors the shared memory region that contains the pointers to
|
namespace detail
|
||||||
// the data and layout regions that should be used. This region is updated
|
{
|
||||||
// once a new dataset arrives.
|
// We need this wrapper type since template-template specilization of FacadeT is broken on clang
|
||||||
template <typename AlgorithmT> class DataWatchdog final
|
// when it is combined with an templated alias (DataFacade in this case).
|
||||||
|
// See https://godbolt.org/g/ZS6Xmt for an example.
|
||||||
|
template <typename AlgorithmT, typename FacadeT> class DataWatchdogImpl;
|
||||||
|
|
||||||
|
template <typename AlgorithmT>
|
||||||
|
class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>> final
|
||||||
{
|
{
|
||||||
using mutex_type = typename storage::SharedMonitor<storage::SharedDataTimestamp>::mutex_type;
|
using mutex_type = typename storage::SharedMonitor<storage::SharedDataTimestamp>::mutex_type;
|
||||||
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
|
using Facade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataWatchdog() : active(true), timestamp(0)
|
DataWatchdogImpl() : active(true), timestamp(0)
|
||||||
{
|
{
|
||||||
// create the initial facade before launching the watchdog thread
|
// create the initial facade before launching the watchdog thread
|
||||||
{
|
{
|
||||||
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
||||||
|
|
||||||
facade = std::make_shared<const FacadeT>(
|
facade_factory =
|
||||||
std::make_unique<datafacade::SharedMemoryAllocator>(barrier.data().region));
|
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
|
||||||
|
std::make_shared<datafacade::SharedMemoryAllocator>(barrier.data().region));
|
||||||
timestamp = barrier.data().timestamp;
|
timestamp = barrier.data().timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
watcher = std::thread(&DataWatchdog::Run, this);
|
watcher = std::thread(&DataWatchdogImpl::Run, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DataWatchdog()
|
~DataWatchdogImpl()
|
||||||
{
|
{
|
||||||
active = false;
|
active = false;
|
||||||
barrier.notify_all();
|
barrier.notify_all();
|
||||||
watcher.join();
|
watcher.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const FacadeT> Get() const { return facade; }
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms) const
|
||||||
|
{
|
||||||
|
return facade_factory.Get(params);
|
||||||
|
}
|
||||||
|
std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const
|
||||||
|
{
|
||||||
|
return facade_factory.Get(params);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Run()
|
void Run()
|
||||||
@@ -68,8 +82,9 @@ template <typename AlgorithmT> class DataWatchdog final
|
|||||||
if (timestamp != barrier.data().timestamp)
|
if (timestamp != barrier.data().timestamp)
|
||||||
{
|
{
|
||||||
auto region = barrier.data().region;
|
auto region = barrier.data().region;
|
||||||
facade = std::make_shared<const FacadeT>(
|
facade_factory =
|
||||||
std::make_unique<datafacade::SharedMemoryAllocator>(region));
|
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
|
||||||
|
std::make_shared<datafacade::SharedMemoryAllocator>(region));
|
||||||
timestamp = barrier.data().timestamp;
|
timestamp = barrier.data().timestamp;
|
||||||
util::Log() << "updated facade to region " << region << " with timestamp "
|
util::Log() << "updated facade to region " << region << " with timestamp "
|
||||||
<< timestamp;
|
<< timestamp;
|
||||||
@@ -83,9 +98,16 @@ template <typename AlgorithmT> class DataWatchdog final
|
|||||||
std::thread watcher;
|
std::thread watcher;
|
||||||
bool active;
|
bool active;
|
||||||
unsigned timestamp;
|
unsigned timestamp;
|
||||||
std::shared_ptr<const FacadeT> facade;
|
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT> facade_factory;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This class monitors the shared memory region that contains the pointers to
|
||||||
|
// the data and layout regions that should be used. This region is updated
|
||||||
|
// once a new dataset arrives.
|
||||||
|
template <typename AlgorithmT, template <typename A> class FacadeT>
|
||||||
|
using DataWatchdog = detail::DataWatchdogImpl<AlgorithmT, FacadeT<AlgorithmT>>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "partition/cell_storage.hpp"
|
#include "partition/cell_storage.hpp"
|
||||||
#include "partition/multi_level_partition.hpp"
|
#include "partition/multi_level_partition.hpp"
|
||||||
|
|
||||||
|
#include "util/filtered_graph.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -22,14 +23,13 @@ using CH = routing_algorithms::ch::Algorithm;
|
|||||||
using CoreCH = routing_algorithms::corech::Algorithm;
|
using CoreCH = routing_algorithms::corech::Algorithm;
|
||||||
using MLD = routing_algorithms::mld::Algorithm;
|
using MLD = routing_algorithms::mld::Algorithm;
|
||||||
|
|
||||||
using EdgeRange = util::range<EdgeID>;
|
|
||||||
|
|
||||||
template <typename AlgorithmT> class AlgorithmDataFacade;
|
template <typename AlgorithmT> class AlgorithmDataFacade;
|
||||||
|
|
||||||
template <> class AlgorithmDataFacade<CH>
|
template <> class AlgorithmDataFacade<CH>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using EdgeData = contractor::QueryEdge::EdgeData;
|
using EdgeData = contractor::QueryEdge::EdgeData;
|
||||||
|
using EdgeRange = util::filtered_range<EdgeID, util::vector_view<bool>>;
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
virtual unsigned GetNumberOfNodes() const = 0;
|
virtual unsigned GetNumberOfNodes() const = 0;
|
||||||
@@ -42,10 +42,6 @@ template <> class AlgorithmDataFacade<CH>
|
|||||||
|
|
||||||
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
|
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
|
||||||
|
|
||||||
virtual EdgeID BeginEdges(const NodeID n) const = 0;
|
|
||||||
|
|
||||||
virtual EdgeID EndEdges(const NodeID n) const = 0;
|
|
||||||
|
|
||||||
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
|
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
|
||||||
|
|
||||||
// searches for a specific edge
|
// searches for a specific edge
|
||||||
@@ -73,6 +69,7 @@ template <> class AlgorithmDataFacade<MLD>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
|
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
|
||||||
|
using EdgeRange = util::range<EdgeID>;
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
virtual unsigned GetNumberOfNodes() const = 0;
|
virtual unsigned GetNumberOfNodes() const = 0;
|
||||||
@@ -85,16 +82,14 @@ template <> class AlgorithmDataFacade<MLD>
|
|||||||
|
|
||||||
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
|
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
|
||||||
|
|
||||||
virtual EdgeID BeginEdges(const NodeID n) const = 0;
|
|
||||||
|
|
||||||
virtual EdgeID EndEdges(const NodeID n) const = 0;
|
|
||||||
|
|
||||||
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
|
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
|
||||||
|
|
||||||
virtual const partition::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
|
virtual const partition::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
|
||||||
|
|
||||||
virtual const partition::CellStorageView &GetCellStorage() const = 0;
|
virtual const partition::CellStorageView &GetCellStorage() const = 0;
|
||||||
|
|
||||||
|
virtual const customizer::CellMetricView &GetCellMetric() const = 0;
|
||||||
|
|
||||||
virtual EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const = 0;
|
virtual EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const = 0;
|
||||||
|
|
||||||
// searches for a specific edge
|
// searches for a specific edge
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/exception_utils.hpp"
|
#include "util/exception_utils.hpp"
|
||||||
|
#include "util/filtered_graph.hpp"
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
#include "util/guidance/turn_bearing.hpp"
|
||||||
@@ -68,7 +69,7 @@ template <>
|
|||||||
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
|
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using QueryGraph = contractor::QueryGraphView;
|
using QueryGraph = util::FilteredGraphView<contractor::QueryGraphView>;
|
||||||
using GraphNode = QueryGraph::NodeArrayEntry;
|
using GraphNode = QueryGraph::NodeArrayEntry;
|
||||||
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
||||||
|
|
||||||
@@ -77,7 +78,9 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
|
|||||||
// allocator that keeps the allocation data
|
// allocator that keeps the allocation data
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||||
|
|
||||||
void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeGraphPointer(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
|
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
|
||||||
memory_block, storage::DataLayout::CH_GRAPH_NODE_LIST);
|
memory_block, storage::DataLayout::CH_GRAPH_NODE_LIST);
|
||||||
@@ -85,24 +88,34 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
|
|||||||
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
|
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
|
||||||
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
|
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
|
||||||
|
|
||||||
|
auto filter_block_id = static_cast<storage::DataLayout::BlockID>(
|
||||||
|
storage::DataLayout::CH_EDGE_FILTER_0 + exclude_index);
|
||||||
|
|
||||||
|
auto edge_filter_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, filter_block_id);
|
||||||
|
|
||||||
util::vector_view<GraphNode> node_list(
|
util::vector_view<GraphNode> node_list(
|
||||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
|
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
|
||||||
util::vector_view<GraphEdge> edge_list(
|
util::vector_view<GraphEdge> edge_list(
|
||||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
|
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
|
||||||
m_query_graph = QueryGraph(node_list, edge_list);
|
|
||||||
|
util::vector_view<bool> edge_filter(edge_filter_ptr,
|
||||||
|
data_layout.num_entries[filter_block_id]);
|
||||||
|
m_query_graph = QueryGraph({node_list, edge_list}, edge_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
ContiguousInternalMemoryAlgorithmDataFacade(
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator_)
|
std::shared_ptr<ContiguousBlockAllocator> allocator_, std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
|
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeGraphPointer(data_layout, memory_block);
|
InitializeGraphPointer(data_layout, memory_block, exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
@@ -122,10 +135,6 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
|
|||||||
return m_query_graph.GetEdgeData(e);
|
return m_query_graph.GetEdgeData(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph.BeginEdges(n); }
|
|
||||||
|
|
||||||
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph.EndEdges(n); }
|
|
||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
||||||
{
|
{
|
||||||
return m_query_graph.GetAdjacentEdgeRange(node);
|
return m_query_graph.GetAdjacentEdgeRange(node);
|
||||||
@@ -166,32 +175,37 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
|||||||
// allocator that keeps the allocation data
|
// allocator that keeps the allocation data
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||||
|
|
||||||
void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeCoreInformationPointer(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
auto core_marker_ptr =
|
auto core_block_id = static_cast<storage::DataLayout::BlockID>(
|
||||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
|
storage::DataLayout::CH_CORE_MARKER_0 + exclude_index);
|
||||||
util::vector_view<bool> is_core_node(
|
auto core_marker_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, core_block_id);
|
||||||
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
|
util::vector_view<bool> is_core_node(core_marker_ptr,
|
||||||
|
data_layout.num_entries[core_block_id]);
|
||||||
m_is_core_node = std::move(is_core_node);
|
m_is_core_node = std::move(is_core_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
ContiguousInternalMemoryAlgorithmDataFacade(
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator_)
|
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
|
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeCoreInformationPointer(data_layout, memory_block);
|
InitializeCoreInformationPointer(data_layout, memory_block, exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCoreNode(const NodeID id) const override final
|
bool IsCoreNode(const NodeID id) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(id < m_is_core_node.size());
|
BOOST_ASSERT(m_is_core_node.empty() || id < m_is_core_node.size());
|
||||||
return m_is_core_node[id];
|
return !m_is_core_node.empty() || m_is_core_node[id];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -212,6 +226,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
|
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
|
||||||
using RTreeNode = SharedRTree::TreeNode;
|
using RTreeNode = SharedRTree::TreeNode;
|
||||||
|
|
||||||
|
extractor::ClassData exclude_mask;
|
||||||
std::string m_timestamp;
|
std::string m_timestamp;
|
||||||
extractor::ProfileProperties *m_profile_properties;
|
extractor::ProfileProperties *m_profile_properties;
|
||||||
extractor::Datasources *m_datasources;
|
extractor::Datasources *m_datasources;
|
||||||
@@ -246,10 +261,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
// allocator that keeps the allocation data
|
// allocator that keeps the allocation data
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||||
|
|
||||||
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
m_profile_properties = data_layout.GetBlockPtr<extractor::ProfileProperties>(
|
m_profile_properties = data_layout.GetBlockPtr<extractor::ProfileProperties>(
|
||||||
memory_block, storage::DataLayout::PROPERTIES);
|
memory_block, storage::DataLayout::PROPERTIES);
|
||||||
|
|
||||||
|
exclude_mask = m_profile_properties->excludable_classes[exclude_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block)
|
||||||
@@ -539,7 +558,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
m_entry_class_table = std::move(entry_class_table);
|
m_entry_class_table = std::move(entry_class_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeChecksumPointer(data_layout, memory_block);
|
InitializeChecksumPointer(data_layout, memory_block);
|
||||||
InitializeNodeInformationPointers(data_layout, memory_block);
|
InitializeNodeInformationPointers(data_layout, memory_block);
|
||||||
@@ -550,7 +571,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
InitializeTimestampPointer(data_layout, memory_block);
|
InitializeTimestampPointer(data_layout, memory_block);
|
||||||
InitializeNamePointers(data_layout, memory_block);
|
InitializeNamePointers(data_layout, memory_block);
|
||||||
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
|
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
|
||||||
InitializeProfilePropertiesPointer(data_layout, memory_block);
|
InitializeProfilePropertiesPointer(data_layout, memory_block, exclude_index);
|
||||||
InitializeRTreePointers(data_layout, memory_block);
|
InitializeRTreePointers(data_layout, memory_block);
|
||||||
InitializeIntersectionClassPointers(data_layout, memory_block);
|
InitializeIntersectionClassPointers(data_layout, memory_block);
|
||||||
}
|
}
|
||||||
@@ -558,10 +579,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
public:
|
public:
|
||||||
// allows switching between process_memory/shared_memory datafacade, based on the type of
|
// allows switching between process_memory/shared_memory datafacade, based on the type of
|
||||||
// allocator
|
// allocator
|
||||||
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_)
|
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_,
|
||||||
|
const std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
|
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// node and edge information access
|
// node and edge information access
|
||||||
@@ -802,6 +824,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
return edge_based_node_data.GetClassData(id);
|
return edge_based_node_data.GetClassData(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExcludeNode(const NodeID id) const override final
|
||||||
|
{
|
||||||
|
return (edge_based_node_data.GetClassData(id) & exclude_mask) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final
|
std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final
|
||||||
{
|
{
|
||||||
auto indexes = extractor::getClassIndexes(class_data);
|
auto indexes = extractor::getClassIndexes(class_data);
|
||||||
@@ -926,9 +953,10 @@ class ContiguousInternalMemoryDataFacade<CH>
|
|||||||
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
|
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
||||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
const std::size_t exclude_index)
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator)
|
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
|
||||||
|
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, exclude_index)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -940,9 +968,10 @@ class ContiguousInternalMemoryDataFacade<CoreCH> final
|
|||||||
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
||||||
: ContiguousInternalMemoryDataFacade<CH>(allocator),
|
const std::size_t exclude_index)
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator)
|
: ContiguousInternalMemoryDataFacade<CH>(allocator, exclude_index),
|
||||||
|
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator, exclude_index)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -953,19 +982,24 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
// MLD data
|
// MLD data
|
||||||
partition::MultiLevelPartitionView mld_partition;
|
partition::MultiLevelPartitionView mld_partition;
|
||||||
partition::CellStorageView mld_cell_storage;
|
partition::CellStorageView mld_cell_storage;
|
||||||
|
customizer::CellMetricView mld_cell_metric;
|
||||||
using QueryGraph = customizer::MultiLevelEdgeBasedGraphView;
|
using QueryGraph = customizer::MultiLevelEdgeBasedGraphView;
|
||||||
using GraphNode = QueryGraph::NodeArrayEntry;
|
using GraphNode = QueryGraph::NodeArrayEntry;
|
||||||
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
||||||
|
|
||||||
QueryGraph query_graph;
|
QueryGraph query_graph;
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeMLDDataPointers(data_layout, memory_block);
|
InitializeMLDDataPointers(data_layout, memory_block, exclude_index);
|
||||||
InitializeGraphPointer(data_layout, memory_block);
|
InitializeGraphPointer(data_layout, memory_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeMLDDataPointers(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeMLDDataPointers(storage::DataLayout &data_layout,
|
||||||
|
char *memory_block,
|
||||||
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0)
|
if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0)
|
||||||
{
|
{
|
||||||
@@ -992,15 +1026,32 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
partition::MultiLevelPartitionView{level_data, partition, cell_to_children};
|
partition::MultiLevelPartitionView{level_data, partition, cell_to_children};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_WEIGHTS) > 0)
|
const auto weights_block_id = static_cast<storage::DataLayout::BlockID>(
|
||||||
{
|
storage::DataLayout::MLD_CELL_WEIGHTS_0 + exclude_index);
|
||||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0);
|
const auto durations_block_id = static_cast<storage::DataLayout::BlockID>(
|
||||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS) > 0);
|
storage::DataLayout::MLD_CELL_DURATIONS_0 + exclude_index);
|
||||||
|
|
||||||
|
if (data_layout.GetBlockSize(weights_block_id) > 0)
|
||||||
|
{
|
||||||
|
auto mld_cell_weights_ptr =
|
||||||
|
data_layout.GetBlockPtr<EdgeWeight>(memory_block, weights_block_id);
|
||||||
|
auto mld_cell_durations_ptr =
|
||||||
|
data_layout.GetBlockPtr<EdgeDuration>(memory_block, durations_block_id);
|
||||||
|
auto weight_entries_count =
|
||||||
|
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS_0);
|
||||||
|
auto duration_entries_count =
|
||||||
|
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS_0);
|
||||||
|
BOOST_ASSERT(weight_entries_count == duration_entries_count);
|
||||||
|
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
|
||||||
|
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
|
||||||
|
duration_entries_count);
|
||||||
|
|
||||||
|
mld_cell_metric = customizer::CellMetricView{std::move(weights), std::move(durations)};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0)
|
||||||
|
{
|
||||||
|
|
||||||
auto mld_cell_weights_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELL_WEIGHTS);
|
|
||||||
auto mld_cell_durations_ptr = data_layout.GetBlockPtr<EdgeDuration>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELL_DURATIONS);
|
|
||||||
auto mld_source_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
|
auto mld_source_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
|
||||||
memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
|
memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
|
||||||
auto mld_destination_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
|
auto mld_destination_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
|
||||||
@@ -1010,10 +1061,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr<std::uint64_t>(
|
auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr<std::uint64_t>(
|
||||||
memory_block, storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
memory_block, storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
||||||
|
|
||||||
auto weight_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS);
|
|
||||||
auto duration_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS);
|
|
||||||
auto source_boundary_entries_count =
|
auto source_boundary_entries_count =
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
|
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
|
||||||
auto destination_boundary_entries_count =
|
auto destination_boundary_entries_count =
|
||||||
@@ -1022,11 +1069,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
auto cell_level_offsets_entries_count =
|
auto cell_level_offsets_entries_count =
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
||||||
|
|
||||||
BOOST_ASSERT(weight_entries_count == duration_entries_count);
|
|
||||||
|
|
||||||
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
|
|
||||||
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
|
|
||||||
duration_entries_count);
|
|
||||||
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
|
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
|
||||||
source_boundary_entries_count);
|
source_boundary_entries_count);
|
||||||
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
|
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
|
||||||
@@ -1036,9 +1078,7 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
|
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
|
||||||
cell_level_offsets_entries_count);
|
cell_level_offsets_entries_count);
|
||||||
|
|
||||||
mld_cell_storage = partition::CellStorageView{std::move(weights),
|
mld_cell_storage = partition::CellStorageView{std::move(source_boundary),
|
||||||
std::move(durations),
|
|
||||||
std::move(source_boundary),
|
|
||||||
std::move(destination_boundary),
|
std::move(destination_boundary),
|
||||||
std::move(cells),
|
std::move(cells),
|
||||||
std::move(level_offsets)};
|
std::move(level_offsets)};
|
||||||
@@ -1072,10 +1112,10 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
ContiguousInternalMemoryAlgorithmDataFacade(
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator_)
|
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
|
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const partition::MultiLevelPartitionView &GetMultiLevelPartition() const override
|
const partition::MultiLevelPartitionView &GetMultiLevelPartition() const override
|
||||||
@@ -1085,6 +1125,8 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
|
|
||||||
const partition::CellStorageView &GetCellStorage() const override { return mld_cell_storage; }
|
const partition::CellStorageView &GetCellStorage() const override { return mld_cell_storage; }
|
||||||
|
|
||||||
|
const customizer::CellMetricView &GetCellMetric() const override { return mld_cell_metric; }
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); }
|
unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); }
|
||||||
|
|
||||||
@@ -1102,10 +1144,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
return query_graph.GetEdgeData(e);
|
return query_graph.GetEdgeData(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeID BeginEdges(const NodeID n) const override final { return query_graph.BeginEdges(n); }
|
|
||||||
|
|
||||||
EdgeID EndEdges(const NodeID n) const override final { return query_graph.EndEdges(n); }
|
|
||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
||||||
{
|
{
|
||||||
return query_graph.GetAdjacentEdgeRange(node);
|
return query_graph.GetAdjacentEdgeRange(node);
|
||||||
@@ -1130,9 +1168,10 @@ class ContiguousInternalMemoryDataFacade<MLD> final
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
||||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
const std::size_t exclude_index)
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator)
|
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
|
||||||
|
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, exclude_index)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual extractor::ClassData GetClassData(const NodeID id) const = 0;
|
virtual extractor::ClassData GetClassData(const NodeID id) const = 0;
|
||||||
|
|
||||||
|
virtual bool ExcludeNode(const NodeID id) const = 0;
|
||||||
|
|
||||||
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;
|
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;
|
||||||
|
|
||||||
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
#ifndef OSRM_ENGINE_DATAFACADE_FACTORY_HPP
|
||||||
|
#define OSRM_ENGINE_DATAFACADE_FACTORY_HPP
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
|
|
||||||
|
#include "engine/algorithm.hpp"
|
||||||
|
#include "engine/api/base_parameters.hpp"
|
||||||
|
#include "engine/api/tile_parameters.hpp"
|
||||||
|
|
||||||
|
#include "util/integer_range.hpp"
|
||||||
|
|
||||||
|
#include "storage/shared_datatype.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace engine
|
||||||
|
{
|
||||||
|
// This class selects the right facade for
|
||||||
|
template <template <typename A> class FacadeT, typename AlgorithmT> class DataFacadeFactory
|
||||||
|
{
|
||||||
|
static constexpr auto has_exclude_flags = routing_algorithms::HasExcludeFlags<AlgorithmT>{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Facade = FacadeT<AlgorithmT>;
|
||||||
|
DataFacadeFactory() = default;
|
||||||
|
|
||||||
|
template <typename AllocatorT>
|
||||||
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator)
|
||||||
|
: DataFacadeFactory(allocator, has_exclude_flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ParameterT> std::shared_ptr<const Facade> Get(const ParameterT ¶ms) const
|
||||||
|
{
|
||||||
|
return Get(params, has_exclude_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Algorithm with exclude flags
|
||||||
|
template <typename AllocatorT>
|
||||||
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::true_type)
|
||||||
|
{
|
||||||
|
for (const auto index : util::irange<std::size_t>(0, facades.size()))
|
||||||
|
{
|
||||||
|
facades[index] = std::make_shared<const Facade>(allocator, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
properties = allocator->GetLayout().template GetBlockPtr<extractor::ProfileProperties>(
|
||||||
|
allocator->GetMemory(), storage::DataLayout::PROPERTIES);
|
||||||
|
|
||||||
|
for (const auto index : util::irange<std::size_t>(0, properties->class_names.size()))
|
||||||
|
{
|
||||||
|
const std::string name = properties->GetClassName(index);
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
name_to_class[name] = extractor::getClassData(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Algorithm without exclude flags
|
||||||
|
template <typename AllocatorT>
|
||||||
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::false_type)
|
||||||
|
{
|
||||||
|
facades[0] = std::make_shared<const Facade>(allocator, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::false_type) const
|
||||||
|
{
|
||||||
|
return facades[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default for non-exclude flags: return only facade
|
||||||
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms, std::false_type) const
|
||||||
|
{
|
||||||
|
if (!params.exclude.empty())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return facades[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TileParameters don't drive from BaseParameters and generally don't have use for exclude flags
|
||||||
|
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::true_type) const
|
||||||
|
{
|
||||||
|
return facades[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selection logic for finding the corresponding datafacade for the given parameters
|
||||||
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms, std::true_type) const
|
||||||
|
{
|
||||||
|
if (params.exclude.empty())
|
||||||
|
return facades[0];
|
||||||
|
|
||||||
|
extractor::ClassData mask = 0;
|
||||||
|
for (const auto &name : params.exclude)
|
||||||
|
{
|
||||||
|
auto class_mask_iter = name_to_class.find(name);
|
||||||
|
if (class_mask_iter == name_to_class.end())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask |= class_mask_iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto exclude_iter = std::find(
|
||||||
|
properties->excludable_classes.begin(), properties->excludable_classes.end(), mask);
|
||||||
|
if (exclude_iter != properties->excludable_classes.end())
|
||||||
|
{
|
||||||
|
auto exclude_index =
|
||||||
|
std::distance(properties->excludable_classes.begin(), exclude_iter);
|
||||||
|
return facades[exclude_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<std::shared_ptr<const Facade>, extractor::MAX_EXCLUDABLE_CLASSES> facades;
|
||||||
|
std::unordered_map<std::string, extractor::ClassData> name_to_class;
|
||||||
|
const extractor::ProfileProperties *properties = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "engine/datafacade.hpp"
|
#include "engine/datafacade.hpp"
|
||||||
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
#include "engine/datafacade/process_memory_allocator.hpp"
|
#include "engine/datafacade/process_memory_allocator.hpp"
|
||||||
|
#include "engine/datafacade_factory.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,8 @@ template <typename AlgorithmT, template <typename A> class FacadeT> class DataFa
|
|||||||
|
|
||||||
virtual ~DataFacadeProvider() = default;
|
virtual ~DataFacadeProvider() = default;
|
||||||
|
|
||||||
virtual std::shared_ptr<const Facade> Get() const = 0;
|
virtual std::shared_ptr<const Facade> Get(const api::BaseParameters &) const = 0;
|
||||||
|
virtual std::shared_ptr<const Facade> Get(const api::TileParameters &) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename AlgorithmT, template <typename A> class FacadeT>
|
template <typename AlgorithmT, template <typename A> class FacadeT>
|
||||||
@@ -30,26 +32,39 @@ class ImmutableProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
|
|||||||
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
||||||
|
|
||||||
ImmutableProvider(const storage::StorageConfig &config)
|
ImmutableProvider(const storage::StorageConfig &config)
|
||||||
: immutable_data_facade(std::make_shared<Facade>(
|
: facade_factory(std::make_shared<datafacade::ProcessMemoryAllocator>(config))
|
||||||
std::make_shared<datafacade::ProcessMemoryAllocator>(config)))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const Facade> Get() const override final { return immutable_data_facade; }
|
std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const override final
|
||||||
|
{
|
||||||
|
return facade_factory.Get(params);
|
||||||
|
}
|
||||||
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms) const override final
|
||||||
|
{
|
||||||
|
return facade_factory.Get(params);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<const Facade> immutable_data_facade;
|
DataFacadeFactory<FacadeT, AlgorithmT> facade_factory;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename AlgorithmT, template <typename A> class FacadeT>
|
template <typename AlgorithmT, template <typename A> class FacadeT>
|
||||||
class WatchingProvider : public DataFacadeProvider<AlgorithmT, FacadeT>
|
class WatchingProvider : public DataFacadeProvider<AlgorithmT, FacadeT>
|
||||||
{
|
{
|
||||||
DataWatchdog<AlgorithmT> watchdog;
|
DataWatchdog<AlgorithmT, FacadeT> watchdog;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
||||||
|
|
||||||
std::shared_ptr<const Facade> Get() const override final { return watchdog.Get(); }
|
std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const override final
|
||||||
|
{
|
||||||
|
return watchdog.Get(params);
|
||||||
|
}
|
||||||
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms) const override final
|
||||||
|
{
|
||||||
|
return watchdog.Get(params);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-16
@@ -24,6 +24,8 @@
|
|||||||
#include "util/fingerprint.hpp"
|
#include "util/fingerprint.hpp"
|
||||||
#include "util/json_container.hpp"
|
#include "util/json_container.hpp"
|
||||||
|
|
||||||
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -53,7 +55,8 @@ template <typename Algorithm> class Engine final : public EngineInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Engine(const EngineConfig &config)
|
explicit Engine(const EngineConfig &config)
|
||||||
: route_plugin(config.max_locations_viaroute, config.max_alternatives), //
|
: task_scheduler(config.use_threads_number),
|
||||||
|
route_plugin(config.max_locations_viaroute, config.max_alternatives), //
|
||||||
table_plugin(config.max_locations_distance_table), //
|
table_plugin(config.max_locations_distance_table), //
|
||||||
nearest_plugin(config.max_results_nearest), //
|
nearest_plugin(config.max_results_nearest), //
|
||||||
trip_plugin(config.max_locations_trip), //
|
trip_plugin(config.max_locations_trip), //
|
||||||
@@ -85,48 +88,47 @@ template <typename Algorithm> class Engine final : public EngineInterface
|
|||||||
Status Route(const api::RouteParameters ¶ms,
|
Status Route(const api::RouteParameters ¶ms,
|
||||||
util::json::Object &result) const override final
|
util::json::Object &result) const override final
|
||||||
{
|
{
|
||||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get()};
|
return route_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
return route_plugin.HandleRequest(algorithms, params, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Table(const api::TableParameters ¶ms,
|
Status Table(const api::TableParameters ¶ms,
|
||||||
util::json::Object &result) const override final
|
util::json::Object &result) const override final
|
||||||
{
|
{
|
||||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get()};
|
return table_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
return table_plugin.HandleRequest(algorithms, params, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Nearest(const api::NearestParameters ¶ms,
|
Status Nearest(const api::NearestParameters ¶ms,
|
||||||
util::json::Object &result) const override final
|
util::json::Object &result) const override final
|
||||||
{
|
{
|
||||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get()};
|
return nearest_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
return nearest_plugin.HandleRequest(algorithms, params, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Trip(const api::TripParameters ¶ms, util::json::Object &result) const override final
|
Status Trip(const api::TripParameters ¶ms, util::json::Object &result) const override final
|
||||||
{
|
{
|
||||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get()};
|
return trip_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
return trip_plugin.HandleRequest(algorithms, params, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Match(const api::MatchParameters ¶ms,
|
Status Match(const api::MatchParameters ¶ms,
|
||||||
util::json::Object &result) const override final
|
util::json::Object &result) const override final
|
||||||
{
|
{
|
||||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get()};
|
return match_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
return match_plugin.HandleRequest(algorithms, params, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Tile(const api::TileParameters ¶ms, std::string &result) const override final
|
Status Tile(const api::TileParameters ¶ms, std::string &result) const override final
|
||||||
{
|
{
|
||||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get()};
|
return tile_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
return tile_plugin.HandleRequest(algorithms, params, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckCompability(const EngineConfig &config);
|
static bool CheckCompability(const EngineConfig &config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename ParametersT> auto GetAlgorithms(const ParametersT ¶ms) const
|
||||||
|
{
|
||||||
|
return RoutingAlgorithms<Algorithm>{heaps, facade_provider->Get(params)};
|
||||||
|
}
|
||||||
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
|
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
|
||||||
mutable SearchEngineData<Algorithm> heaps;
|
mutable SearchEngineData<Algorithm> heaps;
|
||||||
|
tbb::task_scheduler_init task_scheduler;
|
||||||
|
|
||||||
const plugins::ViaRoutePlugin route_plugin;
|
const plugins::ViaRoutePlugin route_plugin;
|
||||||
const plugins::TablePlugin table_plugin;
|
const plugins::TablePlugin table_plugin;
|
||||||
@@ -178,7 +180,7 @@ bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const Engin
|
|||||||
|
|
||||||
auto mem = storage::makeSharedMemory(barrier.data().region);
|
auto mem = storage::makeSharedMemory(barrier.data().region);
|
||||||
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
|
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
|
||||||
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER) >
|
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER_0) >
|
||||||
sizeof(std::uint64_t) + sizeof(util::FingerPrint);
|
sizeof(std::uint64_t) + sizeof(util::FingerPrint);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -187,9 +189,10 @@ bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const Engin
|
|||||||
return false;
|
return false;
|
||||||
storage::io::FileReader in(config.storage_config.GetPath(".osrm.core"),
|
storage::io::FileReader in(config.storage_config.GetPath(".osrm.core"),
|
||||||
storage::io::FileReader::VerifyFingerprint);
|
storage::io::FileReader::VerifyFingerprint);
|
||||||
|
in.ReadElementCount64(); // number of core markers
|
||||||
|
const auto number_of_core_markers = in.ReadElementCount64();
|
||||||
|
|
||||||
auto size = in.GetSize();
|
return number_of_core_markers > 0;
|
||||||
return size > sizeof(std::uint64_t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ struct EngineConfig final
|
|||||||
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
|
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
|
||||||
bool use_shared_memory = true;
|
bool use_shared_memory = true;
|
||||||
Algorithm algorithm = Algorithm::CH;
|
Algorithm algorithm = Algorithm::CH;
|
||||||
|
int use_threads_number = 1;
|
||||||
|
std::string verbosity;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||||
return boolPairAnd(HasValidEdge(segment),
|
return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)),
|
||||||
CheckApproach(input_coordinate, segment, approach));
|
CheckApproach(input_coordinate, segment, approach));
|
||||||
},
|
},
|
||||||
[this, max_distance, input_coordinate](const std::size_t,
|
[this, max_distance, input_coordinate](const std::size_t,
|
||||||
@@ -81,8 +81,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, bearing, bearing_range, max_distance](
|
[this, approach, &input_coordinate, bearing, bearing_range, max_distance](
|
||||||
const CandidateSegment &segment) {
|
const CandidateSegment &segment) {
|
||||||
auto use_direction = boolPairAnd(
|
auto use_direction =
|
||||||
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
|
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||||
|
boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)));
|
||||||
use_direction =
|
use_direction =
|
||||||
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
|
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
|
||||||
return use_direction;
|
return use_direction;
|
||||||
@@ -108,8 +109,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, bearing, bearing_range](
|
[this, approach, &input_coordinate, bearing, bearing_range](
|
||||||
const CandidateSegment &segment) {
|
const CandidateSegment &segment) {
|
||||||
auto use_direction = boolPairAnd(
|
auto use_direction =
|
||||||
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
|
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||||
|
boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)));
|
||||||
return boolPairAnd(use_direction,
|
return boolPairAnd(use_direction,
|
||||||
CheckApproach(input_coordinate, segment, approach));
|
CheckApproach(input_coordinate, segment, approach));
|
||||||
},
|
},
|
||||||
@@ -135,8 +137,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, bearing, bearing_range](
|
[this, approach, &input_coordinate, bearing, bearing_range](
|
||||||
const CandidateSegment &segment) {
|
const CandidateSegment &segment) {
|
||||||
auto use_direction = boolPairAnd(
|
auto use_direction =
|
||||||
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
|
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||||
|
boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)));
|
||||||
return boolPairAnd(use_direction,
|
return boolPairAnd(use_direction,
|
||||||
CheckApproach(input_coordinate, segment, approach));
|
CheckApproach(input_coordinate, segment, approach));
|
||||||
},
|
},
|
||||||
@@ -159,7 +162,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||||
return boolPairAnd(HasValidEdge(segment),
|
return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)),
|
||||||
CheckApproach(input_coordinate, segment, approach));
|
CheckApproach(input_coordinate, segment, approach));
|
||||||
},
|
},
|
||||||
[max_results](const std::size_t num_results, const CandidateSegment &) {
|
[max_results](const std::size_t num_results, const CandidateSegment &) {
|
||||||
@@ -180,7 +183,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||||
return boolPairAnd(HasValidEdge(segment),
|
return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)),
|
||||||
CheckApproach(input_coordinate, segment, approach));
|
CheckApproach(input_coordinate, segment, approach));
|
||||||
},
|
},
|
||||||
[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,
|
||||||
@@ -209,6 +212,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto valid_edges = HasValidEdge(segment);
|
const auto valid_edges = HasValidEdge(segment);
|
||||||
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||||
use_directions =
|
use_directions =
|
||||||
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
|
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||||
@@ -254,6 +259,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
|
|
||||||
const auto valid_edges = HasValidEdge(segment);
|
const auto valid_edges = HasValidEdge(segment);
|
||||||
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||||
use_directions =
|
use_directions =
|
||||||
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
|
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||||
@@ -302,6 +309,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||||
|
|
||||||
if (use_segment)
|
if (use_segment)
|
||||||
@@ -309,6 +317,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
use_directions =
|
use_directions =
|
||||||
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||||
HasValidEdge(segment));
|
HasValidEdge(segment));
|
||||||
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(
|
use_directions = boolPairAnd(
|
||||||
use_directions, CheckApproach(input_coordinate, segment, approach));
|
use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||||
|
|
||||||
@@ -358,6 +367,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||||
|
|
||||||
if (use_segment)
|
if (use_segment)
|
||||||
@@ -365,6 +375,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
use_directions =
|
use_directions =
|
||||||
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||||
HasValidEdge(segment));
|
HasValidEdge(segment));
|
||||||
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(
|
use_directions = boolPairAnd(
|
||||||
use_directions, CheckApproach(input_coordinate, segment, approach));
|
use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||||
|
|
||||||
@@ -491,23 +502,26 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bool is_reverse_valid_target = areSegmentsValid(
|
bool is_reverse_valid_target = areSegmentsValid(
|
||||||
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
|
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
|
||||||
|
|
||||||
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
auto transformed = PhantomNodeWithDistance{
|
||||||
component_id,
|
PhantomNode{data,
|
||||||
forward_weight,
|
component_id,
|
||||||
reverse_weight,
|
forward_weight,
|
||||||
forward_weight_offset,
|
reverse_weight,
|
||||||
reverse_weight_offset,
|
forward_weight_offset,
|
||||||
forward_duration,
|
reverse_weight_offset,
|
||||||
reverse_duration,
|
forward_duration,
|
||||||
forward_duration_offset,
|
reverse_duration,
|
||||||
reverse_duration_offset,
|
forward_duration_offset,
|
||||||
is_forward_valid_source,
|
reverse_duration_offset,
|
||||||
is_forward_valid_target,
|
is_forward_valid_source,
|
||||||
is_reverse_valid_source,
|
is_forward_valid_target,
|
||||||
is_reverse_valid_target,
|
is_reverse_valid_source,
|
||||||
point_on_segment,
|
is_reverse_valid_target,
|
||||||
input_coordinate},
|
point_on_segment,
|
||||||
current_perpendicular_distance};
|
input_coordinate,
|
||||||
|
static_cast<unsigned short>(util::coordinate_calculation::bearing(
|
||||||
|
coordinates[data.u], coordinates[data.v]))},
|
||||||
|
current_perpendicular_distance};
|
||||||
|
|
||||||
return transformed;
|
return transformed;
|
||||||
}
|
}
|
||||||
@@ -528,6 +542,25 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
max_distance;
|
max_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, bool> CheckSegmentExclude(const CandidateSegment &segment) const
|
||||||
|
{
|
||||||
|
std::pair<bool, bool> valid = {true, true};
|
||||||
|
|
||||||
|
if (segment.data.forward_segment_id.enabled &&
|
||||||
|
datafacade.ExcludeNode(segment.data.forward_segment_id.id))
|
||||||
|
{
|
||||||
|
valid.first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segment.data.reverse_segment_id.enabled &&
|
||||||
|
datafacade.ExcludeNode(segment.data.reverse_segment_id.id))
|
||||||
|
{
|
||||||
|
valid.second = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<bool, bool> CheckSegmentBearing(const CandidateSegment &segment,
|
std::pair<bool, bool> CheckSegmentBearing(const CandidateSegment &segment,
|
||||||
const int filter_bearing,
|
const int filter_bearing,
|
||||||
const int filter_bearing_range) const
|
const int filter_bearing_range) const
|
||||||
|
|||||||
@@ -29,8 +29,12 @@ namespace guidance
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry);
|
std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry,
|
||||||
std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry);
|
const PhantomNode &source_node,
|
||||||
|
const bool traversed_in_reverse);
|
||||||
|
std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry,
|
||||||
|
const PhantomNode &target_node,
|
||||||
|
const bool traversed_in_reverse);
|
||||||
} // ns detail
|
} // ns detail
|
||||||
|
|
||||||
inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &facade,
|
inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &facade,
|
||||||
@@ -72,7 +76,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
std::size_t segment_index = 0;
|
std::size_t segment_index = 0;
|
||||||
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
||||||
|
|
||||||
auto bearings = detail::getDepartBearings(leg_geometry);
|
auto bearings =
|
||||||
|
detail::getDepartBearings(leg_geometry, source_node, source_traversed_in_reverse);
|
||||||
|
|
||||||
StepManeuver maneuver{source_node.location,
|
StepManeuver maneuver{source_node.location,
|
||||||
bearings.first,
|
bearings.first,
|
||||||
@@ -260,7 +265,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||||
bearings = detail::getArriveBearings(leg_geometry);
|
bearings = detail::getArriveBearings(leg_geometry, target_node, target_traversed_in_reverse);
|
||||||
|
|
||||||
intersection = {
|
intersection = {
|
||||||
target_node.location,
|
target_node.location,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace guidance
|
|||||||
|
|
||||||
// passed as none-reference to modify in-place and move out again
|
// passed as none-reference to modify in-place and move out again
|
||||||
OSRM_ATTR_WARN_UNUSED
|
OSRM_ATTR_WARN_UNUSED
|
||||||
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps);
|
std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
|
||||||
|
|
||||||
// trim initial/final segment of very short length.
|
// trim initial/final segment of very short length.
|
||||||
// This function uses in/out parameter passing to modify both steps and geometry in place.
|
// This function uses in/out parameter passing to modify both steps and geometry in place.
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@@ -53,7 +54,7 @@ struct PhantomNode
|
|||||||
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
||||||
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
||||||
is_valid_forward_source{false}, is_valid_forward_target{false},
|
is_valid_forward_source{false}, is_valid_forward_target{false},
|
||||||
is_valid_reverse_source{false}, is_valid_reverse_target{false}
|
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +118,12 @@ struct PhantomNode
|
|||||||
{
|
{
|
||||||
return reverse_segment_id.enabled && is_valid_reverse_target;
|
return reverse_segment_id.enabled && is_valid_reverse_target;
|
||||||
}
|
}
|
||||||
|
short GetBearing(const bool traversed_in_reverse) const
|
||||||
|
{
|
||||||
|
if (traversed_in_reverse)
|
||||||
|
return std::round(util::bearing::reverse(bearing));
|
||||||
|
return std::round(bearing);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
||||||
|
|
||||||
@@ -136,7 +143,8 @@ struct PhantomNode
|
|||||||
bool is_valid_reverse_source,
|
bool is_valid_reverse_source,
|
||||||
bool is_valid_reverse_target,
|
bool is_valid_reverse_target,
|
||||||
const util::Coordinate location,
|
const util::Coordinate location,
|
||||||
const util::Coordinate input_location)
|
const util::Coordinate input_location,
|
||||||
|
const unsigned short bearing)
|
||||||
: forward_segment_id{other.forward_segment_id},
|
: forward_segment_id{other.forward_segment_id},
|
||||||
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
|
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
|
||||||
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
|
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
|
||||||
@@ -148,7 +156,7 @@ struct PhantomNode
|
|||||||
is_valid_forward_source{is_valid_forward_source},
|
is_valid_forward_source{is_valid_forward_source},
|
||||||
is_valid_forward_target{is_valid_forward_target},
|
is_valid_forward_target{is_valid_forward_target},
|
||||||
is_valid_reverse_source{is_valid_reverse_source},
|
is_valid_reverse_source{is_valid_reverse_source},
|
||||||
is_valid_reverse_target{is_valid_reverse_target}
|
is_valid_reverse_target{is_valid_reverse_target}, bearing{bearing}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +181,8 @@ struct PhantomNode
|
|||||||
unsigned short is_valid_forward_target : 1;
|
unsigned short is_valid_forward_target : 1;
|
||||||
unsigned short is_valid_reverse_source : 1;
|
unsigned short is_valid_reverse_source : 1;
|
||||||
unsigned short is_valid_reverse_target : 1;
|
unsigned short is_valid_reverse_target : 1;
|
||||||
unsigned short : 12; // Unused padding out to 16 bits (2 bytes)
|
unsigned short bearing : 9;
|
||||||
|
unsigned short : 3; // Unused padding out to 16 bits (2 bytes)
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "engine/api/base_parameters.hpp"
|
#include "engine/api/base_parameters.hpp"
|
||||||
#include "engine/datafacade/datafacade_base.hpp"
|
#include "engine/datafacade/datafacade_base.hpp"
|
||||||
#include "engine/phantom_node.hpp"
|
#include "engine/phantom_node.hpp"
|
||||||
|
#include "engine/routing_algorithms.hpp"
|
||||||
#include "engine/status.hpp"
|
#include "engine/status.hpp"
|
||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
@@ -36,6 +37,31 @@ class BasePlugin
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckAlgorithms(const api::BaseParameters ¶ms,
|
||||||
|
const RoutingAlgorithmsInterface &algorithms,
|
||||||
|
util::json::Object &result) const
|
||||||
|
{
|
||||||
|
if (algorithms.IsValid())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!algorithms.HasExcludeFlags() && !params.exclude.empty())
|
||||||
|
{
|
||||||
|
Error("NotImplemented", "This algorithm does not support exclude flags.", result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (algorithms.HasExcludeFlags() && !params.exclude.empty())
|
||||||
|
{
|
||||||
|
Error("InvalidValue", "Exclude flag combination is not supported.", result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(false,
|
||||||
|
"There are only two reasons why the algorithm interface can be invalid.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Status Error(const std::string &code,
|
Status Error(const std::string &code,
|
||||||
const std::string &message,
|
const std::string &message,
|
||||||
util::json::Object &json_result) const
|
util::json::Object &json_result) const
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class RoutingAlgorithmsInterface
|
|||||||
virtual InternalRouteResult
|
virtual InternalRouteResult
|
||||||
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
virtual std::vector<EdgeDuration>
|
||||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const = 0;
|
const std::vector<std::size_t> &target_indices) const = 0;
|
||||||
@@ -54,6 +54,8 @@ class RoutingAlgorithmsInterface
|
|||||||
virtual bool HasMapMatching() const = 0;
|
virtual bool HasMapMatching() const = 0;
|
||||||
virtual bool HasManyToManySearch() const = 0;
|
virtual bool HasManyToManySearch() const = 0;
|
||||||
virtual bool HasGetTileTurns() const = 0;
|
virtual bool HasGetTileTurns() const = 0;
|
||||||
|
virtual bool HasExcludeFlags() const = 0;
|
||||||
|
virtual bool IsValid() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Short-lived object passed to each plugin in request to wrap routing algorithms
|
// Short-lived object passed to each plugin in request to wrap routing algorithms
|
||||||
@@ -79,7 +81,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
InternalRouteResult
|
InternalRouteResult
|
||||||
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
||||||
|
|
||||||
std::vector<EdgeWeight>
|
std::vector<EdgeDuration>
|
||||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const final override;
|
const std::vector<std::size_t> &target_indices) const final override;
|
||||||
@@ -127,6 +129,13 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
|
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasExcludeFlags() const final override
|
||||||
|
{
|
||||||
|
return routing_algorithms::HasExcludeFlags<Algorithm>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() const final override { return static_cast<bool>(facade); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SearchEngineData<Algorithm> &heaps;
|
SearchEngineData<Algorithm> &heaps;
|
||||||
std::shared_ptr<const DataFacade<Algorithm>> facade;
|
std::shared_ptr<const DataFacade<Algorithm>> facade;
|
||||||
@@ -157,16 +166,6 @@ RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phant
|
|||||||
return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes);
|
return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
|
||||||
std::vector<EdgeWeight>
|
|
||||||
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
|
||||||
const std::vector<std::size_t> &source_indices,
|
|
||||||
const std::vector<std::size_t> &target_indices) const
|
|
||||||
{
|
|
||||||
return routing_algorithms::manyToManySearch(
|
|
||||||
heaps, *facade, phantom_nodes, source_indices, target_indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
|
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
|
||||||
const routing_algorithms::CandidateLists &candidates_list,
|
const routing_algorithms::CandidateLists &candidates_list,
|
||||||
@@ -202,7 +201,7 @@ InternalManyRoutesResult inline RoutingAlgorithms<
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline std::vector<EdgeWeight>
|
inline std::vector<EdgeDuration>
|
||||||
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
||||||
const std::vector<PhantomNode> &,
|
const std::vector<PhantomNode> &,
|
||||||
const std::vector<std::size_t> &,
|
const std::vector<std::size_t> &,
|
||||||
|
|||||||
@@ -17,11 +17,23 @@ namespace routing_algorithms
|
|||||||
{
|
{
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
std::vector<std::size_t> source_indices,
|
||||||
const std::vector<std::size_t> &target_indices);
|
std::vector<std::size_t> target_indices);
|
||||||
|
|
||||||
|
namespace mld
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool DIRECTION>
|
||||||
|
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade,
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
std::size_t phantom_index,
|
||||||
|
std::vector<std::size_t> phantom_indices);
|
||||||
|
|
||||||
|
} // mld
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|||||||
@@ -132,40 +132,15 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION, typename Algorithm, typename... Args>
|
template <bool DIRECTION, typename Algorithm, typename... Args>
|
||||||
void routingStep(const DataFacade<Algorithm> &facade,
|
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
const NodeID node,
|
||||||
NodeID &middle_node,
|
const EdgeWeight weight,
|
||||||
EdgeWeight &path_upper_bound,
|
Args... args)
|
||||||
const bool force_loop_forward,
|
|
||||||
const bool force_loop_reverse,
|
|
||||||
Args... args)
|
|
||||||
{
|
{
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
const auto &cells = facade.GetCellStorage();
|
const auto &cells = facade.GetCellStorage();
|
||||||
|
const auto &metric = facade.GetCellMetric();
|
||||||
const auto node = forward_heap.DeleteMin();
|
|
||||||
const auto weight = forward_heap.GetKey(node);
|
|
||||||
|
|
||||||
// Upper bound for the path source -> target with
|
|
||||||
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
|
|
||||||
// is weight + reverse_weight
|
|
||||||
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
|
|
||||||
// with weight(to -> target) = reverse_weight and all weights ≥ 0
|
|
||||||
if (reverse_heap.WasInserted(node))
|
|
||||||
{
|
|
||||||
auto reverse_weight = reverse_heap.GetKey(node);
|
|
||||||
auto path_weight = weight + reverse_weight;
|
|
||||||
|
|
||||||
// if loops are forced, they are so at the source
|
|
||||||
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
|
|
||||||
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
|
|
||||||
(path_weight >= 0) && (path_weight < path_upper_bound))
|
|
||||||
{
|
|
||||||
middle_node = node;
|
|
||||||
path_upper_bound = path_weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto level = getNodeQueryLevel(partition, node, args...);
|
const auto level = getNodeQueryLevel(partition, node, args...);
|
||||||
|
|
||||||
@@ -174,12 +149,13 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
if (DIRECTION == FORWARD_DIRECTION)
|
if (DIRECTION == FORWARD_DIRECTION)
|
||||||
{
|
{
|
||||||
// Shortcuts in forward direction
|
// Shortcuts in forward direction
|
||||||
const auto &cell = cells.GetCell(level, partition.GetCell(level, node));
|
const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node));
|
||||||
auto destination = cell.GetDestinationNodes().begin();
|
auto destination = cell.GetDestinationNodes().begin();
|
||||||
for (auto shortcut_weight : cell.GetOutWeight(node))
|
for (auto shortcut_weight : cell.GetOutWeight(node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
||||||
const NodeID to = *destination;
|
const NodeID to = *destination;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
||||||
{
|
{
|
||||||
const EdgeWeight to_weight = weight + shortcut_weight;
|
const EdgeWeight to_weight = weight + shortcut_weight;
|
||||||
@@ -200,12 +176,13 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Shortcuts in backward direction
|
// Shortcuts in backward direction
|
||||||
const auto &cell = cells.GetCell(level, partition.GetCell(level, node));
|
const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node));
|
||||||
auto source = cell.GetSourceNodes().begin();
|
auto source = cell.GetSourceNodes().begin();
|
||||||
for (auto shortcut_weight : cell.GetInWeight(node))
|
for (auto shortcut_weight : cell.GetInWeight(node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
||||||
const NodeID to = *source;
|
const NodeID to = *source;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
||||||
{
|
{
|
||||||
const EdgeWeight to_weight = weight + shortcut_weight;
|
const EdgeWeight to_weight = weight + shortcut_weight;
|
||||||
@@ -233,7 +210,8 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
{
|
{
|
||||||
const NodeID to = facade.GetTarget(edge);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
|
||||||
if (checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
|
if (!facade.ExcludeNode(to) &&
|
||||||
|
checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(edge_data.weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_data.weight > 0, "edge_weight invalid");
|
||||||
const EdgeWeight to_weight = weight + edge_data.weight;
|
const EdgeWeight to_weight = weight + edge_data.weight;
|
||||||
@@ -252,6 +230,45 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool DIRECTION, typename Algorithm, typename... Args>
|
||||||
|
void routingStep(const DataFacade<Algorithm> &facade,
|
||||||
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
|
NodeID &middle_node,
|
||||||
|
EdgeWeight &path_upper_bound,
|
||||||
|
const bool force_loop_forward,
|
||||||
|
const bool force_loop_reverse,
|
||||||
|
Args... args)
|
||||||
|
{
|
||||||
|
const auto node = forward_heap.DeleteMin();
|
||||||
|
const auto weight = forward_heap.GetKey(node);
|
||||||
|
|
||||||
|
BOOST_ASSERT(!facade.ExcludeNode(node));
|
||||||
|
|
||||||
|
// Upper bound for the path source -> target with
|
||||||
|
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
|
||||||
|
// is weight + reverse_weight
|
||||||
|
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
|
||||||
|
// with weight(to -> target) = reverse_weight and all weights ≥ 0
|
||||||
|
if (reverse_heap.WasInserted(node))
|
||||||
|
{
|
||||||
|
auto reverse_weight = reverse_heap.GetKey(node);
|
||||||
|
auto path_weight = weight + reverse_weight;
|
||||||
|
|
||||||
|
// if loops are forced, they are so at the source
|
||||||
|
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
|
||||||
|
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
|
||||||
|
(path_weight >= 0) && (path_weight < path_upper_bound))
|
||||||
|
{
|
||||||
|
middle_node = node;
|
||||||
|
path_upper_bound = path_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relax outgoing edges from node
|
||||||
|
relaxOutgoingEdges<DIRECTION>(facade, forward_heap, node, weight, args...);
|
||||||
|
}
|
||||||
|
|
||||||
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
|
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
|
||||||
// This gives us a packed path (node ids) from the base graph around s and t,
|
// This gives us a packed path (node ids) from the base graph around s and t,
|
||||||
// and overlay node ids otherwise. We then have to unpack the overlay clique
|
// and overlay node ids otherwise. We then have to unpack the overlay clique
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ struct TurnData final
|
|||||||
const int turn_angle;
|
const int turn_angle;
|
||||||
const EdgeWeight weight;
|
const EdgeWeight weight;
|
||||||
const EdgeWeight duration;
|
const EdgeWeight duration;
|
||||||
|
const extractor::guidance::TurnInstruction turn_instruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "util/bit_range.hpp"
|
#include "util/bit_range.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -11,11 +13,26 @@ namespace extractor
|
|||||||
{
|
{
|
||||||
|
|
||||||
using ClassData = std::uint8_t;
|
using ClassData = std::uint8_t;
|
||||||
|
constexpr ClassData INAVLID_CLASS_DATA = std::numeric_limits<ClassData>::max();
|
||||||
static const std::uint8_t MAX_CLASS_INDEX = 8 - 1;
|
static const std::uint8_t MAX_CLASS_INDEX = 8 - 1;
|
||||||
|
static const std::uint8_t MAX_EXCLUDABLE_CLASSES = 8;
|
||||||
|
|
||||||
inline bool isSubset(const ClassData lhs, const ClassData rhs) { return (lhs & rhs) == lhs; }
|
inline bool isSubset(const ClassData lhs, const ClassData rhs) { return (lhs & rhs) == lhs; }
|
||||||
|
|
||||||
inline auto getClassIndexes(const ClassData data) { return util::makeBitRange<ClassData>(data); }
|
inline auto getClassIndexes(const ClassData data) { return util::makeBitRange<ClassData>(data); }
|
||||||
|
|
||||||
|
inline auto getClassData(const std::size_t index)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(index <= MAX_CLASS_INDEX);
|
||||||
|
return uint8_t{1} << index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isValidClassName(const std::string &name)
|
||||||
|
{
|
||||||
|
return std::find_if_not(name.begin(), name.end(), [](const auto c) {
|
||||||
|
return std::isalnum(c);
|
||||||
|
}) == name.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef EXTRACTION_RELATION_HPP
|
||||||
|
#define EXTRACTION_RELATION_HPP
|
||||||
|
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ExtractionRelation
|
||||||
|
{
|
||||||
|
using AttributesMap = std::unordered_map<std::string, std::string>;
|
||||||
|
using OsmIDTyped = std::pair<osmium::object_id_type, osmium::item_type>;
|
||||||
|
|
||||||
|
struct OsmIDTypedHash
|
||||||
|
{
|
||||||
|
std::size_t operator()(const OsmIDTyped &id) const
|
||||||
|
{
|
||||||
|
return id.first ^ (static_cast<std::uint64_t>(id.second) << 56);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ExtractionRelation() : is_restriction(false) {}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
is_restriction = false;
|
||||||
|
values.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRestriction() const { return is_restriction; }
|
||||||
|
|
||||||
|
AttributesMap &GetMember(const osmium::RelationMember &member)
|
||||||
|
{
|
||||||
|
return values[OsmIDTyped(member.ref(), member.type())];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_restriction;
|
||||||
|
std::unordered_map<OsmIDTyped, AttributesMap, OsmIDTypedHash> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
// It contains data of all parsed relations for each node/way element
|
||||||
|
class ExtractionRelationContainer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using AttributesMap = ExtractionRelation::AttributesMap;
|
||||||
|
using OsmIDTyped = ExtractionRelation::OsmIDTyped;
|
||||||
|
using RelationList = std::vector<AttributesMap>;
|
||||||
|
|
||||||
|
void AddRelation(const ExtractionRelation &rel)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!rel.is_restriction);
|
||||||
|
for (auto it : rel.values)
|
||||||
|
data[it.first].push_back(it.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
const RelationList &Get(const OsmIDTyped &id) const
|
||||||
|
{
|
||||||
|
const auto it = data.find(id);
|
||||||
|
if (it != data.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
static RelationList empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<OsmIDTyped, RelationList, ExtractionRelation::OsmIDTypedHash> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace extractor
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif // EXTRACTION_RELATION_HPP
|
||||||
@@ -15,6 +15,7 @@ namespace osmium
|
|||||||
{
|
{
|
||||||
class Node;
|
class Node;
|
||||||
class Way;
|
class Way;
|
||||||
|
class Relation;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
@@ -44,6 +45,7 @@ namespace extractor
|
|||||||
class ExtractionContainers;
|
class ExtractionContainers;
|
||||||
struct ExtractionNode;
|
struct ExtractionNode;
|
||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
|
struct ExtractionRelation;
|
||||||
struct ProfileProperties;
|
struct ProfileProperties;
|
||||||
struct InputConditionalTurnRestriction;
|
struct InputConditionalTurnRestriction;
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,14 @@ class CoordinateExtractor
|
|||||||
const double length,
|
const double length,
|
||||||
const double rate) const;
|
const double rate) const;
|
||||||
|
|
||||||
|
// find the coordinate at a specific distance in the vector
|
||||||
|
util::Coordinate
|
||||||
|
ExtractCoordinateAtLength(const double distance,
|
||||||
|
const std::vector<util::Coordinate> &coordinates) const;
|
||||||
|
util::Coordinate ExtractCoordinateAtLength(const double distance,
|
||||||
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
|
const std::vector<double> &length_cache) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||||
@@ -241,14 +249,6 @@ class CoordinateExtractor
|
|||||||
const double segment_length,
|
const double segment_length,
|
||||||
const std::vector<double> &segment_distances,
|
const std::vector<double> &segment_distances,
|
||||||
const std::uint8_t considered_lanes) const;
|
const std::uint8_t considered_lanes) const;
|
||||||
|
|
||||||
// find the coordinate at a specific location in the vector
|
|
||||||
util::Coordinate ExtractCoordinateAtLength(const double distance,
|
|
||||||
const std::vector<util::Coordinate> &coordinates,
|
|
||||||
const std::vector<double> &length_cache) const;
|
|
||||||
util::Coordinate
|
|
||||||
ExtractCoordinateAtLength(const double distance,
|
|
||||||
const std::vector<util::Coordinate> &coordinates) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
|||||||
@@ -327,6 +327,42 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
// check whether we turn onto a oneway through street. These typically happen at the end of
|
||||||
|
// roads and might not seem obvious, since it isn't always as visible that you cannot turn
|
||||||
|
// left/right. To be on the safe side, we announce these as non-obvious
|
||||||
|
const auto turns_onto_through_street = [&](const auto &road) {
|
||||||
|
// find edge opposite to the one we are checking (in-road)
|
||||||
|
const auto in_through_candidate =
|
||||||
|
intersection.FindClosestBearing(util::bearing::reverse(road.bearing));
|
||||||
|
|
||||||
|
const auto &in_data = node_based_graph.GetEdgeData(in_through_candidate->eid);
|
||||||
|
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||||
|
|
||||||
|
// by asking for the same class, we ensure that we do not overrule obvious by road-class
|
||||||
|
// decisions
|
||||||
|
const auto same_class = in_data.road_classification == out_data.road_classification;
|
||||||
|
|
||||||
|
// only if the entry is allowed for one of the two, but not the other, we need to check.
|
||||||
|
// Otherwise other handlers do it better
|
||||||
|
const bool is_oneway = !in_through_candidate->entry_allowed && road.entry_allowed;
|
||||||
|
|
||||||
|
const bool not_roundabout =
|
||||||
|
!(in_data.roundabout || in_data.circular || out_data.roundabout || out_data.circular);
|
||||||
|
|
||||||
|
// for the purpose of this check, we do not care about low-priority roads (parking lots,
|
||||||
|
// mostly). Since we postulate both classes to be the same, checking one of the two is
|
||||||
|
// enough
|
||||||
|
const bool not_low_priority = !in_data.road_classification.IsLowPriorityRoadClass();
|
||||||
|
|
||||||
|
const auto in_deviation = angularDeviation(in_through_candidate->angle, STRAIGHT_ANGLE);
|
||||||
|
const auto out_deviaiton = angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||||
|
// in case the deviation isn't considerably lower for the road we are turning onto,
|
||||||
|
// consider it non-obvious. The threshold here requires a slight (60) vs sharp (120)
|
||||||
|
// degree variation, at lest (120/60 == 2)
|
||||||
|
return is_oneway && same_class && not_roundabout && not_low_priority &&
|
||||||
|
(in_deviation / (std::max(out_deviaiton, 0.5)) <= 2);
|
||||||
|
};
|
||||||
|
|
||||||
if (best_over_best_continue)
|
if (best_over_best_continue)
|
||||||
{
|
{
|
||||||
// Find left/right deviation
|
// Find left/right deviation
|
||||||
@@ -366,8 +402,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
|
angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
|
||||||
|
|
||||||
// return best_option candidate if it is nearly straight and distinct from the nearest other
|
// return best_option candidate if it is nearly straight and distinct from the nearest other
|
||||||
// out
|
// out way
|
||||||
// way
|
|
||||||
if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||||
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
|
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
|
||||||
return best_option;
|
return best_option;
|
||||||
@@ -385,8 +420,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
right_data.road_classification);
|
right_data.road_classification);
|
||||||
|
|
||||||
// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
|
// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
|
||||||
// consider the
|
// consider the turn obvious
|
||||||
// turn obvious
|
|
||||||
const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) {
|
const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) {
|
||||||
return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
|
return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
|
||||||
FUZZY_ANGLE_DIFFERENCE &&
|
FUZZY_ANGLE_DIFFERENCE &&
|
||||||
@@ -400,6 +434,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
if (check_narrow(left_index) && !obvious_to_left)
|
if (check_narrow(left_index) && !obvious_to_left)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// we are turning onto a through street (possibly at the end of the road). Ensure that we
|
||||||
|
// announce a turn, if it isn't a slight merge
|
||||||
|
if (turns_onto_through_street(intersection[best_option]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
// checks if a given way in the intersection is distinct enough from the best_option
|
// checks if a given way in the intersection is distinct enough from the best_option
|
||||||
// candidate
|
// candidate
|
||||||
const auto isDistinct = [&](const std::size_t index, const double deviation) {
|
const auto isDistinct = [&](const std::size_t index, const double deviation) {
|
||||||
@@ -437,6 +476,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
|||||||
if (std::abs(best_continue_deviation) < 1)
|
if (std::abs(best_continue_deviation) < 1)
|
||||||
return best_continue;
|
return best_continue;
|
||||||
|
|
||||||
|
// we are turning onto a through street (possibly at the end of the road). Ensure that we
|
||||||
|
// announce a turn, if it isn't a slight merge
|
||||||
|
if (turns_onto_through_street(intersection[best_continue]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
// check if any other similar best continues exist
|
// check if any other similar best continues exist
|
||||||
std::size_t i, last = intersection.size();
|
std::size_t i, last = intersection.size();
|
||||||
for (i = 1; i < last; ++i)
|
for (i = 1; i < last; ++i)
|
||||||
|
|||||||
@@ -199,7 +199,10 @@ inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruct
|
|||||||
|
|
||||||
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
|
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
|
||||||
{
|
{
|
||||||
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
|
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout ||
|
||||||
|
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
|
||||||
|
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
|
||||||
|
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Silent Turn Instructions are not to be mentioned to the outside world but
|
// Silent Turn Instructions are not to be mentioned to the outside world but
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#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 <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -28,6 +30,7 @@ struct ProfileProperties
|
|||||||
use_turn_restrictions(false), left_hand_driving(false), fallback_to_duration(true),
|
use_turn_restrictions(false), left_hand_driving(false), fallback_to_duration(true),
|
||||||
weight_name{"duration"}, call_tagless_node_function(true)
|
weight_name{"duration"}, call_tagless_node_function(true)
|
||||||
{
|
{
|
||||||
|
std::fill(excludable_classes.begin(), excludable_classes.end(), INAVLID_CLASS_DATA);
|
||||||
BOOST_ASSERT(weight_name[MAX_WEIGHT_NAME_LENGTH] == '\0');
|
BOOST_ASSERT(weight_name[MAX_WEIGHT_NAME_LENGTH] == '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +73,24 @@ struct ProfileProperties
|
|||||||
return std::string(weight_name);
|
return std::string(weight_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark this combination of classes as excludable
|
||||||
|
void SetExcludableClasses(std::size_t index, ClassData classes)
|
||||||
|
{
|
||||||
|
excludable_classes[index] = classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this classes are excludable
|
||||||
|
boost::optional<std::size_t> ClassesAreExcludable(ClassData classes) const
|
||||||
|
{
|
||||||
|
auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes);
|
||||||
|
if (iter != excludable_classes.end())
|
||||||
|
{
|
||||||
|
return std::distance(excludable_classes.begin(), iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void SetClassName(std::size_t index, const std::string &name)
|
void SetClassName(std::size_t index, const std::string &name)
|
||||||
{
|
{
|
||||||
char *name_ptr = class_names[index];
|
char *name_ptr = class_names[index];
|
||||||
@@ -109,6 +130,8 @@ struct ProfileProperties
|
|||||||
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
|
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
|
||||||
//! stores the names of each class
|
//! stores the names of each class
|
||||||
std::array<char[MAX_CLASS_NAME_LENGTH + 1], MAX_CLASS_INDEX + 1> class_names;
|
std::array<char[MAX_CLASS_NAME_LENGTH + 1], MAX_CLASS_INDEX + 1> class_names;
|
||||||
|
//! stores the masks of excludable class combinations
|
||||||
|
std::array<ClassData, MAX_EXCLUDABLE_CLASSES> excludable_classes;
|
||||||
unsigned weight_precision = 1;
|
unsigned weight_precision = 1;
|
||||||
bool force_split_edges = false;
|
bool force_split_edges = false;
|
||||||
bool call_tagless_node_function = true;
|
bool call_tagless_node_function = true;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace osmium
|
|||||||
{
|
{
|
||||||
class Node;
|
class Node;
|
||||||
class Way;
|
class Way;
|
||||||
|
class Relation;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -33,8 +34,10 @@ namespace extractor
|
|||||||
{
|
{
|
||||||
|
|
||||||
class RestrictionParser;
|
class RestrictionParser;
|
||||||
|
class ExtractionRelationContainer;
|
||||||
struct ExtractionNode;
|
struct ExtractionNode;
|
||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
|
struct ExtractionRelation;
|
||||||
struct ExtractionTurn;
|
struct ExtractionTurn;
|
||||||
struct ExtractionSegment;
|
struct ExtractionSegment;
|
||||||
|
|
||||||
@@ -52,17 +55,21 @@ class ScriptingEnvironment
|
|||||||
|
|
||||||
virtual const ProfileProperties &GetProfileProperties() = 0;
|
virtual const ProfileProperties &GetProfileProperties() = 0;
|
||||||
|
|
||||||
|
virtual std::vector<std::vector<std::string>> GetExcludableClasses() = 0;
|
||||||
|
virtual std::vector<std::string> GetClassNames() = 0;
|
||||||
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
||||||
virtual std::vector<std::string> GetRestrictions() = 0;
|
virtual std::vector<std::string> GetRestrictions() = 0;
|
||||||
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
|
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
|
||||||
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
|
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void ProcessElements(
|
||||||
ProcessElements(const osmium::memory::Buffer &buffer,
|
const osmium::memory::Buffer &buffer,
|
||||||
const RestrictionParser &restriction_parser,
|
const RestrictionParser &restriction_parser,
|
||||||
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
const ExtractionRelationContainer &relations,
|
||||||
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
||||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
|
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
||||||
|
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
|
||||||
|
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef SCRIPTING_ENVIRONMENT_LUA_HPP
|
#ifndef SCRIPTING_ENVIRONMENT_LUA_HPP
|
||||||
#define SCRIPTING_ENVIRONMENT_LUA_HPP
|
#define SCRIPTING_ENVIRONMENT_LUA_HPP
|
||||||
|
|
||||||
|
#include "extractor/extraction_relation.hpp"
|
||||||
#include "extractor/raster_source.hpp"
|
#include "extractor/raster_source.hpp"
|
||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
|
|
||||||
@@ -19,8 +20,13 @@ namespace extractor
|
|||||||
|
|
||||||
struct LuaScriptingContext final
|
struct LuaScriptingContext final
|
||||||
{
|
{
|
||||||
void ProcessNode(const osmium::Node &, ExtractionNode &result);
|
void ProcessNode(const osmium::Node &,
|
||||||
void ProcessWay(const osmium::Way &, ExtractionWay &result);
|
ExtractionNode &result,
|
||||||
|
const ExtractionRelationContainer::RelationList &relations);
|
||||||
|
void ProcessWay(const osmium::Way &,
|
||||||
|
ExtractionWay &result,
|
||||||
|
const ExtractionRelationContainer::RelationList &relations);
|
||||||
|
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
|
||||||
|
|
||||||
ProfileProperties properties;
|
ProfileProperties properties;
|
||||||
RasterContainer raster_sources;
|
RasterContainer raster_sources;
|
||||||
@@ -29,11 +35,13 @@ struct LuaScriptingContext final
|
|||||||
bool has_turn_penalty_function;
|
bool has_turn_penalty_function;
|
||||||
bool has_node_function;
|
bool has_node_function;
|
||||||
bool has_way_function;
|
bool has_way_function;
|
||||||
|
bool has_relation_function;
|
||||||
bool has_segment_function;
|
bool has_segment_function;
|
||||||
|
|
||||||
sol::function turn_function;
|
sol::function turn_function;
|
||||||
sol::function way_function;
|
sol::function way_function;
|
||||||
sol::function node_function;
|
sol::function node_function;
|
||||||
|
sol::function relation_function;
|
||||||
sol::function segment_function;
|
sol::function segment_function;
|
||||||
|
|
||||||
int api_version;
|
int api_version;
|
||||||
@@ -51,30 +59,36 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
|
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
|
||||||
static const constexpr int SUPPORTED_MAX_API_VERSION = 2;
|
static const constexpr int SUPPORTED_MAX_API_VERSION = 3;
|
||||||
|
|
||||||
explicit Sol2ScriptingEnvironment(const std::string &file_name);
|
explicit Sol2ScriptingEnvironment(const std::string &file_name);
|
||||||
~Sol2ScriptingEnvironment() override = default;
|
~Sol2ScriptingEnvironment() override = default;
|
||||||
|
|
||||||
const ProfileProperties &GetProfileProperties() override;
|
const ProfileProperties &GetProfileProperties() override;
|
||||||
|
|
||||||
LuaScriptingContext &GetSol2Context();
|
std::vector<std::vector<std::string>> GetExcludableClasses() override;
|
||||||
|
|
||||||
std::vector<std::string> GetStringListFromTable(const std::string &table_name);
|
|
||||||
std::vector<std::string> GetStringListFromFunction(const std::string &function_name);
|
|
||||||
std::vector<std::string> GetNameSuffixList() override;
|
std::vector<std::string> GetNameSuffixList() override;
|
||||||
|
std::vector<std::string> GetClassNames() override;
|
||||||
std::vector<std::string> GetRestrictions() override;
|
std::vector<std::string> GetRestrictions() override;
|
||||||
void ProcessTurn(ExtractionTurn &turn) override;
|
void ProcessTurn(ExtractionTurn &turn) override;
|
||||||
void ProcessSegment(ExtractionSegment &segment) override;
|
void ProcessSegment(ExtractionSegment &segment) override;
|
||||||
|
|
||||||
void
|
void ProcessElements(
|
||||||
ProcessElements(const osmium::memory::Buffer &buffer,
|
const osmium::memory::Buffer &buffer,
|
||||||
const RestrictionParser &restriction_parser,
|
const RestrictionParser &restriction_parser,
|
||||||
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
const ExtractionRelationContainer &relations,
|
||||||
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
||||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
|
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
||||||
|
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
|
||||||
|
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
LuaScriptingContext &GetSol2Context();
|
||||||
|
|
||||||
|
std::vector<std::string> GetStringListFromTable(const std::string &table_name);
|
||||||
|
std::vector<std::vector<std::string>> GetStringListsFromTable(const std::string &table_name);
|
||||||
|
std::vector<std::string> GetStringListFromFunction(const std::string &function_name);
|
||||||
|
|
||||||
void InitContext(LuaScriptingContext &context);
|
void InitContext(LuaScriptingContext &context);
|
||||||
std::mutex init_mutex;
|
std::mutex init_mutex;
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
|
|||||||
params->Get(Nan::New("max_locations_map_matching").ToLocalChecked());
|
params->Get(Nan::New("max_locations_map_matching").ToLocalChecked());
|
||||||
auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked());
|
auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked());
|
||||||
auto max_alternatives = params->Get(Nan::New("max_alternatives").ToLocalChecked());
|
auto max_alternatives = params->Get(Nan::New("max_alternatives").ToLocalChecked());
|
||||||
|
auto use_threads_number = params->Get(Nan::New("use_threads_number").ToLocalChecked());
|
||||||
|
|
||||||
if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber())
|
if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber())
|
||||||
{
|
{
|
||||||
@@ -217,6 +218,11 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
|
|||||||
Nan::ThrowError("max_alternatives must be an integral number");
|
Nan::ThrowError("max_alternatives must be an integral number");
|
||||||
return engine_config_ptr();
|
return engine_config_ptr();
|
||||||
}
|
}
|
||||||
|
if (!use_threads_number->IsUndefined() && !use_threads_number->IsNumber())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("use_threads_number must be an integral number");
|
||||||
|
return engine_config_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
if (max_locations_trip->IsNumber())
|
if (max_locations_trip->IsNumber())
|
||||||
engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue());
|
engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue());
|
||||||
@@ -233,6 +239,8 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
|
|||||||
engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue());
|
engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue());
|
||||||
if (max_alternatives->IsNumber())
|
if (max_alternatives->IsNumber())
|
||||||
engine_config->max_alternatives = static_cast<int>(max_alternatives->NumberValue());
|
engine_config->max_alternatives = static_cast<int>(max_alternatives->NumberValue());
|
||||||
|
if (use_threads_number->IsNumber())
|
||||||
|
engine_config->use_threads_number = static_cast<int>(use_threads_number->NumberValue());
|
||||||
|
|
||||||
return engine_config;
|
return engine_config;
|
||||||
}
|
}
|
||||||
@@ -585,6 +593,39 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
|||||||
params->generate_hints = generate_hints->BooleanValue();
|
params->generate_hints = generate_hints->BooleanValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->Has(Nan::New("exclude").ToLocalChecked()))
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> exclude = obj->Get(Nan::New("exclude").ToLocalChecked());
|
||||||
|
if (exclude.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!exclude->IsArray())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Exclude must be an array of strings or empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Array> exclude_array = v8::Local<v8::Array>::Cast(exclude);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < exclude_array->Length(); ++i)
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> class_name = exclude_array->Get(i);
|
||||||
|
if (class_name.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (class_name->IsString())
|
||||||
|
{
|
||||||
|
std::string class_name_str = *v8::String::Utf8Value(class_name);
|
||||||
|
params->exclude.emplace_back(class_name_str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Exclude must be an array of strings or empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user