Compare commits
234 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 254ee07942 | |||
| 0bf8bd2230 | |||
| b5225f07cb | |||
| abed7690d0 | |||
| f96174ddbe | |||
| e5b713841a | |||
| 3b1b12069f | |||
| 1635f7351d | |||
| ce5ae411c1 | |||
| d1bc32fb31 | |||
| f9f87f25d4 | |||
| 89aa6b7881 | |||
| edf9e0c1ed | |||
| c2e520ad9d | |||
| 7649187095 | |||
| fe39d0fd10 | |||
| 98b83b7208 | |||
| 57321979ae | |||
| e3ce0c5887 | |||
| 95af72c70c | |||
| 3b37769624 | |||
| d150df1c5c | |||
| a322e27e05 | |||
| 98fe0badbe | |||
| 44b841a25d | |||
| 9c8bf820de | |||
| 4d9aa65e78 | |||
| 0f3942558f | |||
| ba074b0116 | |||
| 6aa97048df | |||
| d9a5c79ea6 | |||
| 9d7714c714 | |||
| 8291be375a | |||
| 0a73737f69 | |||
| 2fd1b6c913 | |||
| ea38a1d880 | |||
| f576e13c51 | |||
| ee7bb8731a | |||
| da0c3ff394 | |||
| 6ae559b42b | |||
| 95ca6ebdaa | |||
| 0d6964d9c8 | |||
| ba386d4b2c | |||
| b5ffb51e18 | |||
| a9f674497a | |||
| 1e8a92ccb4 | |||
| b9178bb8c7 | |||
| 520b29d0d5 | |||
| fe397e6953 | |||
| dcb741d827 | |||
| 508c205d35 | |||
| d5294bb5d0 | |||
| 6ed9be31ca | |||
| 3bbd3a8a65 | |||
| 73a608895a | |||
| 96c73baeb3 | |||
| 73113f5eb8 | |||
| 7b74b86891 | |||
| 0903b8227f | |||
| fa525ad610 | |||
| 0f2bb5dde5 | |||
| 84dc1b6845 | |||
| 4ce1a37772 | |||
| 8dd4cc5c40 | |||
| 6aed145dae | |||
| d15cc77b0b | |||
| 24a75d37fb | |||
| 7e80dae59b | |||
| 7316c48e9f | |||
| c520c7a24a | |||
| 7564633045 | |||
| 7174c5d036 | |||
| ddd128ce0e | |||
| f5aa5c0769 | |||
| 2acde49f0f | |||
| 8849015bbf | |||
| 70cd7a94ec | |||
| 3984dea34b | |||
| b11b471aa4 | |||
| 63754df4d4 | |||
| e644424508 | |||
| 4f6eef3d16 | |||
| e2e8104864 | |||
| 96127c289c | |||
| cfed65f7ea | |||
| c2263fec9b | |||
| 497720d060 | |||
| 238366e71f | |||
| 2c8cf26e74 | |||
| c87ae5612a | |||
| a2d83753bc | |||
| eedf75d951 | |||
| 3f51a1ae2e | |||
| a000f80705 | |||
| 7030bff7f7 | |||
| bb0b7fd2d1 | |||
| 71e1f3679e | |||
| b33517b099 | |||
| f3d5336892 | |||
| d81f25d54e | |||
| 44ebdfeb2d | |||
| a5a7a03fa0 | |||
| 363d2145bd | |||
| c7e19396a4 | |||
| 445e5bed49 | |||
| 4cf94319df | |||
| 1bb88b374e | |||
| 35fac07581 | |||
| 9287475b2a | |||
| b4976f89f2 | |||
| 93c8674a40 | |||
| d5f21fd13a | |||
| 04eef0463a | |||
| 82c3bc7b0e | |||
| 1d33cb96f5 | |||
| 648646068c | |||
| f251f93a11 | |||
| aab1aad8f4 | |||
| 65a6dc704e | |||
| 6018fcf490 | |||
| 1e6888c0d3 | |||
| c7303be33b | |||
| d8acf76f2d | |||
| 08248e3853 | |||
| 78acc6f215 | |||
| a4f1dc536d | |||
| 57a30dd375 | |||
| 5517ee334f | |||
| 30af544919 | |||
| f0069d3dcc | |||
| 206bdff9e7 | |||
| c32270b2b8 | |||
| cc03402570 | |||
| 21a76f1867 | |||
| 212ad94c90 | |||
| 378d9f4112 | |||
| e341d367d8 | |||
| 98937b187f | |||
| 59168e21b4 | |||
| d12a95b4ef | |||
| 83482afa02 | |||
| e470d1ae1c | |||
| e504128587 | |||
| 1ab6c07bad | |||
| 5ce465ce23 | |||
| a8b730576f | |||
| b796033473 | |||
| d078ed67ca | |||
| 346146d834 | |||
| 64307ea882 | |||
| 578eda7d28 | |||
| 505f4cb4a2 | |||
| bac6b729bf | |||
| d3a5cadb6c | |||
| 65351faf83 | |||
| 3aa1c5f13c | |||
| 8f3fe410b8 | |||
| ff3bf32b11 | |||
| 38cb01a30e | |||
| b8f7569e93 | |||
| cf17bd38eb | |||
| 930f6df2cb | |||
| e88106e990 | |||
| 21f64c75eb | |||
| 5186b9490d | |||
| e9e935303c | |||
| a154d71841 | |||
| fddb035539 | |||
| 1544a08ea2 | |||
| 8d68d4c050 | |||
| 62a1290043 | |||
| c5e1742150 | |||
| 754bc2d274 | |||
| 3ac061c546 | |||
| e59a7926a2 | |||
| be5b49e391 | |||
| 7b32d3184c | |||
| d770c35245 | |||
| e04baef3bb | |||
| 9d3ad22bc7 | |||
| cc35d15b2d | |||
| 15e3928906 | |||
| 4363fd64c4 | |||
| dac2f93383 | |||
| 82372bb2ab | |||
| b0c67c9019 | |||
| d83a34f72b | |||
| a16f156203 | |||
| 807aa71a7c | |||
| 14d9b67b58 | |||
| 82df0ca766 | |||
| a6c7529a4e | |||
| 202bb6d3e2 | |||
| bc514926bf | |||
| 9fc16b6a83 | |||
| 2125e0175d | |||
| 6b5982d389 | |||
| a4a8aa63d4 | |||
| bedf451952 | |||
| 93b8f1993c | |||
| c693f4806b | |||
| b07275694a | |||
| 82177c101b | |||
| da6dbd2159 | |||
| b3957d87b4 | |||
| 5f9ccadd6c | |||
| 6e04da9f8f | |||
| 58c13d2c07 | |||
| bca8593eef | |||
| 3e2e10a4c3 | |||
| 6979763292 | |||
| 324f1739e4 | |||
| 1489662f57 | |||
| 1c1f407f67 | |||
| 8fb631417b | |||
| ae45ad1ad2 | |||
| 6b89803534 | |||
| f6116db957 | |||
| c824429458 | |||
| 23b2154d98 | |||
| 25c8711aad | |||
| cf30628d4e | |||
| 7675c730b6 | |||
| 2ce74c05e1 | |||
| 88e6558da3 | |||
| f1140ec903 | |||
| a2e114e852 | |||
| 8f6fc0146b | |||
| 6ad1cd3fb5 | |||
| 40443d1e25 | |||
| 4ec323c5cc | |||
| 300d901618 | |||
| fd6daa580a | |||
| c2fc47df34 |
@@ -80,6 +80,7 @@ stxxl.errlog
|
||||
/test/profile.lua
|
||||
/test/cache
|
||||
/test/speeds.csv
|
||||
/test/penalties.csv
|
||||
/test/data/monaco.*
|
||||
node_modules
|
||||
|
||||
|
||||
+83
-70
@@ -1,7 +1,7 @@
|
||||
#language: cpp
|
||||
# This makes travis use the thin image which boots faster
|
||||
language: generic
|
||||
language: cpp
|
||||
|
||||
git:
|
||||
depth: 10
|
||||
|
||||
# sudo:required is needed for trusty images
|
||||
sudo: required
|
||||
@@ -13,101 +13,109 @@ notifications:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
|
||||
cache:
|
||||
ccache: true
|
||||
apt: true
|
||||
|
||||
env:
|
||||
global:
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- JOBS=4
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
# We override the compiler names here to yield better ccache behavior, which uses this as key
|
||||
include:
|
||||
|
||||
# Debug Builds
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
compiler: "gcc-5-debug"
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'pip']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Debug' COVERAGE=ON
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
compiler: "gcc-4.8-debug"
|
||||
addons: &gcc48
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-4.8' CXXCOMPILER='g++-4.8' BUILD_TYPE='Debug'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
compiler: "clang-3.8-debug"
|
||||
addons: &clang38
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Debug' RUN_CLANG_FORMAT=ON
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Debug'
|
||||
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Debug' JOBS=1 CUCUMBER_TIMEOUT=60000
|
||||
|
||||
# Release Builds
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
compiler: "gcc-5-release"
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons: &gcc48
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
env: CCOMPILER='gcc-4.8' CXXCOMPILER='g++-4.8' BUILD_TYPE='Release'
|
||||
# Disabled because of CI slowness
|
||||
#- os: linux
|
||||
#- compiler: gcc
|
||||
#- addons: &gcc48
|
||||
#- apt:
|
||||
#- sources: ['ubuntu-toolchain-r-test']
|
||||
#- packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
#- env: CCOMPILER='gcc-4.8' CXXCOMPILER='g++-4.8' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: &clang38
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release'
|
||||
# Disabled because of CI slowness
|
||||
#- os: linux
|
||||
#- compiler: clang
|
||||
#- addons: &clang38
|
||||
#- apt:
|
||||
#- sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
#- packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Release'
|
||||
# Disabled because of CI slowness
|
||||
#- os: osx
|
||||
#- osx_image: xcode7.3
|
||||
#- compiler: clang
|
||||
#- env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Release'
|
||||
|
||||
# Shared Library
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
compiler: "gcc-5-release-shared"
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons: &clang38
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
# Disabled because CI slowness
|
||||
#- os: linux
|
||||
#- compiler: clang
|
||||
#- addons: &clang38
|
||||
#- apt:
|
||||
#- sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
#- packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
|
||||
before_install:
|
||||
- source ./scripts/install_node.sh 4
|
||||
|
||||
install:
|
||||
- npm install
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
||||
- |
|
||||
if [[ -n "${COVERAGE}" ]]; then
|
||||
pip install --user cpp-coveralls
|
||||
fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.1-Linux-x86_64.tar.gz"
|
||||
@@ -115,10 +123,10 @@ install:
|
||||
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
||||
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
# implicit deps, but seem to be installed by default with recent images: libxml2 GDAL boost
|
||||
brew install cmake libzip libstxxl lua51 luabind tbb md5sha1sum
|
||||
brew install cmake libzip libstxxl lua51 luabind tbb md5sha1sum ccache
|
||||
fi
|
||||
|
||||
before_script:
|
||||
install:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
@@ -126,41 +134,46 @@ before_script:
|
||||
fi
|
||||
- mkdir build && pushd build
|
||||
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
||||
- export OSRM_PORT=5000 OSRM_TIMEOUT=6000
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DCOVERAGE=${COVERAGE:-OFF} -DBUILD_TOOLS=1 -DENABLE_CCACHE=0
|
||||
|
||||
script:
|
||||
- make --jobs=2
|
||||
- make tests --jobs=2
|
||||
- make benchmarks
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DCOVERAGE=${COVERAGE:-OFF} -DBUILD_TOOLS=1 -DENABLE_CCACHE=ON
|
||||
- echo "travis_fold:start:MAKE"
|
||||
- make osrm-extract --jobs=3
|
||||
- make --jobs=${JOBS}
|
||||
- make tests --jobs=${JOBS}
|
||||
- make benchmarks --jobs=${JOBS}
|
||||
- echo "travis_fold:end:MAKE"
|
||||
- ccache -s
|
||||
- sudo make install
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
sudo ldconfig
|
||||
fi
|
||||
- echo "travis_fold:start:UNIT_TESTS"
|
||||
- popd
|
||||
- mkdir example/build && pushd example/build
|
||||
- cmake ..
|
||||
- make
|
||||
- popd
|
||||
|
||||
script:
|
||||
- echo "travis_fold:start:BENCHMARK"
|
||||
- make -C test/data benchmark
|
||||
- echo "travis_fold:end:BENCHMARK"
|
||||
- ./example/build/osrm-example test/data/monaco.osrm
|
||||
# All tests assume to be run from the build directory
|
||||
- pushd build
|
||||
- ./unit_tests/library-tests ../test/data/monaco.osrm
|
||||
- ./unit_tests/extractor-tests
|
||||
- ./unit_tests/engine-tests
|
||||
- ./unit_tests/util-tests
|
||||
- ./unit_tests/server-tests
|
||||
- echo "travis_fold:end:UNIT_TESTS"
|
||||
- popd
|
||||
- echo "travis_fold:start:CUCUMBER"
|
||||
- npm test
|
||||
- echo "travis_fold:end:CUCUMBER"
|
||||
- echo "travis_fold:start:BENCHMARK"
|
||||
- make -C test/data benchmark
|
||||
- echo "travis_fold:end:BENCHMARK"
|
||||
- ./build/unit_tests/library-tests test/data/monaco.osrm
|
||||
- mkdir example/build && pushd example/build
|
||||
- cmake ..
|
||||
- make
|
||||
- ./osrm-example ../../test/data/monaco.osrm
|
||||
- popd
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [ -n "$RUN_CLANG_FORMAT" ]; then
|
||||
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
||||
./scripts/format.sh || true # we don't want to fail just yet
|
||||
fi
|
||||
- coveralls --build-root build --exclude unit_tests --exclude third_party --exclude node_modules --gcov-options '\-lp'
|
||||
- |
|
||||
if [ -n "${COVERAGE}" ]; then
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
fi
|
||||
|
||||
+103
@@ -1,3 +1,106 @@
|
||||
# 5.2.0 RC1
|
||||
Changes from 5.1.0
|
||||
|
||||
- API:
|
||||
- new parameter `annotate` for `route` and `match` requests. Returns additional data about each
|
||||
coordinate along the selected/matched route line.
|
||||
- Introducing Intersections for Route Steps. This changes the API format in multiple ways.
|
||||
- `bearing_before`/`bearing_after` of `StepManeuver` are now deprecated and will be removed in the next major release
|
||||
- `location` of `StepManeuvers` is now deprecated and will be removed in the next major release
|
||||
- every `RouteStep` now has property `intersections` containing a list of `Intersection` objects.
|
||||
|
||||
- Profile changes:
|
||||
- duration parser now accepts P[n]DT[n]H[n]M[n]S, P[n]W, PTHHMMSS and PTHH:MM:SS ISO8601 formats.
|
||||
|
||||
- Infrastructure:
|
||||
- Better support for osrm-routed binary upgrade on the fly [UNIX specific]:
|
||||
- Open sockets with SO_REUSEPORT to allow multiple osrm-routed processes serving requests from the same port.
|
||||
- Add SIGNAL_PARENT_WHEN_READY environment variable to enable osrm-routed signal its parent with USR1 when it's running and waiting for requests.
|
||||
- BREAKING: Intersection Classification adds a new file to the mix (osrm.icd). This breaks the fileformat for older versions.
|
||||
- Disable http access logging via DISABLE_ACCESS_LOGGING environment
|
||||
variable.
|
||||
|
||||
- Guidance:
|
||||
- improved detection of turning streets, not reporting new-name in wrong situations
|
||||
|
||||
# 5.1.0
|
||||
Changes with regard to 5.0.0
|
||||
|
||||
- API:
|
||||
- added StepManeuver type `roundabout turn`. The type indicates a small roundabout that is treated as an intersection
|
||||
(turn right at the roundabout for first exit, go straight at the roundabout...)
|
||||
- added StepManeuver type `on ramp` and `off ramp` to distinguish between ramps that enter and exit a highway.
|
||||
- reduced new name instructions for trivial changes
|
||||
- combined multiple turns into a single instruction at segregated roads`
|
||||
|
||||
- Profile Changes:
|
||||
- introduced a suffix_list / get_name_suffix_list to specify name suffices to be suppressed in name change announcements
|
||||
- street names are now consistently assembled for the car, bike and walk profile as: "Name (Ref)" as in "Berlin (A5)"
|
||||
- new `car.lua` dependency `lib/destination.lua`
|
||||
- register a way's .nodes() function for use in the profile's way_function.
|
||||
|
||||
- Infrastructure
|
||||
- BREAKING: reordered internal instruction types. This breaks the **data format**
|
||||
- BREAKING: Changed the on-disk encoding of the StaticRTree for better performance. This breaks the **data format**
|
||||
|
||||
- Fixes:
|
||||
- Issue #2310: post-processing for local paths, fixes #2310
|
||||
- Issue #2309: local path looping, fixes #2309
|
||||
- Issue #2356: Make hint values optional
|
||||
- Issue #2349: Segmentation fault in some requests
|
||||
- Issue #2335: map matching was using shortest path with uturns disabled
|
||||
- Issue #2193: Fix syntax error position indicators in parameters queries
|
||||
- Fix search with u-turn
|
||||
- PhantomNode packing in MSVC now the same on other platforms
|
||||
- Summary is now not malformed when including unnamed roads
|
||||
- Emit new-name on when changing fron unanmed road to named road
|
||||
|
||||
# 5.0.0
|
||||
Changes with regard 5.0.0 RC2:
|
||||
- API:
|
||||
- if `geometry=geojson` is passed the resulting geometry can be a LineString or Point
|
||||
depending on how many coordinates are present.
|
||||
- the removal of the summary field was revered. for `steps=flase` the field will always be an empty string.
|
||||
|
||||
Changes with regard to 4.9.1:
|
||||
- API:
|
||||
- BREAKING: Complete rewrite of the HTTP and library API. See detailed documentation in the wiki.
|
||||
- BREAKING: The default coordinate order is now `longitude, latidue`. Exception: Polyline geometry
|
||||
which follow the original Google specification of `latitdue, longitude`.
|
||||
- BREAKING: Polyline geometries now use precision 5, instead of previously 6
|
||||
- BREAKING: Removed GPX support
|
||||
- New service `tile` which serves debug vector tiles of the road network
|
||||
- Completely new engine for guidance generation:
|
||||
- Support for highway ramps
|
||||
- Support for different intersection types (end of street, forks, merges)
|
||||
- Instruction post-processing to merge unimportant instructions
|
||||
- Improved handling of roundabouts
|
||||
|
||||
- Tools:
|
||||
- BREAKING: Renamed osrm-prepare to osrm-contract
|
||||
- BREAKING: Removes profiles from osrm-contract, only needed in osrm-extract.
|
||||
- Abort processing in osrm-extract if there are no snappable edges remaining.
|
||||
- Added .properties file to osrm-extract ouput.
|
||||
- Enables the use of multiple segment-speed-files on the osrm-contract command line
|
||||
|
||||
- Profile changes:
|
||||
- Remove movable bridge mode
|
||||
- Add `maxspeed=none` tag to car profile.
|
||||
- A `side_road` tag support for the OSRM car profile.
|
||||
|
||||
- Fixes:
|
||||
- Issue #2150: Prevents routing over delivery ways and nodes
|
||||
- Issue #1972: Provide uninstall target
|
||||
- Issue #2072: Disable alternatives by default and if core factor < 1.0
|
||||
- Issue #1999: Fix unpacking for self-loop nodes not in core.
|
||||
|
||||
- Infrastructure:
|
||||
- Cucumber test suit is now based on cucumber-js, removes Ruby as dependency
|
||||
- Updated to mapbox/variant v1.1
|
||||
- Updated to libosmium v2.6.1
|
||||
- Remove GeoJSON based debugging output, replaced by debug tiles
|
||||
|
||||
|
||||
# 5.0.0 RC2
|
||||
- Profiles:
|
||||
- `properties.allow_uturns_at_via` -> `properties.continue_straight_at_waypoint` (value is inverted!)
|
||||
|
||||
+7
-6
@@ -8,7 +8,7 @@ endif()
|
||||
|
||||
project(OSRM C CXX)
|
||||
set(OSRM_VERSION_MAJOR 5)
|
||||
set(OSRM_VERSION_MINOR 0)
|
||||
set(OSRM_VERSION_MINOR 2)
|
||||
set(OSRM_VERSION_PATCH 0)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
@@ -25,14 +25,14 @@ else()
|
||||
message(WARNING "Building on a 32 bit system is unsupported")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND MSVC_VERSION LESS 1800)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
||||
if(WIN32 AND MSVC_VERSION LESS 1900)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
|
||||
endif()
|
||||
|
||||
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
|
||||
option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF)
|
||||
option(BUILD_TOOLS "Build OSRM tools" OFF)
|
||||
option(BUILD_COMPONENTS "Build osrm-components" ON)
|
||||
option(BUILD_COMPONENTS "Build osrm-components" OFF)
|
||||
option(ENABLE_ASSERTIONS OFF)
|
||||
option(COVERAGE OFF)
|
||||
option(SANITIZER OFF)
|
||||
@@ -54,7 +54,7 @@ configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/util/version.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/util/version.hpp
|
||||
)
|
||||
file(GLOB UtilGlob src/util/*.cpp)
|
||||
file(GLOB UtilGlob src/util/*.cpp src/util/*/*.cpp)
|
||||
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
|
||||
file(GLOB ContractorGlob src/contractor/*.cpp)
|
||||
file(GLOB StorageGlob src/storage/*.cpp)
|
||||
@@ -140,6 +140,7 @@ if (COVERAGE)
|
||||
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
message(ERROR "COVERAGE=ON only make sense with a Debug build")
|
||||
endif()
|
||||
message(INFO "Enabling coverage")
|
||||
set(MAYBE_COVERAGE_LIBRARIES "gcov")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
|
||||
endif()
|
||||
@@ -232,7 +233,7 @@ include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
||||
|
||||
|
||||
find_package(Boost 1.49.0 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
if(NOT WIN32)
|
||||
if(NOT WIN32 AND NOT Boost_USE_STATIC_LIBS)
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||
endif()
|
||||
add_definitions(-DBOOST_SPIRIT_USE_PHOENIX_V3)
|
||||
|
||||
@@ -4,13 +4,11 @@ The Open Source Routing Machine is a high performance routing engine written in
|
||||
|
||||
## Current build status
|
||||
|
||||
| build config | branch | status |
|
||||
|:-------------|:--------|:------------|
|
||||
| Linux | master | [](https://travis-ci.org/Project-OSRM/osrm-backend) |
|
||||
| Linux | develop | [](https://travis-ci.org/Project-OSRM/osrm-backend) |
|
||||
| Windows | master/develop | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
|
||||
| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
|
||||
| Coverage | develop | [](https://coveralls.io/github/Project-OSRM/osrm-backend?branch=develop) |
|
||||
| build config | status |
|
||||
|:-------------|:-------|
|
||||
| Linux | [](https://travis-ci.org/Project-OSRM/osrm-backend) |
|
||||
| Windows | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
|
||||
| Coverage | [](https://codecov.io/gh/Project-OSRM/osrm-backend) |
|
||||
|
||||
## Building
|
||||
|
||||
@@ -20,7 +18,46 @@ To quickly try OSRM use our [free and daily updated online service](http://map.p
|
||||
|
||||
## Documentation
|
||||
|
||||
See the Wiki's [server API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Server-api) as well as the [library API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Library-api)
|
||||
### Full documentation
|
||||
|
||||
- [osrm-routed HTTP API documentation](docs/http.md)
|
||||
- [libosrm API documentation](docs/libosrm.md)
|
||||
|
||||
### Quick start
|
||||
|
||||
Building OSRM assuming all dependencies are installed:
|
||||
|
||||
```
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build .
|
||||
sudo cmake --build . --target install
|
||||
```
|
||||
|
||||
Loading preparing a dataset and starting the server:
|
||||
|
||||
```
|
||||
osrm-extract data.osm.pbf -p profiles/car.lua
|
||||
osrm-contract data.osrm
|
||||
osrm-routed data.osrm
|
||||
```
|
||||
|
||||
Running a query on your local server:
|
||||
|
||||
```
|
||||
curl http://127.0.0.1:5000/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
|
||||
```
|
||||
|
||||
### Running a request against the Demo Server
|
||||
|
||||
First read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy).
|
||||
|
||||
Then run simple query with instructions and alternatives on Berlin:
|
||||
|
||||
```
|
||||
curl https://router.project-osrm.org/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
|
||||
```
|
||||
|
||||
## References in publications
|
||||
|
||||
|
||||
+9
-6
@@ -116,17 +116,20 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
|
||||
|
||||
ECHO running engine-tests.exe ...
|
||||
%Configuration%\unit_tests\engine-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running extractor-tests.exe ...
|
||||
%Configuration%\unit_tests\extractor-tests.exe
|
||||
unit_tests\%Configuration%\extractor-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running engine-tests.exe ...
|
||||
unit_tests\%Configuration%\engine-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running util-tests.exe ...
|
||||
%Configuration%\unit_tests\util-tests.exe
|
||||
unit_tests\%Configuration%\util-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running server-tests.exe ...
|
||||
unit_tests\%Configuration%\server-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
|
||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE
|
||||
ECHO ========= CREATING PACKAGES ==========
|
||||
|
||||
CD %PROJECT_DIR%\build\%Configuration%
|
||||
|
||||
@@ -28,7 +28,6 @@ artifacts:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
|
||||
deploy:
|
||||
provider: FTP
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
coverage:
|
||||
|
||||
ignore:
|
||||
- unit_tests/.*
|
||||
- third_party/.*
|
||||
|
||||
comment: off
|
||||
+9
-1
@@ -5,15 +5,23 @@ RUN apt-get install -y build-essential git-core python-pip python-software-prope
|
||||
|
||||
RUN apt-get -y install gcc-4.8 g++-4.8 libboost1.55-all-dev llvm-3.4
|
||||
RUN apt-get -y install libbz2-dev libstxxl-dev libstxxl1 libxml2-dev
|
||||
RUN apt-get -y install libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev ruby1.9
|
||||
RUN apt-get -y install libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev
|
||||
RUN apt-get -y install curl cmake cmake-curses-gui
|
||||
|
||||
RUN pip install awscli
|
||||
|
||||
|
||||
# luabind
|
||||
RUN curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||
|
||||
WORKDIR /opt
|
||||
RUN git clone --depth 1 --branch v0.31.0 https://github.com/creationix/nvm.git
|
||||
RUN /bin/bash -c "source /opt/nvm/nvm.sh && nvm install v4"
|
||||
|
||||
RUN useradd -ms /bin/bash mapbox
|
||||
USER mapbox
|
||||
ENV HOME /home/mapbox
|
||||
WORKDIR /home/mapbox
|
||||
|
||||
RUN echo "source /opt/nvm/nvm.sh" > .bashrc
|
||||
RUN echo "source /home/mapbox/.bashrc" > .profile
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@ docker run \
|
||||
-e "CXX=clang++" \
|
||||
-v `pwd`:/home/mapbox/osrm-backend \
|
||||
-t mapbox/osrm:linux \
|
||||
osrm-backend/docker/test.sh
|
||||
/bin/bash -lc "osrm-backend/docker/test.sh"
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@ docker run \
|
||||
-e "CXX=g++" \
|
||||
-v `pwd`:/home/mapbox/osrm-backend \
|
||||
-t mapbox/osrm:linux \
|
||||
osrm-backend/docker/test.sh
|
||||
/bin/bash -lc "osrm-backend/docker/test.sh"
|
||||
|
||||
+5
-6
@@ -4,11 +4,8 @@ set -e
|
||||
set -o pipefail
|
||||
|
||||
export CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
||||
export PATH=$PATH:/home/mapbox/.gem/ruby/1.9.1/bin:/home/mapbox/osrm-backend/vendor/bundle/ruby/1.9.1/bin
|
||||
|
||||
cd /home/mapbox/osrm-backend
|
||||
gem install --user-install bundler
|
||||
bundle install --path vendor/bundle
|
||||
[ -d build ] && rm -rf build
|
||||
mkdir -p build
|
||||
cd build
|
||||
@@ -16,7 +13,9 @@ cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
|
||||
|
||||
make -j`nproc`
|
||||
make tests -j`nproc`
|
||||
./datastructure-tests
|
||||
./algorithm-tests
|
||||
#./unit_tests/server-tests
|
||||
#./unit_tests/library-tests
|
||||
#./unit_tests/extractor-tests
|
||||
#./unit_tests/util-tests
|
||||
cd ..
|
||||
bundle exec cucumber -p verify
|
||||
npm test
|
||||
|
||||
+592
@@ -0,0 +1,592 @@
|
||||
## Environent Variables
|
||||
|
||||
### SIGNAL_PARENT_WHEN_READY
|
||||
|
||||
If the SIGNAL_PARENT_WHEN_READY environment variable is set osrm-routed will
|
||||
send the USR1 signal to its parent when it will be running and waiting for
|
||||
requests. This could be used to upgrade osrm-routed to a new binary on the fly
|
||||
without any service downtime - no incoming requests will be lost.
|
||||
|
||||
### DISABLE_ACCESS_LOGGING
|
||||
|
||||
If the DISABLE_ACCESS_LOGGING environment variable is set osrm-routed will
|
||||
**not** log any http requests to standard output. This can be useful in high
|
||||
traffic setup.
|
||||
|
||||
## HTTP API
|
||||
|
||||
`osrm-routed` supports only `GET` requests of the form. If you your response size
|
||||
exceeds the limits of a simple URL encoding, consider using our [NodeJS bindings](https://github.com/Project-OSRM/node-osrm)
|
||||
or using the [C++ library directly](libosrm.md).
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/{service}/{version}/{profile}/{coordinates}[.{format}]?option=value&option=value
|
||||
```
|
||||
|
||||
- `server`: location of the server. Example: `127.0.0.1:5000` (default)
|
||||
- `service`: Name of the service to be used. Support are the following services:
|
||||
|
||||
| Service | Description |
|
||||
|-------------|-----------------------------------------------------------|
|
||||
| [`route`](#service-route) | shortest path between given coordinates |
|
||||
| [`nearest`](#service-nearest) | returns the nearest street segment for a given coordinate |
|
||||
| [`table`](#service-table) | computes distance tables for given coordinates |
|
||||
| [`match`](#service-match) | matches given coordinates to the road network |
|
||||
| [`trip`](#service-trip) | Compute the shortest round trip between given coordinates |
|
||||
| [`tile`](#service-tile) | Return vector tiles containing debugging info |
|
||||
|
||||
- `version`: Version of the protocol implemented by the service.
|
||||
- `profile`: Mode of transportation, is determined by the profile that is used to prepare the data
|
||||
- `coordinates`: String of format `{longitude},{latitude};{longitude},{latitude}[;{longitude},{latitude} ...]` or `polyline({polyline})`.
|
||||
- `format`: Only `json` is supportest at the moment. This parameter is optional and defaults to `json`.
|
||||
|
||||
Passing any `option=value` is optional. `polyline` follows Google's polyline format with precision 5 and can be generated using [this package](https://www.npmjs.com/package/polyline).
|
||||
To pass parameters to each location some options support an array like encoding:
|
||||
|
||||
```
|
||||
{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`.
|
||||
|
||||
Example: 2nd location use the default value for `option`:
|
||||
|
||||
```
|
||||
{option}={element};;{element}
|
||||
```
|
||||
|
||||
## General options
|
||||
|
||||
| Option | Values | Description |
|
||||
|------------|--------------------------------------------------------|--------------------------------------------------|
|
||||
|bearings |`{bearing};{bearing}[;{bearing} ...]` |Limits the search to segments with given bearing in degrees towards true north in clockwise direction. |
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. |
|
||||
|hints |`{hint};{hint}[;{hint} ...]` |Hint to derive position in street network. |
|
||||
|
||||
Where the elements follow the following format:
|
||||
|
||||
| Element | Values |
|
||||
|------------|--------------------------------------------------------|
|
||||
|bearing |`{value},{range}` `integer 0 .. 360,integer 0 .. 180` |
|
||||
|radius |`double >= 0` or `unlimited` (default) |
|
||||
|hint |Base64 `string` |
|
||||
|
||||
#### Examples
|
||||
|
||||
Query on Berlin with three coordinates:
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false
|
||||
```
|
||||
|
||||
Using polyline:
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
Every response object has a `code` field.
|
||||
|
||||
```json
|
||||
{
|
||||
"code": {code},
|
||||
"message": {message}
|
||||
}
|
||||
```
|
||||
|
||||
Where `code` is on one of the strings below or service dependent:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|----------------------------------------------------------------------------------|
|
||||
| `Ok` | Request could be processed as expected. |
|
||||
| `InvalidUrl` | URL string is invalid. |
|
||||
| `InvalidService` | Service name is invalid. |
|
||||
| `InvalidVersion` | Version is not found. |
|
||||
| `InvalidOptions` | Options are invalid. |
|
||||
| `NoSegment` | One of the supplied input coordinates could not snap to street segment. |
|
||||
| `TooBig` | The request size violates one of the service specific request size restrictions. |
|
||||
|
||||
`message` is a **optional** human-readable error message. All other status types are service dependent.
|
||||
|
||||
In case of an error the HTTP status code will be `400`. Otherwise the HTTP status code will be `200` and `code` will be `Ok`.
|
||||
|
||||
## Service `nearest`
|
||||
|
||||
Snaps a coordinate to the street network and returns the nearest n matches.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/nearest/v1/{profile}/{coordinates}.json?number={number}
|
||||
```
|
||||
|
||||
Where `coordinates` only supports a single `{longitude},{latitude}` entry.
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------|----------------------------------------------------|
|
||||
|number |`integer >= 1` (default `1`) |Number of nearest segments that should be returned. |
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
|
||||
- `distance`: Distance in meters to the supplied input coordinate.
|
||||
|
||||
### Examples
|
||||
|
||||
Querying nearest three snapped locations of `13.388860,52.517037` with a bearing between `20° - 340°`.
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?number=3&bearings=0,20
|
||||
```
|
||||
|
||||
## Service `route`
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|geojson}&overview={full|simplified|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------------------|-------------------------------------------------------------------------------|
|
||||
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|
||||
|steps |`true`, `false` (default) |Return route steps for each route leg |
|
||||
|annotate |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|continue_straight |`default` (default), `true`, `false`|Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. |
|
||||
|
||||
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints`: Array of `Waypoint` objects representing all waypoints in order:
|
||||
- `routes`: An array of `Route` objects, ordered by descending recommendation rank.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|-----------------|
|
||||
| `NoRoute` | No route found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
## Service `table`
|
||||
### Request
|
||||
```
|
||||
http://{server}/table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]`
|
||||
```
|
||||
|
||||
This computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
|
||||
|
||||
### Coordinates
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|--------------------------------------------------|---------------------------------------------|
|
||||
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|
||||
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|
||||
|
||||
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
|
||||
to number of input locations;
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
sources=0;5;7&destinations=5;1;4;2;3;6
|
||||
```
|
||||
|
||||
|Element |Values |
|
||||
|------------|-----------------------------|
|
||||
|index |`0 <= integer < #locations` |
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
|
||||
the i-th waypoint to the j-th waypoint. Values are given in seconds.
|
||||
- `sources` array of `Waypoint` objects describing all sources in order
|
||||
- `destinations` array of `Waypoint` objects describing all destinations in order
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|-----------------|
|
||||
| `NoTable` | No route found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
#### Examples
|
||||
|
||||
Returns a `3x3` matrix:
|
||||
```
|
||||
http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219
|
||||
```
|
||||
|
||||
Returns a `1x3` matrix:
|
||||
```
|
||||
http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0
|
||||
```
|
||||
|
||||
Returns a asymmetric 3x2 matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
|
||||
```
|
||||
http://router.project-osrm.org/table/v1/driving/qikdcB}~dpXkkHz?sources=0;1;3&destinations=2;4
|
||||
```
|
||||
|
||||
## Service `match`
|
||||
|
||||
Map matching matches given GPS points to the road network in the most plausible way.
|
||||
Please note the request might result multiple sub-traces. Large jumps in the timestamps (>60s) or improbable transitions lead to trace splits if a complete matching could not be found.
|
||||
The algorithm might not be able to match all points. Outliers are removed if they can not be matched successfully.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/match/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|
||||
|steps |`true`, `false` (default) |Return route steps for each route |
|
||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
||||
|annotate |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamp of the input location. |
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
||||
|
||||
|Parameter |Values |
|
||||
|------------|------------------------------|
|
||||
|timestamp |`integer` UNIX-like timestamp |
|
||||
|radius |`double >= 0` (default 5m) |
|
||||
|
||||
### Response
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `tracepoints`: Array of `Ẁaypoint` objects representing all points of the trace in order.
|
||||
If the trace point was ommited by map matching because it is an outlier, the entry will be `null`.
|
||||
Each `Waypoint` object has the following additional properties:
|
||||
- `matchings_index`: Index to the `Route` object in `matchings` the sub-trace was matched to.
|
||||
- `waypoint_index`: Index of the waypoint inside the matched route.
|
||||
- `matchings`: An array of `Route` objects that assemble the trace. Each `Route` object has the following additional properties:
|
||||
- `confidence`: Confidence of the matching. `float` value between 0 and 1. 1 is very confident that the matching is correct.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|---------------------|
|
||||
| `NoMatch` | No matchings found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
## Service `trip`
|
||||
|
||||
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm).
|
||||
The returned path does not have to be the shortest path, as TSP is NP-hard it is only an approximation.
|
||||
Note that if the input coordinates can not be joined by a single trip (e.g. the coordinates are on several disconnected islands)
|
||||
multiple trips for each connected component are returned.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/trip/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------------------------|---------------------------------------------------------------------------|
|
||||
|steps |`true`, `false` (default) |Return route instructions for each trip |
|
||||
|annotate |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints`: Array of `Waypoint` objects representing all waypoints in input order. Each `Waypoint` object has the following additional properties:
|
||||
- `trips_index`: Index to `trips` of the sub-trip the point was matched to.
|
||||
- `waypoint_index`: Index of the point in the trip.
|
||||
- `trips`: An array of `Route` objects that assemble the trace.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|---------------------|
|
||||
| `NoTrips` | No trips found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
## Result objects
|
||||
|
||||
### Route
|
||||
|
||||
Represents a route through (potentially multiple) waypoints.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance traveled by the route, in `float` meters.
|
||||
- `duration`: The estimated travel time, in `float` number of seconds.
|
||||
- `geometry`: The whole geometry of the route value depending on `overview` parameter, format depending on the `geometries` parameter. See `RouteStep`'s `geometry` field for a parameter documentation.
|
||||
|
||||
| overview | Description |
|
||||
|------------|-----------------------------|
|
||||
| simplified | Geometry is simplified according to the highest zoom level it can still be displayed on full. |
|
||||
| full | Geometry is not simplified. |
|
||||
| false | Geometry is not added. |
|
||||
|
||||
- `legs`: The legs between the given waypoints, an array of `RouteLeg` objects.
|
||||
|
||||
#### Example
|
||||
|
||||
Three input coordinates, `geometry=geojson`, `steps=false`:
|
||||
|
||||
```json
|
||||
{
|
||||
"distance": 90.0,
|
||||
"duration": 300.0,
|
||||
"geometry": {"type": "LineString", "coordinates": [[120., 10.], [120.1, 10.], [120.2, 10.], [120.3, 10.]]},
|
||||
"legs": [
|
||||
{
|
||||
"distance": 30.0,
|
||||
"duration": 100.0,
|
||||
"steps": []
|
||||
},
|
||||
{
|
||||
"distance": 60.0,
|
||||
"duration": 200.0,
|
||||
"steps": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### RouteLeg
|
||||
|
||||
Represents a route between two waypoints.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance traveled by this route leg, in `float` meters.
|
||||
- `duration`: The estimated travel time, in `float` number of seconds.
|
||||
- `summary`: Summary of the route taken as `string`. Depends on the `steps` parameter:
|
||||
|
||||
| steps | |
|
||||
|--------------|-----------------------------------------------------------------------|
|
||||
| true | Names of the two major roads used. Can be empty if route is too short.|
|
||||
| false | empty `string` |
|
||||
|
||||
- `steps`: Depends on the `steps` parameter.
|
||||
|
||||
| steps | |
|
||||
|--------------|-----------------------------------------------------------------------|
|
||||
| true | array of `RouteStep` objects describing the turn-by-turn instructions |
|
||||
| false | empty array |
|
||||
|
||||
- `annotation`: Additional details about each coordinate along the route geometry:
|
||||
|
||||
| annotate | |
|
||||
|--------------|-----------------------------------------------------------------------|
|
||||
| true | returns distance and durations of each coordinate along the route |
|
||||
| false | will not exist |
|
||||
|
||||
#### Example
|
||||
|
||||
With `steps=false` and `annotate=true`:
|
||||
|
||||
```json
|
||||
{
|
||||
"distance": 30.0,
|
||||
"duration": 100.0,
|
||||
"steps": []
|
||||
"annotation": {
|
||||
"distance": [5,5,10,5,5],
|
||||
"duration": [15,15,40,15,15]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### RouteStep
|
||||
|
||||
A step consists of a maneuver such as a turn or merge, followed
|
||||
by a distance of travel along a single way to the subsequent
|
||||
step.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance of travel from the maneuver to the subsequent step, in `float` meters.
|
||||
- `duration`: The estimated travel time, in `float` number of seconds.
|
||||
- `geometry`: The unsimplified geometry of the route segment, depending on the `geometries` parameter.
|
||||
|
||||
| geometries | |
|
||||
|------------|--------------------------------------------------------------------|
|
||||
| polyline | [polyline](https://www.npmjs.com/package/polyline) with precision 5 in [latitude,longitude] encoding |
|
||||
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
|
||||
|
||||
- `name`: The name of the way along which travel proceeds.
|
||||
- `mode`: A string signifying the mode of transportation.
|
||||
- `maneuver`: A `StepManeuver` object representing the maneuver.
|
||||
- `intersections`: A list of `Intersections` that are passed along the segment, the very first belonging to the StepManeuver
|
||||
|
||||
#### Example
|
||||
|
||||
```
|
||||
{
|
||||
"distance":152.3,
|
||||
"duration":15.6,
|
||||
"name":"Lortzingstraße",
|
||||
"maneuver":{
|
||||
"type":"depart",
|
||||
"modifier":"left"
|
||||
},
|
||||
"geometry":"{lu_IypwpAVrAvAdI",
|
||||
"mode":"driving",
|
||||
"intersections":[
|
||||
{"location":[13.39677,52.54366],
|
||||
"out":1,
|
||||
"bearings":[66,246],
|
||||
"entry":["true","true"]},
|
||||
{"location":[13.394718,52.543096],
|
||||
"in":0,
|
||||
"out":2,
|
||||
"bearings":[60,150,240,330],
|
||||
"entry":["false","true","true","true"]
|
||||
}
|
||||
]}
|
||||
```
|
||||
|
||||
### StepManeuver
|
||||
|
||||
#### Properties
|
||||
|
||||
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
|
||||
- `bearing_before`: The clockwise angle from true north to the
|
||||
direction of travel immediately before the maneuver.
|
||||
- `bearing_after`: The clockwise angle from true north to the
|
||||
direction of travel immediately after the maneuver.
|
||||
- `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change**
|
||||
Types unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed.
|
||||
|
||||
| `type` | Description |
|
||||
|-------------------|--------------------------------------------------------------|
|
||||
| turn | a basic turn into direction of the `modifier` |
|
||||
| new name | no turn is taken, but the road name changes. The Road can take a turn itself, following `modifier` |
|
||||
| depart | indicates the departure of the leg |
|
||||
| arrive | indicates the destination of the leg |
|
||||
| merge | merge onto a street (e.g. getting on the highway from a ramp, the `modifier specifies the direction of the merge`) |
|
||||
| ramp | **Deprecated**. Replaced by `on_ramp` and `off_ramp`. |
|
||||
| on ramp | take a ramp to enter a highway (direction given my `modifier`) |
|
||||
| off ramp | take a ramp to exit a highway (direction given my `modifier`) |
|
||||
| fork | take the left/right side at a fork depending on `modifier` |
|
||||
| end of road | road ends in a T intersection turn in direction of `modifier`|
|
||||
| continue | Turn in direction of `modifier` to stay on the same road |
|
||||
| roundabout | traverse roundabout, has additional field `exit` with NR if the roundabout is left. `the modifier specifies the direction of entering the roundabout` |
|
||||
| rotary | a larger version of a roundabout, can offer `rotary_name` in addition to the `exit` parameter. |
|
||||
| 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. If the road takes a turn itself, the `modifier` describes the direction |
|
||||
|
||||
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.
|
||||
|
||||
|
||||
- `modifier` An optional `string` indicating the direction change of the maneuver.
|
||||
|
||||
| `modifier` | Description |
|
||||
|-------------------|-------------------------------------------|
|
||||
| uturn | indicates reversal of direction |
|
||||
| sharp right | a sharp right turn |
|
||||
| right | a normal turn to the right |
|
||||
| slight right | a slight turn to the right |
|
||||
| straight | no relevant change in direction |
|
||||
| slight left | a slight turn to the left |
|
||||
| left | a normal turn to the left |
|
||||
| sharp left | a sharp turn to the left |
|
||||
|
||||
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
|
||||
|
||||
The meaning depends on the `type` field.
|
||||
|
||||
| `type` | Description |
|
||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `turn` | `modifier` indicates the change in direction accomplished through the turn |
|
||||
| `depart`/`arrive` | `modifier` indicates the position of departure point and arrival point in relation to the current direction of travel |
|
||||
|
||||
|
||||
- `exit` An optional `integer` indicating number of the exit to take. The field exists for the following `type` field:
|
||||
|
||||
| `type` | Description |
|
||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `roundabout` | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout. |
|
||||
| else | Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` |
|
||||
|
||||
|
||||
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
|
||||
|
||||
### Intersections
|
||||
|
||||
An intersection gives a full representation of any cross-way the path passes bay. For every step, the very first intersection (`intersections[0]`) corresponds to the
|
||||
location of the StepManeuver. Further intersections are listed for every cross-way until the next turn instruction.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
|
||||
- `bearings`: A list of bearing values (e.g. [0,90,180,270]) that are available at the intersection. The bearings describe all available roads at the intersection.
|
||||
- `entry`: A list of entry flags, corresponding in a 1:1 relationship to the bearings. A value of `true` indicates that the respective road could be entered on a valid route.
|
||||
`false` indicates that the turn onto the respective road would violate a restriction.
|
||||
- `in`: index into bearings/entry array. Used to calculate the bearing just before the turn. Namely, the clockwise angle from true north to the
|
||||
direction of travel immediately before the maneuver/passing the intersection. Bearings are given relative to the intersection. To get the bearing
|
||||
in the direction of driving, the bearing has to be rotated by a value of 180. The value is not supplied for `depart` maneuvers.
|
||||
- `out`: index into the bearings/entry array. Used to extract the bearing just after the turn. Namely, The clockwise angle from true north to the
|
||||
direction of travel immediately after the maneuver/passing the intersection. The value is not supplied for `arrive` maneuvers.
|
||||
|
||||
#### Example
|
||||
```
|
||||
{
|
||||
"location":[13.394718,52.543096],
|
||||
"in":0,
|
||||
"out":2,
|
||||
"bearings":[60,150,240,330],
|
||||
"entry":["false","true","true","true"]
|
||||
}
|
||||
```
|
||||
|
||||
### Waypoint
|
||||
|
||||
Object used to describe waypoint on a route.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `name` Name of the street the coordinate snapped to
|
||||
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
|
||||
- `hint` Unique internal identifier of the segment (ephemeral, not constant over data updates)
|
||||
This can be used on subsequent request to significantly speed up the query and to connect multiple services.
|
||||
E.g. you can use the `hint` value obtained by the `nearest` query as `hint` values for `route` inputs.
|
||||
|
||||
## Service `tile`
|
||||
|
||||
This generates [Mapbox Vector Tiles](https://www.mapbox.com/developers/vector-tiles/) that can be viewed with a vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can be used to examine the routing graph. The tiles are generated directly from the data in-memory, so are in sync with actual routing results, and let you examine which roads are actually routable, and what weights they have applied.
|
||||
|
||||
### Request
|
||||
```
|
||||
http://{server}/tile/v1/{profile}/tile({x},{y},{zoom}).mvt
|
||||
```
|
||||
|
||||
The `x`, `y`, and `zoom` values are the same as described at https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames, and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
|
||||
|
||||
### Response
|
||||
|
||||
The response object is either a binary encoded blob with a `Content-Type` of `application/x-protobuf`, or a `404` error. Note that OSRM is hard-coded to only return tiles from zoom level 12 and higher (to avoid accidentally returning extremely large vector tiles).
|
||||
|
||||
Vector tiles contain just a single layer named `speeds`. Within that layer, features can have `speed` (int) and `is_small` (boolean) attributes.
|
||||
@@ -0,0 +1,26 @@
|
||||
OSRM can be used as a library (libosrm) via C++ instead of using it through the HTTP interface and `osrm-routed`. This allows for fine-tuning OSRM and has much less overhead. Here is a quick introduction into how to use `libosrm` in the upcoming v5 release.
|
||||
|
||||
Take a look at the example code that lives in the [example directory](https://github.com/Project-OSRM/osrm-backend/tree/master/example). Here is all you ever wanted to know about `libosrm`, that is a short description of what the types do and where to find documentation on it:
|
||||
|
||||
- [`EngineConfig`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/engine_config.hpp) - for initializing an OSRM instance we can configure certain properties and constraints. E.g. the storage config is the base path such as `france.osm.osrm` from which we derive and load `france.osm.osrm.*` auxiliary files. This also lets you set constraints such as the maximum number of locations allowed for specific services.
|
||||
|
||||
- [`OSRM`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/osrm/osrm.hpp) - this is the main Routing Machine type with functions such as `Route` and `Table`. You initialize it with a `EngineConfig`. It does all the heavy lifting for you. Each function takes its own parameters, e.g. the `Route` function takes `RouteParameters`, and a out-reference to a JSON result that gets filled. The return value is a `Status`, indicating error or success.
|
||||
|
||||
- [`Status`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/status.hpp) - this is a type wrapping `Error` or `Ok` for indicating error or success, respectively.
|
||||
|
||||
- [`TableParameters`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/table_parameters.hpp) - this is an example of parameter types the Routing Machine functions expect. In this case `Table` expects its own parameters as `TableParameters`. You can see it wrapping two vectors, sources and destinations --- these are indices into your coordinates for the table service to construct a matrix from (empty sources or destinations means: use all of them). If you ask yourself where coordinates come from, you can see `TableParameters` inheriting from `BaseParameters`.
|
||||
|
||||
- [`BaseParameter`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/base_parameters.hpp) - this most importantly holds coordinates (and a few other optional properties that you don't need for basic usage); the specific parameter types inherit from `BaseParameters` to get these member attributes. That means your `TableParameters` type has `coordinates`, `sources` and `destination` member attributes (and a few other that we ignore for now).
|
||||
|
||||
- [`Coordinate`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/coordinate.hpp) - this is a wrapper around a (longitude, latitude) pair. We really don't care about (lon,lat) vs (lat, lon) but we don't want you to accidentally mix them up, so both latitude and longitude are strictly typed wrappers around integers (fixed notation such as `13423240`) and floating points (floating notation such as `13.42324`).
|
||||
|
||||
- [Parameters for other services](https://github.com/Project-OSRM/osrm-backend/tree/master/include/engine/api) - here are all other `*Parameters` you need for other Routing Machine services.
|
||||
|
||||
- [JSON](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/json_container.hpp) - this is a sum type resembling JSON. The Routing Machine service functions take a out-ref to a JSON result and fill it accordingly. It is currently implemented using [mapbox/variant](https://github.com/mapbox/variant) which is similar to [Boost.Variant](http://www.boost.org/doc/libs/1_55_0/doc/html/variant.html) (Boost documentation is great). There are two ways to work with this sum type: either provide a visitor that acts on each type on visitation or use the `get` function in case you're sure about the structure. The JSON structure is written down in the [[v5 server API|Server-API-v5,-current]].
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
To summarize:
|
||||
- create an `OSRM` instance initialized with a `EngineConfig`
|
||||
- call the service function on the `OSRM` object providing service specific `*Parameters`
|
||||
- check the return code and use the JSON result
|
||||
@@ -0,0 +1,34 @@
|
||||
OSRM supports "profiles". Configurations representing different routing behaviours for (typically) different transport modes. A profile describes whether or not we route along a particular type of way, or over a particular node in the OpenStreetMap data, and also how quickly we'll be travelling when we do. This feeds into the way the routing graph is created and thus influences the output routes.
|
||||
|
||||
## Available profiles
|
||||
|
||||
Out-of-the-box OSRM comes with several different profiles, including car, bicycle and foot.
|
||||
|
||||
Profile configuration files have a 'lua' extension, and are found under the 'profiles' subdirectory.
|
||||
Alternatively commands will take a lua profile specified with an explicit -p param, for example:
|
||||
|
||||
`osrm-extract -p ../profiles/car.lua planet-latest.osm.pbf`
|
||||
|
||||
And then **you will need to extract and contract again** (A change to the profile will typically affect the extract step as well as the contract step. See [Processing Flow](https://github.com/Project-OSRM/osrm-backend/wiki/Processing-Flow))
|
||||
|
||||
## lua scripts?
|
||||
|
||||
Profiles are not just configuration files. They are scripts written in the "lua" scripting language ( http://www.lua.org ) The reason for this, is that OpenStreetMap data is not sufficiently straightforward, to simply define tag mappings. Lua scripting offers a powerful way of coping with the complexity of different node,way,relation,tag combinations found within OpenStreetMap data.
|
||||
|
||||
## Basic structure of a profile
|
||||
|
||||
You can understand these lua scripts enough to make interesting modifications, without needing to get to grips with how they work completely.
|
||||
|
||||
Towards the top of the file, a profile (such as [car.lua](../profiles/car.lua)) will typically define various configurations as global variables. A lot of these are look-up hashes of one sort or another.
|
||||
|
||||
As you scroll down the file you'll see local variables, and then local functions, and finally...
|
||||
|
||||
`way_function` and `node_function` are the important functions which are called when extracting OpenStreetMap data with `osrm-extract`.
|
||||
|
||||
## way_function
|
||||
|
||||
Given an OpenStreetMap way, the 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 to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
|
||||
|
||||
All other calculations stem from that, including the returned timings in driving directions, but also, less directly, it feeds into the actual routing decisions the engine will take (a way with a slow traversal speed, may be less favoured than a way with fast traversal speed, but it depends how long it is, and... what it connects to in the rest of the network graph)
|
||||
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the way_function. Instead a way_function will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Releasing a new OSRM version
|
||||
|
||||
Do decide if this is a major or minor version bump use: http://semver.org/
|
||||
|
||||
What we guarantee on major version changes:
|
||||
|
||||
- Breaking changes will be in the changelog
|
||||
- If we break an HTTP API we bump the version
|
||||
|
||||
What we guarantee on minor version changes:
|
||||
|
||||
- HTTP API does not include breaking changes
|
||||
- C++ library API does not include breaking changes
|
||||
- node-osrm API does not include breaking changes
|
||||
|
||||
What we DO NOT guarantee on minor version changes:
|
||||
|
||||
- file format comp ability. Breakage will be listed in the changelog.
|
||||
- new turn types and fields may be introduced. How to handle this see [the HTTP API docs](http.md).
|
||||
|
||||
What we guarantee on patch version changes:
|
||||
|
||||
- HTTP API does not include breaking changes
|
||||
- C++ library API does not include breaking changes
|
||||
- node-osrm API does not include breaking changes
|
||||
- full file format compatibility
|
||||
|
||||
## Major or Minor release x.y
|
||||
|
||||
1. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
|
||||
2. Make sure `CHANGELOG.md` is up to date.
|
||||
3. Make sure the OSRM version in `CMakeLists.txt` is up to date
|
||||
4. Use an annotated tag to mark the release: `git tag vx.y.0 -a` Body of the tag description should be the changelog entries.
|
||||
5. Push tags and commits: `git push; git push --tags`
|
||||
6. Branch of the `vx.y.0` tag to create a release branch `x.y`:
|
||||
`git branch x.y. vx.y.0; git push -u x.y:origin/x.y`
|
||||
7. Modify `.travis.yml` to allow builds for the `x.y` branch.
|
||||
8. Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
|
||||
|
||||
## Patch release x.y.z
|
||||
|
||||
1. Check out the appropriate release branch x.y
|
||||
2. Make sure all fixes are listed in the changelog and included in the branch
|
||||
3. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
|
||||
4. Make sure the OSRM version in `CMakeLists.txt` is up to date
|
||||
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
|
||||
6. Push tags and commits: `git push; git push --tags`
|
||||
7. Proceede with the `node-osrm` release as outlined in the repository.
|
||||
8. Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
|
||||
|
||||
@@ -19,14 +19,14 @@ else()
|
||||
message(WARNING "Building on a 32 bit system is unsupported")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND MSVC_VERSION LESS 1800)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
||||
if(WIN32 AND MSVC_VERSION LESS 1900)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
|
||||
endif()
|
||||
|
||||
add_executable(osrm-example example.cpp)
|
||||
|
||||
find_package(LibOSRM REQUIRED)
|
||||
find_package(Boost 1.49.0 COMPONENTS filesystem system thread REQUIRED)
|
||||
find_package(Boost 1.49.0 COMPONENTS filesystem system thread iostreams REQUIRED)
|
||||
|
||||
target_link_libraries(osrm-example ${LibOSRM_LIBRARIES} ${Boost_LIBRARIES})
|
||||
include_directories(SYSTEM ${LibOSRM_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
|
||||
|
||||
@@ -4,7 +4,7 @@ Feature: Bike - Squares and other areas
|
||||
Background:
|
||||
Given the profile "bicycle"
|
||||
|
||||
@square @mokob @2154
|
||||
@square
|
||||
Scenario: Bike - Route along edge of a squares
|
||||
Given the node map
|
||||
| x | |
|
||||
@@ -50,7 +50,7 @@ Feature: Bike - Squares and other areas
|
||||
| d | a | xa,xa |
|
||||
| a | d | xa,xa |
|
||||
|
||||
@parking @mokob @2154
|
||||
@parking
|
||||
Scenario: Bike - parking areas
|
||||
Given the node map
|
||||
| e | | | f |
|
||||
@@ -78,7 +78,7 @@ Feature: Bike - Squares and other areas
|
||||
| a | d | abcda,abcda |
|
||||
|
||||
|
||||
@train @platform @mokob @2154
|
||||
@train @platform
|
||||
Scenario: Bike - railway platforms
|
||||
Given the node map
|
||||
| x | a | b | y |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@routing @bicycle @bridge
|
||||
Feature: Bicycle - Handle movable bridge
|
||||
Feature: Bicycle - Handle cycling
|
||||
|
||||
Background:
|
||||
Given the profile "bicycle"
|
||||
@@ -18,14 +18,14 @@ Feature: Bicycle - Handle movable bridge
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes |
|
||||
| a | g | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling |
|
||||
| b | f | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling |
|
||||
| e | c | cde,cde | movable bridge,movable bridge |
|
||||
| e | b | cde,abc,abc | movable bridge,cycling,cycling |
|
||||
| e | a | cde,abc,abc | movable bridge,cycling,cycling |
|
||||
| c | e | cde,cde | movable bridge,movable bridge |
|
||||
| c | f | cde,efg,efg | movable bridge,cycling,cycling |
|
||||
| c | g | cde,efg,efg | movable bridge,cycling,cycling |
|
||||
| a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
|
||||
| b | f | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
|
||||
| e | c | cde,cde | cycling,cycling |
|
||||
| e | b | cde,abc,abc | cycling,cycling,cycling |
|
||||
| e | a | cde,abc,abc | cycling,cycling,cycling |
|
||||
| c | e | cde,cde | cycling,cycling |
|
||||
| c | f | cde,efg,efg | cycling,cycling,cycling |
|
||||
| c | g | cde,efg,efg | cycling,cycling,cycling |
|
||||
|
||||
Scenario: Bicycle - Properly handle durations
|
||||
Given the node map
|
||||
@@ -41,7 +41,7 @@ Feature: Bicycle - Handle movable bridge
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes | speed |
|
||||
| a | g | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling | 5 km/h |
|
||||
| b | f | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling | 4 km/h |
|
||||
| c | e | cde,cde | movable bridge,movable bridge | 2 km/h |
|
||||
| e | c | cde,cde | movable bridge,movable bridge | 2 km/h |
|
||||
| a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 5 km/h |
|
||||
| b | f | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 4 km/h |
|
||||
| c | e | cde,cde | cycling,cycling | 2 km/h |
|
||||
| e | c | cde,cde | cycling,cycling | 2 km/h |
|
||||
|
||||
@@ -10,13 +10,13 @@ Feature: Bike - Street names in instructions
|
||||
| | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | My Way |
|
||||
| bc | Your Way |
|
||||
| nodes | name | ref |
|
||||
| ab | My Way | A6 |
|
||||
| bc | Your Way | A7 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | c | My Way,Your Way,Your Way |
|
||||
| from | to | route |
|
||||
| a | c | My Way (A6),Your Way (A7),Your Way (A7) |
|
||||
|
||||
@unnamed
|
||||
Scenario: Bike - Use way type to describe unnamed ways
|
||||
|
||||
@@ -14,7 +14,7 @@ Feature: Bike - Way ref
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | b | Utopia Drive / E7,Utopia Drive / E7 |
|
||||
| a | b | Utopia Drive (E7),Utopia Drive (E7) |
|
||||
|
||||
Scenario: Bike - Way with only ref
|
||||
Given the node map
|
||||
|
||||
@@ -34,7 +34,6 @@ OSRM will use 4/5 of the projected free-flow speed.
|
||||
| a | b | ab,ab | 47 km/h +- 1 |
|
||||
| b | c | bc,bc | 47 km/h +- 1 |
|
||||
|
||||
@mokob @2162
|
||||
Scenario: Car - Advisory speed overwrites backwards maxspeed
|
||||
Given the node map
|
||||
| a | b | c |
|
||||
@@ -49,7 +48,6 @@ OSRM will use 4/5 of the projected free-flow speed.
|
||||
| b | a | ab,ab | 47 km/h +- 1 |
|
||||
| c | b | bc,bc | 47 km/h +- 1 |
|
||||
|
||||
@mokob @2162 @deleteme
|
||||
Scenario: Car - Advisory speed overwrites backwards maxspeed
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
@@ -65,7 +63,6 @@ OSRM will use 4/5 of the projected free-flow speed.
|
||||
| c | b | bc,bc | 47 km/h +- 1 |
|
||||
| d | c | cd,cd | 47 km/h +- 1 |
|
||||
|
||||
@mokob @2162
|
||||
Scenario: Car - Directional advisory speeds play nice with eachother
|
||||
Given the node map
|
||||
| a | b | c |
|
||||
|
||||
+13
-13
@@ -1,5 +1,5 @@
|
||||
@routing @car @bridge
|
||||
Feature: Car - Handle movable bridge
|
||||
Feature: Car - Handle driving
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
@@ -18,14 +18,14 @@ Feature: Car - Handle movable bridge
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes |
|
||||
| a | g | abc,cde,efg,efg | driving,movable bridge,driving,driving |
|
||||
| b | f | abc,cde,efg,efg | driving,movable bridge,driving,driving |
|
||||
| e | c | cde,cde | movable bridge,movable bridge |
|
||||
| e | b | cde,abc,abc | movable bridge,driving,driving |
|
||||
| e | a | cde,abc,abc | movable bridge,driving,driving |
|
||||
| c | e | cde,cde | movable bridge,movable bridge |
|
||||
| c | f | cde,efg,efg | movable bridge,driving,driving |
|
||||
| c | g | cde,efg,efg | movable bridge,driving,driving |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving |
|
||||
| b | f | abc,cde,efg,efg | driving,driving,driving,driving |
|
||||
| e | c | cde,cde | driving,driving |
|
||||
| e | b | cde,abc,abc | driving,driving,driving |
|
||||
| e | a | cde,abc,abc | driving,driving,driving |
|
||||
| c | e | cde,cde | driving,driving |
|
||||
| c | f | cde,efg,efg | driving,driving,driving |
|
||||
| c | g | cde,efg,efg | driving,driving,driving |
|
||||
|
||||
Scenario: Car - Properly handle durations
|
||||
Given the node map
|
||||
@@ -41,7 +41,7 @@ Feature: Car - Handle movable bridge
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes | speed |
|
||||
| a | g | abc,cde,efg,efg | driving,movable bridge,driving,driving | 7 km/h |
|
||||
| b | f | abc,cde,efg,efg | driving,movable bridge,driving,driving | 5 km/h |
|
||||
| c | e | cde,cde | movable bridge,movable bridge | 2 km/h |
|
||||
| e | c | cde,cde | movable bridge,movable bridge | 2 km/h |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h |
|
||||
| b | f | abc,cde,efg,efg | driving,driving,driving,driving | 5 km/h |
|
||||
| c | e | cde,cde | driving,driving | 2 km/h |
|
||||
| e | c | cde,cde | driving,driving | 2 km/h |
|
||||
|
||||
@@ -31,7 +31,7 @@ Feature: Traffic - speeds
|
||||
4,1,27
|
||||
"""
|
||||
|
||||
Scenario: Weighting not based on raster sources
|
||||
Scenario: Weighting based on speed file
|
||||
Given the profile "testbot"
|
||||
Given the extract extra arguments "--generate-edge-lookup"
|
||||
Given the contract extra arguments "--segment-speed-file speeds.csv"
|
||||
@@ -0,0 +1,97 @@
|
||||
@routing @speed @traffic
|
||||
Feature: Traffic - turn penalties
|
||||
|
||||
Background: Evenly spaced grid with multiple intersections
|
||||
Given the node map
|
||||
| | a:1 | | b:2 | |
|
||||
| c:3 | d:4 | e:5 | f:6 | g:7 |
|
||||
| | h:8 | | i:9 | |
|
||||
| j:10 | k:11 | l:12 | m:13 | n:14 |
|
||||
| | o:15 | | p:16 | |
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ad | primary |
|
||||
| cd | primary |
|
||||
| de | primary |
|
||||
| dhk | primary |
|
||||
|
||||
| bf | primary |
|
||||
| ef | primary |
|
||||
| fg | primary |
|
||||
| fim | primary |
|
||||
|
||||
| jk | primary |
|
||||
| kl | primary |
|
||||
| ko | primary |
|
||||
|
||||
| lm | primary |
|
||||
| mn | primary |
|
||||
| mp | primary |
|
||||
And the profile "car"
|
||||
And the extract extra arguments "--generate-edge-lookup"
|
||||
|
||||
Scenario: Weighting not based on turn penalty file
|
||||
When I route I should get
|
||||
| from | to | route | speed | time |
|
||||
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
||||
# straight
|
||||
| i | g | fim,fg,fg | 59 km/h | 12s +-1 |
|
||||
# right
|
||||
| a | e | ad,de,de | 57 km/h | 12.5s +-1 |
|
||||
# left
|
||||
| c | g | cd,de,ef,fg,fg | 63 km/h | 23s +-1 |
|
||||
# double straight
|
||||
| p | g | mp,fim,fg,fg | 61 km/h | 23.5s +-1 |
|
||||
# straight-right
|
||||
| a | l | ad,dhk,kl,kl | 60 km/h | 24s +-1 |
|
||||
# straight-left
|
||||
| l | e | kl,dhk,de,de | 59 km/h | 24.5s +-1 |
|
||||
# double right
|
||||
| g | n | fg,fim,mn,mn | 57 km/h | 25s +-1 |
|
||||
# double left
|
||||
|
||||
Scenario: Weighting based on turn penalty file
|
||||
Given the turn penalty file
|
||||
"""
|
||||
9,6,7,1.8
|
||||
9,13,14,24.5
|
||||
8,4,3,26
|
||||
12,11,8,9
|
||||
8,11,12,13
|
||||
1,4,5,-0.2
|
||||
"""
|
||||
And the contract extra arguments "--turn-penalty-file penalties.csv"
|
||||
When I route I should get
|
||||
| from | to | route | speed | time |
|
||||
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
||||
# straight
|
||||
| i | g | fim,fg,fg | 55 km/h | 13s +-1 |
|
||||
# right - ifg penalty
|
||||
| a | e | ad,de,de | 64 km/h | 11s +-1 |
|
||||
# left - faster because of negative ade penalty
|
||||
| c | g | cd,de,ef,fg,fg | 63 km/h | 23s +-1 |
|
||||
# double straight
|
||||
| p | g | mp,fim,fg,fg | 59 km/h | 24.5s +-1 |
|
||||
# straight-right - ifg penalty
|
||||
| a | l | ad,de,ef,fim,lm,lm | 61 km/h | 35.5s +-1 |
|
||||
# was straight-left - forced around by hkl penalty
|
||||
| l | e | lm,fim,ef,ef | 57 km/h | 25s +-1 |
|
||||
# double right - forced left by lkh penalty
|
||||
| g | n | fg,fim,mn,mn | 30 km/h | 47.5s +-1 |
|
||||
# double left - imn penalty
|
||||
| j | c | jk,kl,lm,fim,ef,de,cd,cd | 60 km/h | 48s +-1 |
|
||||
# double left - hdc penalty ever so slightly higher than imn; forces all the way around
|
||||
|
||||
Scenario: Too-negative penalty clamps, but does not fail
|
||||
Given the contract extra arguments "--turn-penalty-file penalties.csv"
|
||||
And the profile "testbot"
|
||||
And the turn penalty file
|
||||
"""
|
||||
1,4,5,-10
|
||||
"""
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
| a | d | ad,ad | 10s +-1 |
|
||||
| a | e | ad,de,de | 10s +-1 |
|
||||
| b | f | bf,bf | 10s +-1 |
|
||||
| b | g | bf,fg,fg | 20s +-1 |
|
||||
@@ -10,13 +10,13 @@ Feature: Foot - Street names in instructions
|
||||
| | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | My Way |
|
||||
| bc | Your Way |
|
||||
| nodes | name | ref |
|
||||
| ab | My Way | A6 |
|
||||
| bc | Your Way | B7 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | c | My Way,Your Way,Your Way |
|
||||
| from | to | route |
|
||||
| a | c | My Way (A6),Your Way (B7),Your Way (B7) |
|
||||
|
||||
@unnamed
|
||||
Scenario: Foot - Use way type to describe unnamed ways
|
||||
|
||||
@@ -14,7 +14,7 @@ Feature: Foot - Way ref
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | b | Utopia Drive / E7,Utopia Drive / E7 |
|
||||
| a | b | Utopia Drive (E7),Utopia Drive (E7) |
|
||||
|
||||
Scenario: Foot - Way with only ref
|
||||
Given the node map
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
@routing @car @bridge @tunnel @guidance
|
||||
Feature: Car - Guidance - Bridges and Tunnels
|
||||
Background:
|
||||
Given the profile "car"
|
||||
And a grid size of 100 meters
|
||||
|
||||
Scenario: Simple Bridge
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | bridge | name |
|
||||
| ab | primary | | Hauptstraße |
|
||||
| bc | primary | yes | Hauptstraßenbrücke |
|
||||
| cd | primary | | Hauptstraße |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | d | Hauptstraße,Hauptstraße | depart,arrive |
|
||||
|
||||
Scenario: Bridge with Immediate Turn
|
||||
Given the node map
|
||||
| | | | d |
|
||||
| a | | b | c |
|
||||
| | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | bridge | name |
|
||||
| ab | primary | | Hauptstraße |
|
||||
| bc | primary | yes | Hauptstraßenbrücke |
|
||||
| dce | primary | | Nebenstraße |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | d | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road left,arrive |
|
||||
| a | e | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road right,arrive |
|
||||
| e | a | Nebenstraße,Hauptstraßenbrücke,Hauptstraße | depart,turn left,arrive |
|
||||
| d | a | Nebenstraße,Hauptstraßenbrücke,Hauptstraße | depart,turn right,arrive |
|
||||
|
||||
Scenario: Bridge with Immediate Turn Front and Back
|
||||
Given the node map
|
||||
| f | | | d |
|
||||
| a | | b | c |
|
||||
| g | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | bridge | name |
|
||||
| ab | primary | | Hauptstraße |
|
||||
| bc | primary | yes | Hauptstraßenbrücke |
|
||||
| dce | primary | | Nebenstraße |
|
||||
| gaf | primary | | Anderestraße |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| f | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road left,arrive |
|
||||
| f | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road right,arrive |
|
||||
| g | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road left,arrive |
|
||||
| g | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road right,arrive |
|
||||
| e | f | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn left,end of road right,arrive |
|
||||
| e | g | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn left,end of road left,arrive |
|
||||
| d | f | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn right,end of road right,arrive |
|
||||
| d | g | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn right,end of road left,arrive |
|
||||
|
||||
Scenario: Simple Tunnel
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | tunnel | name |
|
||||
| ab | primary | | Hauptstraße |
|
||||
| bc | primary | yes | Hauptstraßentunnel |
|
||||
| cd | primary | | Hauptstraße |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | d | Hauptstraße,Hauptstraße | depart,arrive |
|
||||
|
||||
Scenario: Tunnel with Immediate Turn
|
||||
Given the node map
|
||||
| | | | d |
|
||||
| a | | b | c |
|
||||
| | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | tunnel | name |
|
||||
| ab | primary | | Hauptstraße |
|
||||
| bc | primary | yes | Hauptstraßentunnel |
|
||||
| dce | primary | | Nebenstraße |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | d | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road left,arrive |
|
||||
| a | e | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road right,arrive |
|
||||
| e | a | Nebenstraße,Hauptstraßentunnel,Hauptstraße | depart,turn left,arrive |
|
||||
| d | a | Nebenstraße,Hauptstraßentunnel,Hauptstraße | depart,turn right,arrive |
|
||||
|
||||
Scenario: Tunnel with Immediate Turn Front and Back
|
||||
Given the node map
|
||||
| f | | | d |
|
||||
| a | | b | c |
|
||||
| g | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | bridge | name |
|
||||
| ab | primary | | Hauptstraße |
|
||||
| bc | primary | yes | Hauptstraßentunnel |
|
||||
| dce | primary | | Nebenstraße |
|
||||
| gaf | primary | | Anderestraße |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| f | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road left,arrive |
|
||||
| f | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road right,arrive |
|
||||
| g | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road left,arrive |
|
||||
| g | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road right,arrive |
|
||||
| e | f | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn left,end of road right,arrive |
|
||||
| e | g | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn left,end of road left,arrive |
|
||||
| d | f | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn right,end of road right,arrive |
|
||||
| d | g | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn right,end of road left,arrive |
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
@routing @guidance @collapsing
|
||||
Feature: Collapse
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
Given a grid size of 20 meters
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Single Street
|
||||
Given the node map
|
||||
| | | i | l | | |
|
||||
| | | | | | |
|
||||
| d | | c | b | | a |
|
||||
| e | | f | g | | h |
|
||||
| | | | | | |
|
||||
| | | j | k | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | first | yes |
|
||||
| cd | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| fg | primary | first | yes |
|
||||
| gh | primary | first | yes |
|
||||
| ic | primary | second | yes |
|
||||
| bl | primary | second | yes |
|
||||
| kg | primary | second | yes |
|
||||
| fj | primary | second | yes |
|
||||
| cf | primary | first | yes |
|
||||
| gb | primary | first | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,l | first,second,second | depart,turn right,arrive |
|
||||
| a,d | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,h | first,first,first | depart,continue uturn,arrive |
|
||||
| e,j | first,second,second | depart,turn right,arrive |
|
||||
| e,h | first,first | depart,arrive |
|
||||
| e,l | first,second,second | depart,turn left,arrive |
|
||||
| e,d | first,first,first | depart,continue uturn,arrive |
|
||||
| k,h | second,first,first | depart,turn right,arrive |
|
||||
| k,l | second,second | depart,arrive |
|
||||
| k,d | second,first,first | depart,turn left,arrive |
|
||||
| k,j | second,second,second | depart,continue uturn,arrive |
|
||||
| i,d | second,first,first | depart,turn right,arrive |
|
||||
| i,j | second,second | depart,arrive |
|
||||
| i,h | second,first,first | depart,turn left,arrive |
|
||||
| i,l | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Correct Street
|
||||
Given the node map
|
||||
| | | i | l | | |
|
||||
| | | | | | |
|
||||
| d | | c | b | | a |
|
||||
| e | | f | g | | h |
|
||||
| | | | | | |
|
||||
| | | j | k | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | first | yes |
|
||||
| cd | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| fg | primary | first | yes |
|
||||
| gh | primary | first | yes |
|
||||
| ic | primary | second | yes |
|
||||
| bl | primary | second | yes |
|
||||
| kg | primary | second | yes |
|
||||
| fj | primary | second | yes |
|
||||
| cf | primary | second | yes |
|
||||
| gb | primary | second | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,l | first,second,second | depart,turn right,arrive |
|
||||
| a,d | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,h | first,first,first | depart,continue uturn,arrive |
|
||||
| e,j | first,second,second | depart,turn right,arrive |
|
||||
| e,h | first,first | depart,arrive |
|
||||
| e,l | first,second,second | depart,turn left,arrive |
|
||||
| e,d | first,first,first | depart,continue uturn,arrive |
|
||||
| k,h | second,first,first | depart,turn right,arrive |
|
||||
| k,l | second,second | depart,arrive |
|
||||
| k,d | second,first,first | depart,turn left,arrive |
|
||||
| k,j | second,second,second | depart,continue uturn,arrive |
|
||||
| i,d | second,first,first | depart,turn right,arrive |
|
||||
| i,j | second,second | depart,arrive |
|
||||
| i,h | second,first,first | depart,turn left,arrive |
|
||||
| i,l | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets
|
||||
Given the node map
|
||||
| | | i | l | | |
|
||||
| | | | | | |
|
||||
| d | | c | b | | a |
|
||||
| e | | f | g | | h |
|
||||
| | | | | | |
|
||||
| | | j | k | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | second | yes |
|
||||
| cd | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| fg | primary | first | yes |
|
||||
| gh | primary | first | yes |
|
||||
| ic | primary | second | yes |
|
||||
| bl | primary | second | yes |
|
||||
| kg | primary | second | yes |
|
||||
| fj | primary | second | yes |
|
||||
| cf | primary | second | yes |
|
||||
| gb | primary | first | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,l | first,second,second | depart,turn right,arrive |
|
||||
| a,d | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,h | first,first,first | depart,continue uturn,arrive |
|
||||
| e,j | first,second,second | depart,turn right,arrive |
|
||||
| e,h | first,first | depart,arrive |
|
||||
| e,l | first,second,second | depart,turn left,arrive |
|
||||
| e,d | first,first,first | depart,continue uturn,arrive |
|
||||
| k,h | second,first,first | depart,turn right,arrive |
|
||||
| k,l | second,second | depart,arrive |
|
||||
| k,d | second,first,first | depart,turn left,arrive |
|
||||
| k,j | second,second,second | depart,continue uturn,arrive |
|
||||
| i,d | second,first,first | depart,turn right,arrive |
|
||||
| i,j | second,second | depart,arrive |
|
||||
| i,h | second,first,first | depart,turn left,arrive |
|
||||
| i,l | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Partly Segregated Intersection, Two Segregated Roads
|
||||
Given the node map
|
||||
| | g | | h | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| c | | b | | a |
|
||||
| d | | e | | f |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | j | | i | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | first | yes |
|
||||
| de | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| be | primary | first | no |
|
||||
| gbh | primary | second | yes |
|
||||
| iej | primary | second | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,h | first,second,second | depart,turn right,arrive |
|
||||
| a,c | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,f | first,first,first | depart,continue uturn,arrive |
|
||||
| d,j | first,second,second | depart,turn right,arrive |
|
||||
| d,f | first,first | depart,arrive |
|
||||
| d,h | first,second,second | depart,turn left,arrive |
|
||||
| d,c | first,first,first | depart,continue uturn,arrive |
|
||||
| g,c | second,first,first | depart,turn right,arrive |
|
||||
| g,j | second,second | depart,arrive |
|
||||
| g,f | second,first,first | depart,turn left,arrive |
|
||||
| g,h | second,second,second | depart,continue uturn,arrive |
|
||||
| i,f | second,first,first | depart,turn right,arrive |
|
||||
| i,h | second,second | depart,arrive |
|
||||
| i,c | second,first,first | depart,turn left,arrive |
|
||||
| i,j | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second
|
||||
Given the node map
|
||||
| | g | | h | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| c | | b | | a |
|
||||
| d | | e | | f |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | j | | i | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | first | yes |
|
||||
| de | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| be | primary | second | no |
|
||||
| gbh | primary | second | yes |
|
||||
| iej | primary | second | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,h | first,second,second | depart,turn right,arrive |
|
||||
| a,c | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,f | first,first,first | depart,continue uturn,arrive |
|
||||
| d,j | first,second,second | depart,turn right,arrive |
|
||||
| d,f | first,first | depart,arrive |
|
||||
| d,h | first,second,second | depart,turn left,arrive |
|
||||
| d,c | first,first,first | depart,continue uturn,arrive |
|
||||
| g,c | second,first,first | depart,turn right,arrive |
|
||||
| g,j | second,second | depart,arrive |
|
||||
| g,f | second,first,first | depart,turn left,arrive |
|
||||
| g,h | second,second,second | depart,continue uturn,arrive |
|
||||
| i,f | second,first,first | depart,turn right,arrive |
|
||||
| i,h | second,second | depart,arrive |
|
||||
| i,c | second,first,first | depart,turn left,arrive |
|
||||
| i,j | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles
|
||||
Given the node map
|
||||
| | | i | l | | |
|
||||
| | | | | | a |
|
||||
| | | c | b | | h |
|
||||
| d | | f | g | | |
|
||||
| e | | | | | |
|
||||
| | | j | k | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | second | yes |
|
||||
| cd | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| fg | primary | first | yes |
|
||||
| gh | primary | first | yes |
|
||||
| ic | primary | second | yes |
|
||||
| bl | primary | second | yes |
|
||||
| kg | primary | second | yes |
|
||||
| fj | primary | second | yes |
|
||||
| cf | primary | second | yes |
|
||||
| gb | primary | first | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,l | first,second,second | depart,turn right,arrive |
|
||||
| a,d | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,h | first,first,first | depart,continue uturn,arrive |
|
||||
| e,j | first,second,second | depart,turn right,arrive |
|
||||
| e,h | first,first | depart,arrive |
|
||||
| e,l | first,second,second | depart,turn left,arrive |
|
||||
| e,d | first,first,first | depart,continue uturn,arrive |
|
||||
| k,h | second,first,first | depart,turn right,arrive |
|
||||
| k,l | second,second | depart,arrive |
|
||||
| k,d | second,first,first | depart,turn left,arrive |
|
||||
| k,j | second,second,second | depart,continue uturn,arrive |
|
||||
| i,d | second,first,first | depart,turn right,arrive |
|
||||
| i,j | second,second | depart,arrive |
|
||||
| i,h | second,first,first | depart,turn left,arrive |
|
||||
| i,l | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2)
|
||||
Given the node map
|
||||
| | | i | l | | |
|
||||
| | | | | | |
|
||||
| | | c | b | | |
|
||||
| d | | f | g | | a |
|
||||
| e | | | | | h |
|
||||
| | | j | k | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | second | yes |
|
||||
| cd | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| fg | primary | first | yes |
|
||||
| gh | primary | first | yes |
|
||||
| ic | primary | second | yes |
|
||||
| bl | primary | second | yes |
|
||||
| kg | primary | second | yes |
|
||||
| fj | primary | second | yes |
|
||||
| cf | primary | second | yes |
|
||||
| gb | primary | first | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,l | first,second,second | depart,turn right,arrive |
|
||||
| a,d | first,first | depart,arrive |
|
||||
| a,j | first,second,second | depart,turn left,arrive |
|
||||
| a,h | first,first,first | depart,continue uturn,arrive |
|
||||
| e,j | first,second,second | depart,turn right,arrive |
|
||||
| e,h | first,first | depart,arrive |
|
||||
| e,l | first,second,second | depart,turn left,arrive |
|
||||
| e,d | first,first,first | depart,continue uturn,arrive |
|
||||
| k,h | second,first,first | depart,turn right,arrive |
|
||||
| k,l | second,second | depart,arrive |
|
||||
| k,d | second,first,first | depart,turn left,arrive |
|
||||
| k,j | second,second,second | depart,continue uturn,arrive |
|
||||
| i,d | second,first,first | depart,turn right,arrive |
|
||||
| i,j | second,second | depart,arrive |
|
||||
| i,h | second,first,first | depart,turn left,arrive |
|
||||
| i,l | second,second,second | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Entering a segregated road
|
||||
Given the node map
|
||||
| | a | f | | |
|
||||
| | | | | g |
|
||||
| | b | e | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| c | d | | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| abc | primary | first | yes |
|
||||
| def | primary | first | yes |
|
||||
| be | primary | first | no |
|
||||
| ge | primary | second | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| d,c | first,first,first | depart,continue uturn,arrive |
|
||||
| a,f | first,first,first | depart,continue uturn,arrive |
|
||||
| a,g | first,second,second | depart,turn left,arrive |
|
||||
| d,g | first,second,second | depart,turn right,arrive |
|
||||
| g,f | second,first,first | depart,turn right,arrive |
|
||||
| g,c | second,first,first | depart,end of road left,arrive |
|
||||
|
||||
|
||||
Scenario: Do not collapse turning roads
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| | | c | | d |
|
||||
| a | | b | f | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name |
|
||||
| ab | primary | first |
|
||||
| bc | primary | first |
|
||||
| cd | primary | first |
|
||||
| ce | primary | second |
|
||||
| bf | primary | third |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
|
||||
| a,e | first,second,second | depart,turn left,arrive |
|
||||
| a,f | first,third,third | depart,turn straight,arrive |
|
||||
@@ -16,9 +16,42 @@ Feature: Continue Instructions
|
||||
| bd | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||
| a,d | abc,bd,bd | depart,new name straight,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||
| a,d | abc,bd,bd | depart,turn straight,arrive |
|
||||
|
||||
Scenario: Road turning left and straight
|
||||
Given the node map
|
||||
| | | c | |
|
||||
| a | | b | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name |
|
||||
| abc | primary | road |
|
||||
| bd | primary | road |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | road,road,road | depart,continue left,arrive |
|
||||
| a,d | road,road | depart,arrive |
|
||||
|
||||
Scenario: Road turning left and straight
|
||||
Given the node map
|
||||
| | | c | |
|
||||
| a | | b | d |
|
||||
| | | e | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name |
|
||||
| abc | primary | road |
|
||||
| bd | primary | road |
|
||||
| be | primary | road |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | road,road,road | depart,continue left,arrive |
|
||||
| a,d | road,road | depart,arrive |
|
||||
| a,e | road,road,road | depart,continue right,arrive |
|
||||
|
||||
Scenario: Road turning right
|
||||
Given the node map
|
||||
@@ -31,9 +64,9 @@ Feature: Continue Instructions
|
||||
| bd | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc,abc | depart,continue right,arrive |
|
||||
| a,d | abc,bd,bd | depart,new name straight,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc,abc | depart,continue right,arrive |
|
||||
| a,d | abc,bd,bd | depart,turn straight,arrive |
|
||||
|
||||
Scenario: Road turning slight left
|
||||
Given the node map
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
@routing @guidance
|
||||
Feature: Destination Signs
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - route name assembly with destination signs
|
||||
Given the node map
|
||||
| a | b |
|
||||
| c | d |
|
||||
| e | f |
|
||||
| g | h |
|
||||
| i | j |
|
||||
| k | l |
|
||||
| m | n |
|
||||
| o | p |
|
||||
| q | r |
|
||||
|
||||
And the ways
|
||||
| nodes | name | ref | destination | destination:ref | oneway | # |
|
||||
| ab | AB | E1 | | | yes | |
|
||||
| cd | CD | | Berlin | | yes | |
|
||||
| ef | EF | | Berlin | A1 | yes | |
|
||||
| gh | | | Berlin | A1 | yes | |
|
||||
| ij | | | Berlin | | yes | |
|
||||
| kl | KL | E1 | Berlin | A1 | yes | |
|
||||
| mn | MN | | Berlin;Hamburg | A1;A2 | yes | |
|
||||
| op | OP | | Berlin;Hamburg | A1;A2 | no | mis-tagged destination: not a oneway |
|
||||
| qr | QR | | | A1;A2 | yes | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | # |
|
||||
| a | b | AB (E1),AB (E1) | |
|
||||
| c | d | CD (Berlin),CD (Berlin) | |
|
||||
| e | f | EF (A1: Berlin),EF (A1: Berlin) | |
|
||||
| g | h | , | |
|
||||
| i | j | , | |
|
||||
| k | l | KL (E1),KL (E1) | |
|
||||
| m | n | MN (A1, A2: Berlin, Hamburg),MN (A1, A2: Berlin, Hamburg) | |
|
||||
| o | p | OP,OP | guard against mis-tagging |
|
||||
| q | r | QR (A1, A2),QR (A1, A2) | |
|
||||
@@ -21,7 +21,6 @@ Feature: End Of Road Instructions
|
||||
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
|
||||
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
|
||||
|
||||
|
||||
Scenario: End of Road with three streets
|
||||
Given the node map
|
||||
| | | c |
|
||||
@@ -104,3 +103,21 @@ Feature: End Of Road Instructions
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
|
||||
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
|
||||
|
||||
Scenario: End of Road with two ramps - prefer ramp over end of road
|
||||
Given the node map
|
||||
| | | c |
|
||||
| a | | b |
|
||||
| | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ab | primary |
|
||||
| bc | motorway_link |
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,on ramp left,arrive |
|
||||
| a,d | ab,bd,bd | depart,on ramp right,arrive |
|
||||
|
||||
|
||||
@@ -211,3 +211,73 @@ Feature: Fork Instructions
|
||||
| a,c | ,, | depart,fork slight left,arrive |
|
||||
| a,d | ,, | depart,fork slight right,arrive |
|
||||
|
||||
Scenario: Non-Fork on complex intersection - left
|
||||
Given the node map
|
||||
| | | | | c |
|
||||
| a | | b | | |
|
||||
| | e | | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | secondary |
|
||||
| bd | tertiary |
|
||||
| eb | tertiary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
| a,d | abc,bd,bd | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Non-Fork on complex intersection - right
|
||||
Given the node map
|
||||
| | e | | | c |
|
||||
| a | | b | | |
|
||||
| | | | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abd | secondary |
|
||||
| bc | tertiary |
|
||||
| eb | tertiary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abd,bc,bc | depart,turn slight left,arrive |
|
||||
| a,d | abd,abd | depart,arrive |
|
||||
|
||||
Scenario: Tripple fork
|
||||
Given the node map
|
||||
| | | | | | | | | c |
|
||||
| a | | b | | d | | | | |
|
||||
| | | | | | | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ab | secondary |
|
||||
| bc | secondary |
|
||||
| bd | secondary |
|
||||
| be | secondary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,fork slight left,arrive |
|
||||
| a,d | ab,bd,bd | depart,fork straight,arrive |
|
||||
| a,e | ab,be,be | depart,fork slight right,arrive |
|
||||
|
||||
Scenario: Tripple fork -- middle obvious
|
||||
Given the node map
|
||||
| | | | | c |
|
||||
| a | | b | | d |
|
||||
| | | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abd | secondary |
|
||||
| bc | secondary |
|
||||
| be | secondary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abd,bc,bc | depart,turn slight left,arrive |
|
||||
| a,d | abd,abd | depart,arrive |
|
||||
| a,e | abd,be,be | depart,turn slight right,arrive |
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
@routing @guidance @intersections
|
||||
Feature: Intersections Data
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
Given a grid size of 10 meters
|
||||
|
||||
Scenario: Passing Three Way South
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
| | | d | | |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | through |
|
||||
| bc | through |
|
||||
| bd | corner |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| a,c | through,through | depart,arrive | true:90,true:90 true:180 false:270;true:270 |
|
||||
|
||||
Scenario: Passing Three Way North
|
||||
Given the node map
|
||||
| | | d | | |
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | through |
|
||||
| bc | through |
|
||||
| bd | corner |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| a,c | through,through | depart,arrive | true:90,true:0 true:90 false:270;true:270 |
|
||||
|
||||
Scenario: Passing Oneway Street In
|
||||
Given the node map
|
||||
| | | d | | |
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| ab | through | no |
|
||||
| bc | through | no |
|
||||
| db | corner | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| a,c | through,through | depart,arrive | true:90,false:0 true:90 false:270;true:270 |
|
||||
|
||||
Scenario: Passing Oneway Street Out
|
||||
Given the node map
|
||||
| | | d | | |
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| ab | through | no |
|
||||
| bc | through | no |
|
||||
| bd | corner | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| a,c | through,through | depart,arrive | true:90,true:0 true:90 false:270;true:270 |
|
||||
|
||||
Scenario: Passing Two Intersections
|
||||
Given the node map
|
||||
| | | e | | | | |
|
||||
| a | | b | | c | | d |
|
||||
| | | | | f | | |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | through |
|
||||
| bc | through |
|
||||
| cd | through |
|
||||
| be | corner |
|
||||
| cf | corner |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
|
||||
|
||||
Scenario: Regression test #2424
|
||||
Given the node map
|
||||
| | | e | | | | | | i | | | | |
|
||||
| a | | b | | c | | d | | h | | k | | m |
|
||||
| | | | | f | | | | | | l | | |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| abcd | Fritz-Elsas-Straße |
|
||||
| hkm | Fritz-Elsas-Straße |
|
||||
| dhi | Martin-Luther-Straße |
|
||||
| be | corner |
|
||||
| kl | corner |
|
||||
| cf | corner |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,m | Fritz-Elsas-Straße,Fritz-Elsas-Straße| depart,arrive |
|
||||
|
||||
Scenario: Passing Two Intersections, Collapsing
|
||||
Given the node map
|
||||
| | | e | | | | |
|
||||
| a | | b | | c | | d |
|
||||
| | | | | f | | |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | through |
|
||||
| bc | throughbridge |
|
||||
| cd | through |
|
||||
| be | corner |
|
||||
| cf | corner |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
|
||||
| f,a | corner,throughbridge,through | depart,end of road left,arrive | true:0;true:90 false:180 true:270,true:0 false:90 true:270;true:90 |
|
||||
|
||||
Scenario: Roundabouts
|
||||
Given the node map
|
||||
| | | | | e | | | | |
|
||||
| | | | | | | | | |
|
||||
| | | | | a | | | | |
|
||||
| | | | 1 | | 4 | | | |
|
||||
| | | | | | | | | |
|
||||
| f | | b | | | | d | | h |
|
||||
| | | | | | | | | |
|
||||
| | | | 2 | | 3 | | | |
|
||||
| | | | | c | | | | |
|
||||
| | | | | | | | | |
|
||||
| | | | | g | | | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| abcda | roundabout |
|
||||
| ea | |
|
||||
| fb | |
|
||||
| gc | |
|
||||
| hd | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | intersections |
|
||||
| e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 |
|
||||
| e,g | ea,gc,gc | depart,abcda-exit-2,arrive | 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 | depart,abcda-exit-3,arrive | 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 | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1|
|
||||
| 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:0|
|
||||
| 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214|
|
||||
@@ -16,9 +16,9 @@ Feature: Motorway Guidance
|
||||
| bfg | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,ramp slight right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,off ramp slight right,arrive |
|
||||
|
||||
Scenario: Ramp Exit Right Curved Right
|
||||
Given the node map
|
||||
@@ -32,9 +32,9 @@ Feature: Motorway Guidance
|
||||
| bfg | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,ramp right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,off ramp right,arrive |
|
||||
|
||||
Scenario: Ramp Exit Right Curved Left
|
||||
Given the node map
|
||||
@@ -49,9 +49,9 @@ Feature: Motorway Guidance
|
||||
| cfg | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,cfg,cfg | depart,ramp slight right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,cfg,cfg | depart,off ramp slight right,arrive |
|
||||
|
||||
|
||||
Scenario: Ramp Exit Left
|
||||
@@ -65,9 +65,9 @@ Feature: Motorway Guidance
|
||||
| bfg | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,ramp slight left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,off ramp slight left,arrive |
|
||||
|
||||
Scenario: Ramp Exit Left Curved Left
|
||||
Given the node map
|
||||
@@ -81,9 +81,9 @@ Feature: Motorway Guidance
|
||||
| bfg | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,ramp left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,bfg,bfg | depart,off ramp left,arrive |
|
||||
|
||||
Scenario: Ramp Exit Left Curved Right
|
||||
Given the node map
|
||||
@@ -97,9 +97,9 @@ Feature: Motorway Guidance
|
||||
| cfg | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,cfg,cfg | depart,ramp slight left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| a,g | abcde,cfg,cfg | depart,off ramp slight left,arrive |
|
||||
|
||||
Scenario: On Ramp Right
|
||||
Given the node map
|
||||
@@ -176,11 +176,11 @@ Feature: Motorway Guidance
|
||||
| chi | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
|
||||
| a,i | abcde,chi,chi | depart,ramp slight right,arrive |
|
||||
| f,i | fgc,chi,chi | depart,ramp right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
|
||||
| a,i | abcde,chi,chi | depart,off ramp slight right,arrive |
|
||||
| f,i | fgc,chi,chi | depart,off ramp right,arrive |
|
||||
|
||||
Scenario: On And Off Ramp Left
|
||||
Given the node map
|
||||
@@ -194,11 +194,11 @@ Feature: Motorway Guidance
|
||||
| chi | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
|
||||
| a,i | abcde,chi,chi | depart,ramp slight left,arrive |
|
||||
| f,i | fgc,chi,chi | depart,ramp left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,e | abcde,abcde | depart,arrive |
|
||||
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
|
||||
| a,i | abcde,chi,chi | depart,off ramp slight left,arrive |
|
||||
| f,i | fgc,chi,chi | depart,off ramp left,arrive |
|
||||
|
||||
Scenario: Merging Motorways
|
||||
Given the node map
|
||||
|
||||
@@ -133,3 +133,34 @@ Feature: New-Name Instructions
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,new name slight right,arrive |
|
||||
|
||||
Scenario: Empty road names - Announce Change From, suppress Change To
|
||||
Given the node map
|
||||
| a | | b | | c | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | ab |
|
||||
| bc | |
|
||||
| cd | cd |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,cd,cd | depart,new name straight,arrive |
|
||||
| a,c | ab, | depart,arrive |
|
||||
|
||||
Scenario: Empty road names - Loose name shortly
|
||||
Given the node map
|
||||
| a | | b | | c | | d | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | name |
|
||||
| bc | with-name |
|
||||
| cd | |
|
||||
| de | with-name |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | name,with-name,with-name | depart,new name straight,arrive |
|
||||
| b,e | with-name,with-name | depart,arrive |
|
||||
|
||||
@@ -16,8 +16,8 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp right,arrive |
|
||||
|
||||
Scenario: Ramp On Through Street Left
|
||||
Given the node map
|
||||
@@ -30,8 +30,8 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp left,arrive |
|
||||
|
||||
Scenario: Ramp On Through Street Left and Right
|
||||
Given the node map
|
||||
@@ -46,9 +46,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp right,arrive |
|
||||
| a,e | abc,be,be | depart,ramp left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp right,arrive |
|
||||
| a,e | abc,be,be | depart,on ramp left,arrive |
|
||||
|
||||
Scenario: Ramp On Three Way Intersection Right
|
||||
Given the node map
|
||||
@@ -62,8 +62,8 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,ramp right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,on ramp right,arrive |
|
||||
|
||||
Scenario: Ramp On Three Way Intersection Right
|
||||
Given the node map
|
||||
@@ -78,8 +78,8 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,ramp right,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,on ramp right,arrive |
|
||||
|
||||
Scenario: Ramp Off Though Street
|
||||
Given the node map
|
||||
@@ -93,9 +93,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp right,arrive |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp right,arrive |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
|
||||
Scenario: Straight Ramp Off Turning Though Street
|
||||
Given the node map
|
||||
@@ -108,9 +108,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp straight,arrive |
|
||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp straight,arrive |
|
||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||
|
||||
Scenario: Fork Ramp Off Turning Though Street
|
||||
Given the node map
|
||||
@@ -124,9 +124,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp right,arrive |
|
||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp right,arrive |
|
||||
| a,c | abc,abc,abc | depart,continue left,arrive |
|
||||
|
||||
Scenario: Fork Ramp
|
||||
Given the node map
|
||||
@@ -141,9 +141,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,ramp right,arrive |
|
||||
| a,c | ab,bc,bc | depart,turn left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,on ramp right,arrive |
|
||||
| a,c | ab,bc,bc | depart,turn left,arrive |
|
||||
|
||||
Scenario: Fork Slight Ramp
|
||||
Given the node map
|
||||
@@ -158,9 +158,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,ramp slight right,arrive |
|
||||
| a,c | ab,bc,bc | depart,turn slight left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bd,bd | depart,on ramp slight right,arrive |
|
||||
| a,c | ab,bc,bc | depart,turn slight left,arrive |
|
||||
|
||||
Scenario: Fork Slight Ramp on Through Street
|
||||
Given the node map
|
||||
@@ -174,9 +174,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp slight right,arrive |
|
||||
| a,c | abc,abc,abc | depart,continue slight left,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp slight right,arrive |
|
||||
| a,c | abc,abc,abc | depart,continue slight left,arrive |
|
||||
|
||||
Scenario: Fork Slight Ramp on Obvious Through Street
|
||||
Given the node map
|
||||
@@ -190,9 +190,9 @@ Feature: Ramp Guidance
|
||||
| bd | motorway_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,ramp slight right,arrive |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,on ramp slight right,arrive |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
|
||||
Scenario: Two Ramps Joining into common Motorway
|
||||
Given the node map
|
||||
|
||||
@@ -194,15 +194,15 @@ Feature: Rotary
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| ad | |
|
||||
| bcdb | roundabout |
|
||||
| ce | |
|
||||
| df | |
|
||||
| be | |
|
||||
| cf | |
|
||||
|
||||
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 |
|
||||
| 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
|
||||
@@ -213,15 +213,15 @@ Feature: Rotary
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| ac | |
|
||||
| bcdb | roundabout |
|
||||
| ce | |
|
||||
| df | |
|
||||
| de | |
|
||||
| bf | |
|
||||
|
||||
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 |
|
||||
| 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
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
@routing @guidance
|
||||
Feature: Basic Roundabout
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
Given a grid size of 3 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 |
|
||||
|
||||
Scenario: Enter and Exit - Rotated
|
||||
Given the node map
|
||||
| a | | | d |
|
||||
| | b | c | |
|
||||
| | g | e | |
|
||||
| h | | | 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 |
|
||||
|
||||
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
|
||||
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,roundabout-exit-1,arrive |
|
||||
| b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive |
|
||||
| b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive |
|
||||
| c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive |
|
||||
| c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive |
|
||||
| c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive |
|
||||
| e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive |
|
||||
| e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive |
|
||||
| e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive |
|
||||
| g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive |
|
||||
| g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive |
|
||||
| g,f | bcegb,ef,ef | depart,roundabout-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 |
|
||||
|
||||
Scenario: Mixed Entry and Exit - Not an Intersection
|
||||
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,roundabout-exit-1,arrive |
|
||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive |
|
||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive |
|
||||
| a,f | abc,def,def | depart,roundabout-exit-4,arrive |
|
||||
| d,f | def,def,def | depart,roundabout-exit-1,arrive |
|
||||
| d,c | def,abc,abc | depart,roundabout-exit-2,arrive |
|
||||
| d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive |
|
||||
| d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive |
|
||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive |
|
||||
| g,f | ghi,def,def | depart,roundabout-exit-2,arrive |
|
||||
| g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive |
|
||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive |
|
||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive |
|
||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive |
|
||||
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
|
||||
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
|
||||
|
||||
Scenario: Segregated roads - Not an intersection
|
||||
Given the node map
|
||||
| | a | | c | |
|
||||
| l | | b | | d |
|
||||
| | k | | e | |
|
||||
| j | | h | | f |
|
||||
| | i | | g | |
|
||||
|
||||
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,roundabout-exit-4,arrive |
|
||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
|
||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
||||
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
|
||||
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
||||
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
|
||||
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
||||
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
|
||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
||||
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
|
||||
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
|
||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
|
||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
||||
|
||||
Scenario: Collinear in X
|
||||
Given the node map
|
||||
| a | b | c | d | f |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| bcdb | roundabout |
|
||||
| ce | |
|
||||
| df | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
|
||||
| a,f | ab,df,df | depart,roundabout-exit-2,arrive |
|
||||
|
||||
Scenario: Collinear in X,Y
|
||||
Given the node map
|
||||
| a | | |
|
||||
| b | | |
|
||||
| c | d | f |
|
||||
| e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| bcdb | roundabout |
|
||||
| ce | |
|
||||
| df | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | ab,ce,ce | depart,roundabout turn straight exit-1,arrive |
|
||||
| a,f | ab,df,df | depart,roundabout turn left 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 | roundabout |
|
||||
| be | |
|
||||
| cf | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | ad,be,be | depart,roundabout turn straight exit-1,arrive |
|
||||
| a,f | ad,cf,cf | depart,roundabout turn left 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 | roundabout |
|
||||
| de | |
|
||||
| bf | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | ac,de,de | depart,roundabout turn straight exit-1,arrive |
|
||||
| a,f | ac,bf,bf | depart,roundabout turn left exit-2,arrive |
|
||||
|
||||
Scenario: Enter and Exit -- too complex
|
||||
Given the node map
|
||||
| j | | a | | |
|
||||
| | i | b | | |
|
||||
| | g | | c | d |
|
||||
| h | | e | | |
|
||||
| | | f | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| ij | |
|
||||
| cd | |
|
||||
| ef | |
|
||||
| gh | |
|
||||
| bigecb | roundabout |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,cd,cd | depart,roundabout-exit-4,arrive |
|
||||
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
|
||||
| a,h | ab,gh,gh | depart,roundabout-exit-2,arrive |
|
||||
| d,f | cd,ef,ef | depart,roundabout-exit-4,arrive |
|
||||
| d,h | cd,gh,gh | depart,roundabout-exit-3,arrive |
|
||||
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
|
||||
| f,h | ef,gh,gh | depart,roundabout-exit-4,arrive |
|
||||
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
|
||||
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
|
||||
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
|
||||
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
|
||||
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
||||
|
||||
Scenario: Enter and Exit -- Non-Distinct
|
||||
Given the node map
|
||||
| | | a | | |
|
||||
| | | b | | |
|
||||
| | g | | c | d |
|
||||
| | | e | | |
|
||||
| h | | 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-exit-3,arrive |
|
||||
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive |
|
||||
| a,h | ab,gh,gh | depart,roundabout-exit-1,arrive |
|
||||
| d,f | cd,ef,ef | depart,roundabout-exit-3,arrive |
|
||||
| d,h | cd,gh,gh | depart,roundabout-exit-2,arrive |
|
||||
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
|
||||
| f,h | ef,gh,gh | depart,roundabout-exit-3,arrive |
|
||||
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
|
||||
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
|
||||
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
|
||||
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
|
||||
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
||||
|
||||
@@ -165,6 +165,84 @@ Feature: Basic Roundabout
|
||||
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
|
||||
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
|
||||
|
||||
Scenario: Mixed Entry and Exit - segregated roads
|
||||
Given the node map
|
||||
| | | a | | c | | |
|
||||
| | | | | | | |
|
||||
| l | | | b | | | d |
|
||||
| | | k | | e | | |
|
||||
| j | | | h | | | f |
|
||||
| | | | | | | |
|
||||
| | | i | | g | | |
|
||||
|
||||
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,roundabout-exit-4,arrive |
|
||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
|
||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
||||
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
|
||||
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
||||
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
|
||||
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
||||
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
|
||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
||||
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
|
||||
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
|
||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
|
||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
||||
|
||||
Scenario: Mixed Entry and Exit - segregated roads, different names
|
||||
Given the node map
|
||||
| | | a | | c | | |
|
||||
| | | | | | | |
|
||||
| l | | | b | | | d |
|
||||
| | | k | | e | | |
|
||||
| j | | | h | | | f |
|
||||
| | | | | | | |
|
||||
| | | i | | g | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction | oneway |
|
||||
| ab | | yes |
|
||||
| bc | | yes |
|
||||
| de | | yes |
|
||||
| ef | | yes |
|
||||
| gh | | yes |
|
||||
| hi | | yes |
|
||||
| jk | | yes |
|
||||
| kl | | yes |
|
||||
| bkheb | roundabout | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,roundabout-exit-4,arrive |
|
||||
| a,l | ab,kl,kl | depart,roundabout-exit-1,arrive |
|
||||
| a,i | ab,hi,hi | depart,roundabout-exit-2,arrive |
|
||||
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
|
||||
| d,f | de,ef,ef | depart,roundabout-exit-4,arrive |
|
||||
| d,c | de,bc,bc | depart,roundabout-exit-1,arrive |
|
||||
| d,l | de,kl,kl | depart,roundabout-exit-2,arrive |
|
||||
| d,i | de,hi,hi | depart,roundabout-exit-3,arrive |
|
||||
| g,i | gh,hi,hi | depart,roundabout-exit-4,arrive |
|
||||
| g,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
||||
| g,c | gh,bc,bc | depart,roundabout-exit-2,arrive |
|
||||
| g,l | gh,kl,kl | depart,roundabout-exit-3,arrive |
|
||||
| j,l | jk,kl,kl | depart,roundabout-exit-4,arrive |
|
||||
| j,i | jk,hi,hi | depart,roundabout-exit-1,arrive |
|
||||
| j,f | jk,ef,ef | depart,roundabout-exit-2,arrive |
|
||||
| j,c | jk,bc,bc | depart,roundabout-exit-3,arrive |
|
||||
|
||||
Scenario: Collinear in X
|
||||
Given the node map
|
||||
| a | b | c | d | f |
|
||||
@@ -184,11 +262,11 @@ Feature: Basic Roundabout
|
||||
|
||||
Scenario: Collinear in Y
|
||||
Given the node map
|
||||
| a | |
|
||||
| b | |
|
||||
| c | e |
|
||||
| d | |
|
||||
| f | |
|
||||
| | a |
|
||||
| | b |
|
||||
| e | c |
|
||||
| | d |
|
||||
| | f |
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
@@ -230,15 +308,15 @@ Feature: Basic Roundabout
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| ad | |
|
||||
| bcdb | roundabout |
|
||||
| ce | |
|
||||
| df | |
|
||||
| be | |
|
||||
| cf | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
|
||||
| a,f | ab,df,df | depart,roundabout-exit-2,arrive |
|
||||
| a,e | ad,be,be | depart,roundabout-exit-1,arrive |
|
||||
| a,f | ad,cf,cf | depart,roundabout-exit-2,arrive |
|
||||
|
||||
Scenario: Collinear in X,Y
|
||||
Given the node map
|
||||
@@ -249,13 +327,13 @@ Feature: Basic Roundabout
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| ac | |
|
||||
| bcdb | roundabout |
|
||||
| ce | |
|
||||
| df | |
|
||||
| de | |
|
||||
| bf | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
|
||||
| a,f | ab,df,df | depart,roundabout-exit-2,arrive |
|
||||
| a,e | ac,de,de | depart,roundabout-exit-1,arrive |
|
||||
| a,f | ac,bf,bf | depart,roundabout-exit-2,arrive |
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
@routing @guidance
|
||||
Feature: Suppress New Names on dedicated Suffices
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
Given a grid size of 10 meters
|
||||
|
||||
Scenario: Suffix To Suffix
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | 42 N |
|
||||
| bc | 42 S |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | 42 N,42 S | depart,arrive |
|
||||
|
||||
Scenario: Suffix To Suffix Ref
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name | ref |
|
||||
| ab | 42 N | |
|
||||
| bc | 42 S | 101 |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | 42 N,42 S (101) | depart,arrive |
|
||||
|
||||
Scenario: Prefix Change
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | West 42 |
|
||||
| bc | East 42 |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | West 42,East 42 | depart,arrive |
|
||||
|
||||
Scenario: Prefix Change and Reference
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name | ref |
|
||||
| ab | West 42 | 101 |
|
||||
| bc | East 42 | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | West 42 (101),East 42 | depart,arrive |
|
||||
|
||||
Scenario: Suffix To Suffix - Turn
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
| | | d | | |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | 42 N |
|
||||
| bc | 42 S |
|
||||
| bd | 42 E |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | 42 N,42 S | depart,arrive |
|
||||
| a,d | 42 N,42 E,42 E | depart,turn right,arrive |
|
||||
|
||||
Scenario: Suffix To No Suffix
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | 42 N |
|
||||
| bc | 42 |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | 42 N,42 | depart,arrive |
|
||||
|
||||
Scenario: No Suffix To Suffix
|
||||
Given the node map
|
||||
| a | | b | | c |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | 42 |
|
||||
| bc | 42 S |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | 42,42 S | depart,arrive |
|
||||
|
||||
@@ -282,3 +282,527 @@ Feature: Simple Turns
|
||||
| h,c | first,second,second | depart,turn left,arrive |
|
||||
| h,i | first,first,first | depart,continue uturn,arrive |
|
||||
|
||||
Scenario: Three Way Similar Sharp Turns
|
||||
Given the node map
|
||||
| a | | | | b |
|
||||
| c | | | | |
|
||||
| | d | | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ab | primary |
|
||||
| bc | primary |
|
||||
| bd | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,turn sharp right,arrive |
|
||||
| a,d | ab,bd,bd | depart,turn sharp right,arrive |
|
||||
| d,c | bd,bc,bc | depart,turn sharp left,arrive |
|
||||
| d,a | bd,ab,ab | depart,turn sharp left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (1)
|
||||
Given the node map
|
||||
| | | | | d |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn slight left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (2)
|
||||
Given the node map
|
||||
| | | | | d |
|
||||
| | | | | |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (3)
|
||||
Given the node map
|
||||
| | | | d | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (4)
|
||||
Given the node map
|
||||
| | | d | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (5)
|
||||
Given the node map
|
||||
| | d | | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (6)
|
||||
Given the node map
|
||||
| d | | | | |
|
||||
| | | | | |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp left,arrive |
|
||||
|
||||
Scenario: Left Turn Assignment (7)
|
||||
Given the node map
|
||||
| d | | | | |
|
||||
| a | | b | | c |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp left,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (1)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| | | | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (2)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | | | | d |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (3)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | | d | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (4)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | d | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (5)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | d | | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (6)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| d | | | | |
|
||||
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment (7)
|
||||
Given the node map
|
||||
| | | e | | |
|
||||
| a | | b | | c |
|
||||
| d | | | | |
|
||||
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Two Turns
|
||||
Given the node map
|
||||
| | | f | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| d | e | | | |
|
||||
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
|
||||
| a,e | abc,be,be | depart,turn right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Two Turns (2)
|
||||
Given the node map
|
||||
| | | f | | c |
|
||||
| a | | b | | |
|
||||
| | | | | e |
|
||||
| | | | d | |
|
||||
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
| a,e | abc,be,be | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Two Turns (3)
|
||||
Given the node map
|
||||
| | | f | | |
|
||||
| a | | b | | c |
|
||||
| | | | | e |
|
||||
| | | | d | |
|
||||
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
| a,e | abc,be,be | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Two Turns (4)
|
||||
Given the node map
|
||||
| | | f | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | | d | | e |
|
||||
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn right,arrive |
|
||||
| a,e | abc,be,be | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Three Turns
|
||||
Given the node map
|
||||
| | | g | | |
|
||||
| a | | b | | c |
|
||||
| | d | | f | |
|
||||
| | | e | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
| bg | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
|
||||
| a,e | abc,be,be | depart,turn right,arrive |
|
||||
| a,f | abc,bf,bf | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Slight Turn involving Oneways
|
||||
Given the node map
|
||||
| | | a | | |
|
||||
| | | | | |
|
||||
| | | b | | e |
|
||||
| d | | | | |
|
||||
| | | c | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| abc | primary | yes |
|
||||
| dbe | primary | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
| d,e | dbe,dbe | depart,arrive |
|
||||
| e,d | dbe,dbe | depart,arrive |
|
||||
|
||||
Scenario: Slight Turn involving Oneways
|
||||
Given the node map
|
||||
| | | | a | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | b | | e |
|
||||
| d | | | | |
|
||||
| | | c | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| abc | primary | yes |
|
||||
| dbe | primary | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
| d,e | dbe,dbe | depart,arrive |
|
||||
| e,d | dbe,dbe | depart,arrive |
|
||||
|
||||
|
||||
Scenario: Slight Turn involving Oneways - Name Change
|
||||
Given the node map
|
||||
| | | a | | |
|
||||
| | | | | |
|
||||
| | | b | | e |
|
||||
| d | | | | |
|
||||
| | | c | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| abc | primary | yes |
|
||||
| db | primary | no |
|
||||
| be | primary | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc | depart,arrive |
|
||||
| d,e | db,be,be | depart,new name slight right,arrive |
|
||||
| e,d | be,db,db | depart,new name slight left,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 1
|
||||
Given the node map
|
||||
| | | g | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | d | e | f | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| abc | primary | no |
|
||||
| db | primary | yes |
|
||||
| eb | primary | no |
|
||||
| fb | primary | no |
|
||||
| bg | primary | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,e | abc,eb,eb | depart,turn right,arrive |
|
||||
| a,f | abc,fb,fb | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 2
|
||||
Given the node map
|
||||
| | | g | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | d | e | f | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| abc | primary | no |
|
||||
| db | primary | no |
|
||||
| eb | primary | yes |
|
||||
| fb | primary | no |
|
||||
| bg | primary | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,db,db | depart,turn sharp right,arrive |
|
||||
| a,f | abc,fb,fb | depart,turn right,arrive |
|
||||
|
||||
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 3
|
||||
Given the node map
|
||||
| | | g | | |
|
||||
| a | | b | | c |
|
||||
| | | | | |
|
||||
| | d | e | f | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | oneway |
|
||||
| abc | primary | no |
|
||||
| db | primary | no |
|
||||
| be | primary | no |
|
||||
| fb | primary | yes |
|
||||
| bg | primary | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,db,db | depart,turn sharp right,arrive |
|
||||
| a,e | abc,be,be | depart,turn right,arrive |
|
||||
|
||||
Scenario: Conflicting Turns with well distinguished turn
|
||||
Given the node map
|
||||
| a | | | b | | | c |
|
||||
| | | | | | | |
|
||||
| f | | | | | | d |
|
||||
| | | | | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn slight right,arrive |
|
||||
| a,e | abc,be,be | depart,turn right,arrive |
|
||||
| a,f | abc,bf,bf | depart,turn sharp right,arrive |
|
||||
|
||||
Scenario: Conflicting Turns with well distinguished turn (back)
|
||||
Given the node map
|
||||
| a | | | b | | | c |
|
||||
| | | | | | | |
|
||||
| d | | | | | | f |
|
||||
| | e | | | | | |
|
||||
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| abc | primary |
|
||||
| bd | primary |
|
||||
| be | primary |
|
||||
| bf | primary |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
|
||||
| a,e | abc,be,be | depart,turn right,arrive |
|
||||
| a,f | abc,bf,bf | depart,turn slight right,arrive |
|
||||
|
||||
|
||||
@@ -10,13 +10,11 @@ module.exports = function () {
|
||||
});
|
||||
|
||||
this.Given(/^the extract extra arguments "(.*?)"$/, (args, callback) => {
|
||||
this.setExtractArgs(args);
|
||||
callback();
|
||||
this.setExtractArgs(args, callback);
|
||||
});
|
||||
|
||||
this.Given(/^the contract extra arguments "(.*?)"$/, (args, callback) => {
|
||||
this.setContractArgs(args);
|
||||
callback();
|
||||
this.setContractArgs(args, callback);
|
||||
});
|
||||
|
||||
this.Given(/^a grid size of (\d+) meters$/, (meters, callback) => {
|
||||
@@ -49,18 +47,27 @@ module.exports = function () {
|
||||
|
||||
var addNode = (name, ri, ci, cb) => {
|
||||
if (name) {
|
||||
if (name.length !== 1) throw new Error(util.format('*** node invalid name %s, must be single characters', name));
|
||||
if (!name.match(/[a-z0-9]/)) throw new Error(util.format('*** invalid node name %s, must me alphanumeric', name));
|
||||
|
||||
var lonLat;
|
||||
if (name.match(/[a-z]/)) {
|
||||
if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name));
|
||||
var nodeWithID = name.match(/([a-z])\:([0-9]*)/);
|
||||
if (nodeWithID) {
|
||||
var nodeName = nodeWithID[1],
|
||||
nodeID = nodeWithID[2];
|
||||
if (this.nameNodeHash[nodeName]) throw new Error(util.format('*** duplicate node %s', name));
|
||||
lonLat = this.tableCoordToLonLat(ci, ri);
|
||||
this.addOSMNode(name, lonLat[0], lonLat[1], null);
|
||||
this.addOSMNode(nodeName, lonLat[0], lonLat[1], nodeID);
|
||||
} else {
|
||||
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name);
|
||||
lonLat = this.tableCoordToLonLat(ci, ri);
|
||||
this.addLocation(name, lonLat[0], lonLat[1], null);
|
||||
if (name.length !== 1) throw new Error(util.format('*** node invalid name %s, must be single characters', name));
|
||||
if (!name.match(/[a-z0-9]/)) throw new Error(util.format('*** invalid node name %s, must me alphanumeric', name));
|
||||
|
||||
var lonLat;
|
||||
if (name.match(/[a-z]/)) {
|
||||
if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name));
|
||||
lonLat = this.tableCoordToLonLat(ci, ri);
|
||||
this.addOSMNode(name, lonLat[0], lonLat[1], null);
|
||||
} else {
|
||||
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name);
|
||||
lonLat = this.tableCoordToLonLat(ci, ri);
|
||||
this.addLocation(name, lonLat[0], lonLat[1], null);
|
||||
}
|
||||
}
|
||||
|
||||
cb();
|
||||
@@ -228,6 +235,10 @@ module.exports = function () {
|
||||
fs.writeFile(path.resolve(this.TEST_FOLDER, 'speeds.csv'), data, callback);
|
||||
});
|
||||
|
||||
this.Given(/^the turn penalty file$/, (data, callback) => {
|
||||
fs.writeFile(path.resolve(this.TEST_FOLDER, 'penalties.csv'), data, callback);
|
||||
});
|
||||
|
||||
this.Given(/^the data has been saved to disk$/, (callback) => {
|
||||
try {
|
||||
this.reprocess(callback);
|
||||
|
||||
@@ -33,7 +33,9 @@ module.exports = function () {
|
||||
var subMatchings = [],
|
||||
turns = '',
|
||||
route = '',
|
||||
duration = '';
|
||||
duration = '',
|
||||
annotation = '';
|
||||
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
if (headers.has('matchings')) {
|
||||
@@ -54,6 +56,11 @@ module.exports = function () {
|
||||
if (json.matchings.length != 1) throw new Error('*** Checking duration only supported for matchings with one subtrace');
|
||||
duration = json.matchings[0].duration;
|
||||
}
|
||||
|
||||
if (headers.has('annotation')) {
|
||||
if (json.matchings.length != 1) throw new Error('*** Checking annotation only supported for matchings with one subtrace');
|
||||
annotation = this.annotationList(json.matchings[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (headers.has('turns')) {
|
||||
@@ -68,6 +75,10 @@ module.exports = function () {
|
||||
got.duration = duration.toString();
|
||||
}
|
||||
|
||||
if (headers.has('annotation')) {
|
||||
got.annotation = annotation.toString();
|
||||
}
|
||||
|
||||
var ok = true;
|
||||
var encodedResult = '',
|
||||
extendedTarget = '';
|
||||
@@ -134,6 +145,7 @@ module.exports = function () {
|
||||
this.requestUrl(row.request, afterRequest);
|
||||
} else {
|
||||
var params = this.queryParams;
|
||||
params['annotate'] = 'true';
|
||||
got = {};
|
||||
for (var k in row) {
|
||||
var match = k.match(/param:(.*)/);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var assert = require('assert');
|
||||
|
||||
module.exports = function () {
|
||||
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.SHUTDOWN_TIMEOUT }, (options, callback) => {
|
||||
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
|
||||
this.runBin('osrm-routed', options, () => {
|
||||
callback();
|
||||
});
|
||||
|
||||
@@ -71,6 +71,7 @@ module.exports = function () {
|
||||
r.status = res.statusCode === 200 ? 'x' : null;
|
||||
if (r.status) {
|
||||
r.route = this.wayList(r.json.routes[0]);
|
||||
r.summary = r.json.routes[0].legs.map(l => l.summary).join(',');
|
||||
|
||||
if (r.route.split(',')[0] === util.format('w%d', i)) {
|
||||
r.time = r.json.routes[0].duration;
|
||||
|
||||
@@ -3,8 +3,7 @@ var d3 = require('d3-queue');
|
||||
module.exports = function () {
|
||||
this.When(/^I route I should get$/, this.WhenIRouteIShouldGet);
|
||||
|
||||
// This is used to route 100 times; timeout for entire step is therefore set to 100 * STRESS_TIMEOUT
|
||||
this.When(/^I route (\d+) times I should get$/, { timeout: 30000 }, (n, table, callback) => {
|
||||
this.When(/^I route (\d+) times I should get$/, { timeout: 100 * this.TIMEOUT }, (n, table, callback) => {
|
||||
var q = d3.queue(1);
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
|
||||
@@ -46,8 +46,8 @@ module.exports = function () {
|
||||
if (headers.has('trips')) {
|
||||
subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => {
|
||||
var toAdd = [];
|
||||
if (i === 0) toAdd.push(sl.steps[0].maneuver.location);
|
||||
toAdd.push(sl.steps[sl.steps.length-1].maneuver.location);
|
||||
if (i === 0) toAdd.push(sl.steps[0].intersections[0].location);
|
||||
toAdd.push(sl.steps[sl.steps.length-1].intersections[0].location);
|
||||
return toAdd;
|
||||
})));
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ module.exports = function () {
|
||||
|
||||
this.osmData = new classes.osmData(this);
|
||||
|
||||
this.STRESS_TIMEOUT = 300;
|
||||
|
||||
this.OSRMLoader = this._OSRMLoader();
|
||||
|
||||
this.PREPROCESS_LOG_FILE = path.resolve(this.TEST_FOLDER, 'preprocessing.log');
|
||||
@@ -105,11 +103,16 @@ module.exports = function () {
|
||||
} else cb();
|
||||
};
|
||||
|
||||
this.setExtractArgs = (args) => {
|
||||
this.setExtractArgs = (args, callback) => {
|
||||
this.extractArgs = args;
|
||||
this.forceExtract = true;
|
||||
this.forceContract = true;
|
||||
callback();
|
||||
};
|
||||
|
||||
this.setContractArgs = (args) => {
|
||||
this.setContractArgs = (args, callback) => {
|
||||
this.contractArgs = args;
|
||||
this.forceContract = true;
|
||||
callback();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -222,7 +222,7 @@ module.exports = function () {
|
||||
});
|
||||
};
|
||||
|
||||
['osrm','osrm.names','osrm.restrictions','osrm.ebg','osrm.enw','osrm.edges','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.properties'].forEach(file => {
|
||||
['osrm','osrm.names','osrm.restrictions','osrm.ebg','osrm.enw','osrm.edges','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.properties','osrm.icd'].forEach(file => {
|
||||
q.defer(rename, file);
|
||||
});
|
||||
|
||||
@@ -273,7 +273,7 @@ module.exports = function () {
|
||||
|
||||
var q = d3.queue();
|
||||
|
||||
['osrm.hsgr','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.core','osrm.edges','osrm.datasource_indexes','osrm.datasource_names','osrm.level'].forEach((file) => {
|
||||
['osrm.hsgr','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.core','osrm.edges','osrm.datasource_indexes','osrm.datasource_names','osrm.level','osrm.icd'].forEach((file) => {
|
||||
q.defer(rename, file);
|
||||
});
|
||||
|
||||
@@ -295,9 +295,10 @@ module.exports = function () {
|
||||
this.writeAndExtract((e) => {
|
||||
if (e) return callback(e);
|
||||
this.isContracted((isContracted) => {
|
||||
var contractFn = isContracted ? noop : this.contractData;
|
||||
var contractFn = (isContracted && !this.forceContract) ? noop : this.contractData;
|
||||
if (isContracted) this.log('Already contracted ' + this.osmData.contractedFile, 'preprocess');
|
||||
contractFn((e) => {
|
||||
this.forceContract = false;
|
||||
if (e) return callback(e);
|
||||
this.logPreprocessDone();
|
||||
callback();
|
||||
@@ -311,9 +312,10 @@ module.exports = function () {
|
||||
this.writeInputData((e) => {
|
||||
if (e) return callback(e);
|
||||
this.isExtracted((isExtracted) => {
|
||||
var extractFn = isExtracted ? noop : this.extractData;
|
||||
var extractFn = (isExtracted && !this.forceExtract) ? noop : this.extractData;
|
||||
if (isExtracted) this.log('Already extracted ' + this.osmData.extractedFile, 'preprocess');
|
||||
extractFn((e) => {
|
||||
this.forceExtract = false;
|
||||
callback(e);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,24 +52,91 @@ module.exports = {
|
||||
match (got, want) {
|
||||
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
|
||||
matchAbs = want.match(/(.*)\s+\+\-(.+)$/),
|
||||
matchRe = want.match(/^\/(.*)\/$/);
|
||||
matchRe = want.match(/^\/(.*)\/$/),
|
||||
// we use this for matching before/after bearing
|
||||
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
|
||||
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/);
|
||||
|
||||
function inRange(margin, got, want) {
|
||||
var fromR = parseFloat(want) - margin,
|
||||
toR = parseFloat(want) + margin;
|
||||
return parseFloat(got) >= fromR && parseFloat(got) <= toR;
|
||||
}
|
||||
function parseIntersectionString(str) {
|
||||
return str.split(';')
|
||||
.map((turn_intersections) => turn_intersections
|
||||
.split(',')
|
||||
.map((intersection) => intersection
|
||||
.split(' ')
|
||||
.map((entry_bearing_pair) => entry_bearing_pair
|
||||
.split(':'))));
|
||||
}
|
||||
|
||||
if (got === want) {
|
||||
return true;
|
||||
} else if (matchBearingListAbs) {
|
||||
let want_and_margin = want.split('+-'),
|
||||
margin = parseFloat(want_and_margin[1].trim()),
|
||||
want_pairs = want_and_margin[0].trim().split(',').map((pair) => pair.split('->')),
|
||||
got_pairs = got.split(',').map((pair) => pair.split('->'));
|
||||
if (want_pairs.length != got_pairs.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < want_pairs.length; ++i)
|
||||
{
|
||||
if (!inRange(margin, got_pairs[i][0], want_pairs[i][0]) ||
|
||||
!inRange(margin, got_pairs[i][1], want_pairs[i][1]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (matchIntersectionListAbs) {
|
||||
let margin = parseFloat(want.split('+-')[1]),
|
||||
want_intersections = parseIntersectionString(want.split('+-')[0].trim()),
|
||||
got_intersections = parseIntersectionString(got);
|
||||
if (want_intersections.length != got_intersections.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (let step_idx = 0; step_idx < want_intersections.length; ++step_idx)
|
||||
{
|
||||
if (want_intersections[step_idx].length != got_intersections[step_idx].length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (let intersection_idx = 0; intersection_idx < want_intersections[step_idx].length; ++intersection_idx)
|
||||
{
|
||||
if (want_intersections[step_idx][intersection_idx].length != got_intersections[step_idx][intersection_idx].length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (let pair_idx = 0; pair_idx < want_intersections[step_idx][intersection_idx].length; ++pair_idx)
|
||||
{
|
||||
let want_pair = want_intersections[step_idx][intersection_idx][pair_idx],
|
||||
got_pair = got_intersections[step_idx][intersection_idx][pair_idx];
|
||||
if (got_pair[0] != want_pair[0] ||
|
||||
!inRange(margin, got_pair[1], want_pair[1]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (matchPercent) { // percentage range: 100 ~ 5%
|
||||
var target = parseFloat(matchPercent[1]),
|
||||
percentage = parseFloat(matchPercent[2]);
|
||||
if (target === 0) {
|
||||
return true;
|
||||
} else {
|
||||
var ratio = Math.abs(1 - parseFloat(got) / target);
|
||||
let ratio = Math.abs(1 - parseFloat(got) / target);
|
||||
return 100 * ratio < percentage;
|
||||
}
|
||||
} else if (matchAbs) { // absolute range: 100 +-5
|
||||
var margin = parseFloat(matchAbs[2]),
|
||||
fromR = parseFloat(matchAbs[1]) - margin,
|
||||
toR = parseFloat(matchAbs[1]) + margin;
|
||||
return parseFloat(got) >= fromR && parseFloat(got) <= toR;
|
||||
let margin = parseFloat(matchAbs[2]);
|
||||
return inRange(margin, got, matchAbs[1]);
|
||||
} else if (matchRe) { // regex: /a,b,.*/
|
||||
return got.match(matchRe[1]);
|
||||
} else {
|
||||
|
||||
+3
-26
@@ -6,10 +6,9 @@ var d3 = require('d3-queue');
|
||||
|
||||
module.exports = function () {
|
||||
this.initializeEnv = (callback) => {
|
||||
this.DEFAULT_PORT = 5000;
|
||||
// OSX builds on Travis hit a timeout of ~2000 from time to time
|
||||
this.DEFAULT_TIMEOUT = 5000;
|
||||
this.setDefaultTimeout(this.DEFAULT_TIMEOUT);
|
||||
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
|
||||
this.TIMEOUT = process.env.CUCUMBER_TIMEOUT && parseInt(process.env.CUCUMBER_TIMEOUT) || 3000;
|
||||
this.setDefaultTimeout(this.TIMEOUT);
|
||||
this.ROOT_FOLDER = process.cwd();
|
||||
this.OSM_USER = 'osrm';
|
||||
this.OSM_GENERATOR = 'osrm-test';
|
||||
@@ -25,8 +24,6 @@ module.exports = function () {
|
||||
this.BIN_PATH = path.resolve(this.ROOT_FOLDER, 'build');
|
||||
this.DEFAULT_INPUT_FORMAT = 'osm';
|
||||
this.DEFAULT_ORIGIN = [1,1];
|
||||
this.LAUNCH_TIMEOUT = 1000;
|
||||
this.SHUTDOWN_TIMEOUT = 10000;
|
||||
this.DEFAULT_LOAD_METHOD = 'datastore';
|
||||
this.OSRM_ROUTED_LOG_FILE = path.resolve(this.TEST_FOLDER, 'osrm-routed.log');
|
||||
this.ERROR_LOG_FILE = path.resolve(this.TEST_FOLDER, 'error.log');
|
||||
@@ -51,26 +48,6 @@ module.exports = function () {
|
||||
console.info(util.format('Node Version', process.version));
|
||||
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** PLease upgrade to Node 4.+ to run OSRM cucumber tests');
|
||||
|
||||
if (process.env.OSRM_PORT) {
|
||||
this.OSRM_PORT = parseInt(process.env.OSRM_PORT);
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(util.format('Port set to %d', this.OSRM_PORT));
|
||||
} else {
|
||||
this.OSRM_PORT = this.DEFAULT_PORT;
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(util.format('Using default port %d', this.OSRM_PORT));
|
||||
}
|
||||
|
||||
if (process.env.OSRM_TIMEOUT) {
|
||||
this.OSRM_TIMEOUT = parseInt(process.env.OSRM_TIMEOUT);
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(util.format('Timeout set to %d', this.OSRM_TIMEOUT));
|
||||
} else {
|
||||
this.OSRM_TIMEOUT = this.DEFAULT_TIMEOUT;
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(util.format('Using default timeout %d', this.OSRM_TIMEOUT));
|
||||
}
|
||||
|
||||
fs.exists(this.TEST_FOLDER, (exists) => {
|
||||
if (!exists) throw new Error(util.format('*** Test folder %s doesn\'t exist.', this.TEST_FOLDER));
|
||||
callback();
|
||||
|
||||
@@ -24,10 +24,12 @@ module.exports = function () {
|
||||
});
|
||||
|
||||
this.After((scenario, callback) => {
|
||||
this.setExtractArgs('');
|
||||
this.setContractArgs('');
|
||||
if (this.loadMethod === 'directly' && !!this.OSRMLoader.loader) this.OSRMLoader.shutdown(callback);
|
||||
else callback();
|
||||
this.setExtractArgs('', () => {
|
||||
this.setContractArgs('', () => {
|
||||
if (this.loadMethod === 'directly' && !!this.OSRMLoader.loader) this.OSRMLoader.shutdown(callback);
|
||||
else callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.Around('@stress', (scenario, callback) => {
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = function () {
|
||||
};
|
||||
|
||||
this.sendRequest = (baseUri, parameters, callback) => {
|
||||
var limit = Timeout(this.OSRM_TIMEOUT, { err: { statusCode: 408 } });
|
||||
var limit = Timeout(this.TIMEOUT, { err: { statusCode: 408 } });
|
||||
|
||||
var runRequest = (cb) => {
|
||||
var params = this.paramsToString(parameters);
|
||||
|
||||
@@ -12,7 +12,7 @@ var OSRMBaseLoader = class {
|
||||
}
|
||||
|
||||
launch (callback) {
|
||||
var limit = Timeout(this.scope.LAUNCH_TIMEOUT, { err: this.scope.RoutedError('Launching osrm-routed timed out.') });
|
||||
var limit = Timeout(this.scope.TIMEOUT, { err: this.scope.RoutedError('Launching osrm-routed timed out.') });
|
||||
|
||||
var runLaunch = (cb) => {
|
||||
this.osrmUp(() => {
|
||||
@@ -24,7 +24,7 @@ var OSRMBaseLoader = class {
|
||||
}
|
||||
|
||||
shutdown (callback) {
|
||||
var limit = Timeout(this.scope.SHUTDOWN_TIMEOUT, { err: this.scope.RoutedError('Shutting down osrm-routed timed out.')});
|
||||
var limit = Timeout(this.scope.TIMEOUT, { err: this.scope.RoutedError('Shutting down osrm-routed timed out.')});
|
||||
|
||||
var runShutdown = (cb) => {
|
||||
this.osrmDown(cb);
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = function () {
|
||||
|
||||
this.requestUrl = (path, callback) => {
|
||||
var uri = this.query = [this.HOST, path].join('/'),
|
||||
limit = Timeout(this.OSRM_TIMEOUT, { err: { statusCode: 408 } });
|
||||
limit = Timeout(this.TIMEOUT, { err: { statusCode: 408 } });
|
||||
|
||||
function runRequest (cb) {
|
||||
request(uri, cb);
|
||||
@@ -127,12 +127,28 @@ module.exports = function () {
|
||||
}
|
||||
};
|
||||
|
||||
this.summary = (instructions) => {
|
||||
if (instructions) {
|
||||
return instructions.legs.map(l => l.summary).join(',');
|
||||
}
|
||||
};
|
||||
|
||||
this.wayList = (instructions) => {
|
||||
return this.extractInstructionList(instructions, s => s.name);
|
||||
};
|
||||
|
||||
this.bearingList = (instructions) => {
|
||||
return this.extractInstructionList(instructions, s => s.maneuver.bearing_after);
|
||||
return this.extractInstructionList(instructions, s => s.maneuver.bearing_before + '->' + s.maneuver.bearing_after);
|
||||
};
|
||||
|
||||
this.annotationList = (instructions) => {
|
||||
// Pull out all the distinct segment distances, skipping the arrive
|
||||
// instructions, and the leading 0 on all timestamps arrays.
|
||||
var pairs = [];
|
||||
for (var i in instructions.annotation.duration) {
|
||||
pairs.push(instructions.annotation.duration[i]+':'+instructions.annotation.distance[i]);
|
||||
}
|
||||
return pairs.join(',');
|
||||
};
|
||||
|
||||
this.turnList = (instructions) => {
|
||||
@@ -142,6 +158,9 @@ module.exports = function () {
|
||||
case 'depart':
|
||||
case 'arrive':
|
||||
return v.maneuver.type;
|
||||
case 'on ramp':
|
||||
case 'off ramp':
|
||||
return v.maneuver.type + ' ' + v.maneuver.modifier;
|
||||
case 'roundabout':
|
||||
return 'roundabout-exit-' + v.maneuver.exit;
|
||||
case 'rotary':
|
||||
@@ -149,6 +168,8 @@ module.exports = function () {
|
||||
return v.rotary_name + '-exit-' + v.maneuver.exit;
|
||||
else
|
||||
return 'rotary-exit-' + v.maneuver.exit;
|
||||
case 'roundabout turn':
|
||||
return v.maneuver.type + ' ' + v.maneuver.modifier + ' exit-' + v.maneuver.exit;
|
||||
// FIXME this is a little bit over-simplistic for merge/fork instructions
|
||||
default:
|
||||
return v.maneuver.type + ' ' + v.maneuver.modifier;
|
||||
@@ -157,6 +178,19 @@ module.exports = function () {
|
||||
.join(',');
|
||||
};
|
||||
|
||||
this.intersectionList = (instructions) => {
|
||||
return instructions.legs.reduce((m, v) => m.concat(v.steps), [])
|
||||
.map( v => {
|
||||
return v.intersections
|
||||
.map( intersection => {
|
||||
var string = intersection.entry[0]+':'+intersection.bearings[0], i;
|
||||
for( i = 1; i < intersection.bearings.length; ++i )
|
||||
string = string + ' ' + intersection.entry[i]+':'+intersection.bearings[i];
|
||||
return string;
|
||||
}).join(',');
|
||||
}).join(';');
|
||||
};
|
||||
|
||||
this.modeList = (instructions) => {
|
||||
return this.extractInstructionList(instructions, s => s.mode);
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ module.exports = function () {
|
||||
var afterRequest = (err, res, body) => {
|
||||
if (err) return cb(err);
|
||||
if (body && body.length) {
|
||||
var instructions, bearings, turns, modes, times, distances;
|
||||
var instructions, bearings, turns, modes, times, distances, summary, intersections;
|
||||
|
||||
var json = JSON.parse(body);
|
||||
|
||||
@@ -41,9 +41,11 @@ module.exports = function () {
|
||||
instructions = this.wayList(json.routes[0]);
|
||||
bearings = this.bearingList(json.routes[0]);
|
||||
turns = this.turnList(json.routes[0]);
|
||||
intersections = this.intersectionList(json.routes[0]);
|
||||
modes = this.modeList(json.routes[0]);
|
||||
times = this.timeList(json.routes[0]);
|
||||
distances = this.distanceList(json.routes[0]);
|
||||
summary = this.summary(json.routes[0]);
|
||||
}
|
||||
|
||||
if (headers.has('status')) {
|
||||
@@ -66,6 +68,10 @@ module.exports = function () {
|
||||
if (headers.has('route')) {
|
||||
got.route = (instructions || '').trim();
|
||||
|
||||
if (headers.has('summary')) {
|
||||
got.summary = (summary || '').trim();
|
||||
}
|
||||
|
||||
if (headers.has('alternative')) {
|
||||
// TODO examine more than first alternative?
|
||||
got.alternative ='';
|
||||
@@ -103,6 +109,10 @@ module.exports = function () {
|
||||
}
|
||||
}
|
||||
|
||||
if (headers.has('intersections')) {
|
||||
got.intersections = (intersections || '').trim();
|
||||
}
|
||||
|
||||
var putValue = (key, value) => {
|
||||
if (headers.has(key)) got[key] = instructions ? value : '';
|
||||
};
|
||||
|
||||
@@ -14,8 +14,8 @@ Feature: Compass bearing
|
||||
| ab |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 315,0 |
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 0->315,315->0|
|
||||
|
||||
Scenario: Bearing when going west
|
||||
Given the node map
|
||||
@@ -26,8 +26,8 @@ Feature: Compass bearing
|
||||
| ab |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 270,0 |
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 0->270,270->0|
|
||||
|
||||
Scenario: Bearing af 45 degree intervals
|
||||
Given the node map
|
||||
@@ -48,14 +48,14 @@ Feature: Compass bearing
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| x | a | xa,xa | 0,0 |
|
||||
| x | b | xb,xb | 315,0 |
|
||||
| x | c | xc,xc | 270,0 |
|
||||
| x | d | xd,xd | 225,0 |
|
||||
| x | e | xe,xe | 180,0 |
|
||||
| x | f | xf,xf | 135,0 |
|
||||
| x | g | xg,xg | 90,0 |
|
||||
| x | h | xh,xh | 45,0 |
|
||||
| x | a | xa,xa | 0->0,0->0|
|
||||
| x | b | xb,xb | 0->315,315->0|
|
||||
| x | c | xc,xc | 0->270,270->0|
|
||||
| x | d | xd,xd | 0->225,225->0|
|
||||
| x | e | xe,xe | 0->180,180->0|
|
||||
| x | f | xf,xf | 0->135,135->0|
|
||||
| x | g | xg,xg | 0->90,90->0|
|
||||
| x | h | xh,xh | 0->45,45->0|
|
||||
|
||||
Scenario: Bearing in a roundabout
|
||||
Given the node map
|
||||
@@ -76,9 +76,9 @@ Feature: Compass bearing
|
||||
| ha | yes |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| c | b | cd,de,ef,fg,gh,ha,ab,ab | 270,225,180,135,90,45,0,0 |
|
||||
| g | f | gh,ha,ab,bc,cd,de,ef,ef | 90,45,0,315,270,225,180,0 |
|
||||
| from | to | route | bearing |
|
||||
| c | b | cd,de,ef,fg,gh,ha,ab,ab | 0->270,270->225,225->180,180->135,135->90,90->45,45->0,0->0 |
|
||||
| g | f | gh,ha,ab,bc,cd,de,ef,ef | 0->90,90->45,45->0,0->315,315->270,270->225,225->180,180->0 |
|
||||
|
||||
Scenario: Bearing should stay constant when zig-zagging
|
||||
Given the node map
|
||||
@@ -97,7 +97,7 @@ Feature: Compass bearing
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| a | h | ab,bc,cd,de,ef,fg,gh,gh | 0,135,0,135,0,135,0,0 |
|
||||
| a | h | ab,bc,cd,de,ef,fg,gh,gh | 0->0,0->135,135->0,0->135,135->0,0->135,135->0,0->0 |
|
||||
|
||||
Scenario: Bearings on an east-west way.
|
||||
Given the node map
|
||||
@@ -108,37 +108,37 @@ Feature: Compass bearing
|
||||
| abcdef |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| a | b | abcdef,abcdef | 90,0 |
|
||||
| a | c | abcdef,abcdef | 90,0 |
|
||||
| a | d | abcdef,abcdef | 90,0 |
|
||||
| a | e | abcdef,abcdef | 90,0 |
|
||||
| a | f | abcdef,abcdef | 90,0 |
|
||||
| b | a | abcdef,abcdef | 270,0 |
|
||||
| b | c | abcdef,abcdef | 90,0 |
|
||||
| b | d | abcdef,abcdef | 90,0 |
|
||||
| b | e | abcdef,abcdef | 90,0 |
|
||||
| b | f | abcdef,abcdef | 90,0 |
|
||||
| c | a | abcdef,abcdef | 270,0 |
|
||||
| c | b | abcdef,abcdef | 270,0 |
|
||||
| c | d | abcdef,abcdef | 90,0 |
|
||||
| c | e | abcdef,abcdef | 90,0 |
|
||||
| c | f | abcdef,abcdef | 90,0 |
|
||||
| d | a | abcdef,abcdef | 270,0 |
|
||||
| d | b | abcdef,abcdef | 270,0 |
|
||||
| d | c | abcdef,abcdef | 270,0 |
|
||||
| d | e | abcdef,abcdef | 90,0 |
|
||||
| d | f | abcdef,abcdef | 90,0 |
|
||||
| e | a | abcdef,abcdef | 270,0 |
|
||||
| e | b | abcdef,abcdef | 270,0 |
|
||||
| e | c | abcdef,abcdef | 270,0 |
|
||||
| e | d | abcdef,abcdef | 270,0 |
|
||||
| e | f | abcdef,abcdef | 90,0 |
|
||||
| f | a | abcdef,abcdef | 270,0 |
|
||||
| f | b | abcdef,abcdef | 270,0 |
|
||||
| f | c | abcdef,abcdef | 270,0 |
|
||||
| f | d | abcdef,abcdef | 270,0 |
|
||||
| f | e | abcdef,abcdef | 270,0 |
|
||||
| from | to | route | bearing |
|
||||
| a | b | abcdef,abcdef | 0->90,90->0 |
|
||||
| a | c | abcdef,abcdef | 0->90,90->0 |
|
||||
| a | d | abcdef,abcdef | 0->90,90->0 |
|
||||
| a | e | abcdef,abcdef | 0->90,90->0 |
|
||||
| a | f | abcdef,abcdef | 0->90,90->0 |
|
||||
| b | a | abcdef,abcdef | 0->270,270->0 |
|
||||
| b | c | abcdef,abcdef | 0->90,90->0 |
|
||||
| b | d | abcdef,abcdef | 0->90,90->0 |
|
||||
| b | e | abcdef,abcdef | 0->90,90->0 |
|
||||
| b | f | abcdef,abcdef | 0->90,90->0 |
|
||||
| c | a | abcdef,abcdef | 0->270,270->0 |
|
||||
| c | b | abcdef,abcdef | 0->270,270->0 |
|
||||
| c | d | abcdef,abcdef | 0->90,90->0 |
|
||||
| c | e | abcdef,abcdef | 0->90,90->0 |
|
||||
| c | f | abcdef,abcdef | 0->90,90->0 |
|
||||
| d | a | abcdef,abcdef | 0->270,270->0 |
|
||||
| d | b | abcdef,abcdef | 0->270,270->0 |
|
||||
| d | c | abcdef,abcdef | 0->270,270->0 |
|
||||
| d | e | abcdef,abcdef | 0->90,90->0 |
|
||||
| d | f | abcdef,abcdef | 0->90,90->0 |
|
||||
| e | a | abcdef,abcdef | 0->270,270->0 |
|
||||
| e | b | abcdef,abcdef | 0->270,270->0 |
|
||||
| e | c | abcdef,abcdef | 0->270,270->0 |
|
||||
| e | d | abcdef,abcdef | 0->270,270->0 |
|
||||
| e | f | abcdef,abcdef | 0->90,90->0 |
|
||||
| f | a | abcdef,abcdef | 0->270,270->0 |
|
||||
| f | b | abcdef,abcdef | 0->270,270->0 |
|
||||
| f | c | abcdef,abcdef | 0->270,270->0 |
|
||||
| f | d | abcdef,abcdef | 0->270,270->0 |
|
||||
| f | e | abcdef,abcdef | 0->270,270->0 |
|
||||
|
||||
Scenario: Bearings at high latitudes
|
||||
# The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html,
|
||||
@@ -161,19 +161,19 @@ Feature: Compass bearing
|
||||
| bd |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 0,0 |
|
||||
| b | c | bc,bc | 90,0 |
|
||||
| c | d | cd,cd | 180,0 |
|
||||
| d | a | da,da | 270,0 |
|
||||
| b | a | ab,ab | 180,0 |
|
||||
| c | b | bc,bc | 270,0 |
|
||||
| d | c | cd,cd | 0,0 |
|
||||
| a | d | da,da | 90,0 |
|
||||
| a | c | ac,ac | 45,0 |
|
||||
| c | a | ac,ac | 225,0 |
|
||||
| b | d | bd,bd | 135,0 |
|
||||
| d | b | bd,bd | 315,0 |
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 0->0,0->0 |
|
||||
| b | c | bc,bc | 0->90,90->0 |
|
||||
| c | d | cd,cd | 0->180,180->0 |
|
||||
| d | a | da,da | 0->270,270->0 |
|
||||
| b | a | ab,ab | 0->180,180->0 |
|
||||
| c | b | bc,bc | 0->270,270->0 |
|
||||
| d | c | cd,cd | 0->0,0->0 |
|
||||
| a | d | da,da | 0->90,90->0 |
|
||||
| a | c | ac,ac | 0->45,45->0 |
|
||||
| c | a | ac,ac | 0->225,225->0 |
|
||||
| b | d | bd,bd | 0->135,135->0 |
|
||||
| d | b | bd,bd | 0->315,315->0 |
|
||||
|
||||
Scenario: Bearings at high negative latitudes
|
||||
# The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html,
|
||||
@@ -196,16 +196,16 @@ Feature: Compass bearing
|
||||
| bd |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 180,0 |
|
||||
| b | c | bc,bc | 90,0 |
|
||||
| c | d | cd,cd | 0,0 |
|
||||
| d | a | da,da | 270,0 |
|
||||
| b | a | ab,ab | 0,0 |
|
||||
| c | b | bc,bc | 270,0 |
|
||||
| d | c | cd,cd | 180,0 |
|
||||
| a | d | da,da | 90,0 |
|
||||
| a | c | ac,ac | 135,0 |
|
||||
| c | a | ac,ac | 315,0 |
|
||||
| b | d | bd,bd | 45,0 |
|
||||
| d | b | bd,bd | 225,0 |
|
||||
| from | to | route | bearing |
|
||||
| a | b | ab,ab | 0->180,180->0 |
|
||||
| b | c | bc,bc | 0->90,90->0 |
|
||||
| c | d | cd,cd | 0->0,0->0 |
|
||||
| d | a | da,da | 0->270,270->0 |
|
||||
| b | a | ab,ab | 0->0,0->0 |
|
||||
| c | b | bc,bc | 0->270,270->0 |
|
||||
| d | c | cd,cd | 0->180,180->0 |
|
||||
| a | d | da,da | 0->90,90->0 |
|
||||
| a | c | ac,ac | 0->135,135->0 |
|
||||
| c | a | ac,ac | 0->315,315->0 |
|
||||
| b | d | bd,bd | 0->45,45->0 |
|
||||
| d | b | bd,bd | 0->225,225->0 |
|
||||
|
||||
@@ -15,11 +15,11 @@ Feature: Bearing parameter
|
||||
|
||||
When I route I should get
|
||||
| from | to | bearings | route | bearing |
|
||||
| b | c | 90 90 | ad,ad | 90,0 |
|
||||
| b | c | 90 90 | ad,ad | 0->90,90->0|
|
||||
| b | c | 180 90 | | |
|
||||
| b | c | 80 100 | ad,ad | 90,0 |
|
||||
| b | c | 80 100 | ad,ad | 0->90,90->0|
|
||||
| b | c | 79 100 | | |
|
||||
| b | c | 79,11 100 | ad,ad | 90,0 |
|
||||
| b | c | 79,11 100 | ad,ad | 0->90,90->0|
|
||||
|
||||
Scenario: Testbot - Intial bearing in simple case
|
||||
Given the node map
|
||||
@@ -35,10 +35,10 @@ Feature: Bearing parameter
|
||||
When I route I should get
|
||||
| from | to | bearings | route | bearing |
|
||||
| 0 | c | 0 0 | | |
|
||||
| 0 | c | 45 45 | bc,bc | 45 ~3% |
|
||||
| 0 | c | 45 45 | bc,bc | 0->44,44->0 +- 1|
|
||||
| 0 | c | 85 85 | | |
|
||||
| 0 | c | 95 95 | | |
|
||||
| 0 | c | 135 135 | ac,ac | 135 ~1% |
|
||||
| 0 | c | 135 135 | ac,ac | 0->135,135->0 +- 1|
|
||||
| 0 | c | 180 180 | | |
|
||||
|
||||
Scenario: Testbot - Initial bearing on split way
|
||||
@@ -55,19 +55,19 @@ Feature: Bearing parameter
|
||||
|
||||
When I route I should get
|
||||
| from | to | bearings | route | bearing |
|
||||
| 0 | b | 10 10 | bc,bc | 0,0 |
|
||||
| 0 | b | 90 90 | ab,ab | 90,0 |
|
||||
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
|
||||
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
|
||||
# The returned bearing is wrong here, it's based on the snapped
|
||||
# coordinates, not the acutal edge bearing. This should be
|
||||
# fixed one day, but it's only a problem when we snap two vias
|
||||
# to the same point - DP
|
||||
#| 0 | b | 170 170 | da | 180 |
|
||||
#| 0 | b | 189 189 | da | 180 |
|
||||
| 0 | 1 | 90 270 | ab,bc,cd,cd | 90,0,270,0 |
|
||||
| 1 | d | 10 10 | bc,bc | 0,0 |
|
||||
| 1 | d | 90 90 | ab,bc,cd,da,da | 90,0,270,180,0 |
|
||||
| 1 | 0 | 189 189 | da,da | 180,0 |
|
||||
| 1 | d | 270 270 | cd,cd | 270,0 |
|
||||
| 0 | 1 | 90 270 | ab,bc,cd,cd | 0->90,90->0,0->270,270->0 |
|
||||
| 1 | d | 10 10 | bc,bc | 0->0,0->0 |
|
||||
| 1 | d | 90 90 | ab,bc,cd,da,da | 0->90,90->0,0->270,270->180,180->0 |
|
||||
| 1 | 0 | 189 189 | da,da | 0->180,180->0 |
|
||||
| 1 | d | 270 270 | cd,cd | 0->270,270->0 |
|
||||
| 1 | d | 349 349 | | |
|
||||
|
||||
Scenario: Testbot - Initial bearing in all direction
|
||||
@@ -101,11 +101,11 @@ Feature: Bearing parameter
|
||||
|
||||
When I route I should get
|
||||
| from | to | bearings | route | bearing |
|
||||
| 0 | q | 0 90 | ia,ab,bc,cd,de,ef,fg,gh,ha,ha | 0,90,180,180,270,270,0,0,90,0 |
|
||||
| 0 | a | 45 90 | jb,bc,cd,de,ef,fg,gh,ha,ha | 45,180,180,270,270,0,0,90,0 |
|
||||
| 0 | q | 90 90 | kc,cd,de,ef,fg,gh,ha,ha | 90,180,270,270,0,0,90,0 |
|
||||
| 0 | a | 135 90 | ld,de,ef,fg,gh,ha,ha | 135,270,270,0,0,90,0 |
|
||||
| 0 | a | 180 90 | me,ef,fg,gh,ha,ha | 180,270,0,0,90,0 |
|
||||
| 0 | a | 225 90 | nf,fg,gh,ha,ha | 225,0,0,90,0 |
|
||||
| 0 | a | 270 90 | og,gh,ha,ha | 270,0,90,0 |
|
||||
| 0 | a | 315 90 | ph,ha,ha | 315,90,0 |
|
||||
| 0 | q | 0 90 | ia,ab,bc,cd,de,ef,fg,gh,ha,ha | 0->0,0->90,90->180,180->180,180->270,270->270,270->0,0->0,0->90,90->0 |
|
||||
| 0 | a | 45 90 | jb,bc,cd,de,ef,fg,gh,ha,ha | 0->45,45->180,180->180,180->270,270->270,270->0,0->0,0->90,90->0 |
|
||||
| 0 | q | 90 90 | kc,cd,de,ef,fg,gh,ha,ha | 0->90,90->180,180->270,270->270,270->0,0->0,0->90,90->0 |
|
||||
| 0 | a | 135 90 | ld,de,ef,fg,gh,ha,ha | 0->135,135->270,270->270,270->0,0->0,0->90,90->0 |
|
||||
| 0 | a | 180 90 | me,ef,fg,gh,ha,ha | 0->180,180->270,270->0,0->0,0->90,90->0 |
|
||||
| 0 | a | 225 90 | nf,fg,gh,ha,ha | 0->225,225->0,0->0,0->90,90->0 |
|
||||
| 0 | a | 270 90 | og,gh,ha,ha | 0->270,270->0,0->90,90->0 |
|
||||
| 0 | a | 315 90 | ph,ha,ha | 0->315,315->90,90->0 |
|
||||
|
||||
@@ -18,5 +18,5 @@ Feature: Geometry Compression
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | distance | speed |
|
||||
| b | e | abcdef,abcdef | 589m | 36 km/h |
|
||||
| e | b | abcdef,abcdef | 589m | 36 km/h |
|
||||
| b | e | abcdef,abcdef | 588.8m | 36 km/h |
|
||||
| e | b | abcdef,abcdef | 588.8m | 36 km/h |
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
@routing @continue_straight @via @testbot
|
||||
Feature: U-turns at via points
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Continue straight at waypoints enabled by default
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
| | e | f | g |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| cd |
|
||||
| be |
|
||||
| dg |
|
||||
| ef |
|
||||
| fg |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,e,c | ab,be,be,ef,fg,dg,cd,cd |
|
||||
|
||||
Scenario: Query parameter to disallow changing direction at all waypoints
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
| | e | f | g |
|
||||
|
||||
And the query options
|
||||
| continue_straight | false |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| cd |
|
||||
| be |
|
||||
| dg |
|
||||
| ef |
|
||||
| fg |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,e,c | ab,be,be,be,bc,bc |
|
||||
|
||||
Scenario: Instructions at waypoints at u-turns
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
| | e | f | g |
|
||||
|
||||
And the query options
|
||||
| continue_straight | false |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| cd |
|
||||
| be |
|
||||
| dg |
|
||||
| ef |
|
||||
| fg |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,e,c | ab,be,be,be,bc,bc |
|
||||
|
||||
Scenario: u-turn mixed with non-uturn vias
|
||||
Given the node map
|
||||
| a | 1 | b | 3 | c | 5 | d |
|
||||
| | | 2 | | | | 4 |
|
||||
| | | e | | f | | g |
|
||||
|
||||
And the query options
|
||||
| continue_straight | false |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| ab | no |
|
||||
| bc | no |
|
||||
| cd | no |
|
||||
| be | yes |
|
||||
| dg | no |
|
||||
| ef | no |
|
||||
| fg | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| 1,2,3,4,5 | ab,be,be,be,ef,fg,dg,cd,bc,bc,bc,cd,dg,dg,dg,cd,cd |
|
||||
|
||||
@@ -104,3 +104,18 @@ Feature: Basic Map Matching
|
||||
| trace | matchings |
|
||||
| dcba | hg,gf,fe |
|
||||
| efgh | ab,bc,cd |
|
||||
|
||||
Scenario: Testbot - Duration details
|
||||
Given the node map
|
||||
| a | b | c | d | e | | g | h |
|
||||
| | | i | | | | | |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcdegh | no |
|
||||
| ci | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | matchings | annotation |
|
||||
| abeh | abcedgh | 1:9.897633,0:0,1:10.008842,1:10.008842,1:10.008842,0:0,2:20.017685,1:10.008842 |
|
||||
| abci | abc,ci | 1:9.897633,0:0,1:10.008842,0:0.111209,1:10.010367 |
|
||||
|
||||
@@ -12,7 +12,6 @@ Feature: Testbot - Travel mode
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - Always announce mode change
|
||||
Given the node map
|
||||
| a | b | c | d |
|
||||
@@ -28,7 +27,6 @@ Feature: Testbot - Travel mode
|
||||
| a | d | foo,foo,foo,foo | driving,river downstream,driving,driving |
|
||||
| b | d | foo,foo,foo | river downstream,driving,driving |
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - Compressed Modes
|
||||
Given the node map
|
||||
| a | b | c | d | e | f | g |
|
||||
@@ -44,7 +42,6 @@ Feature: Testbot - Travel mode
|
||||
| a | g | road,liquid,solid,solid | driving,river downstream,driving,driving |
|
||||
| c | g | liquid,solid,solid | river downstream,driving,driving |
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - Modes in each direction, different forward/backward speeds
|
||||
Given the node map
|
||||
| | 0 | 1 | |
|
||||
@@ -79,7 +76,7 @@ Feature: Testbot - Travel mode
|
||||
| 0 | 1 | ab,ab | steps down,steps down | 60s +-1 |
|
||||
| 1 | 0 | ab,ab | steps up,steps up | 60s +-1 |
|
||||
|
||||
@oneway @mokob @2166
|
||||
@oneway
|
||||
Scenario: Testbot - Modes for oneway, different forward/backward speeds
|
||||
Given the node map
|
||||
| a | b |
|
||||
@@ -107,7 +104,7 @@ Feature: Testbot - Travel mode
|
||||
| a | b | ab,ab | steps down,steps down |
|
||||
| b | a | | |
|
||||
|
||||
@oneway @mokob @2166
|
||||
@oneway
|
||||
Scenario: Testbot - Modes for reverse oneway, different forward/backward speeds
|
||||
Given the node map
|
||||
| a | b |
|
||||
@@ -135,7 +132,7 @@ Feature: Testbot - Travel mode
|
||||
| a | b | | |
|
||||
| b | a | ab,ab | steps up,steps up |
|
||||
|
||||
@via @mokob @2166
|
||||
@via
|
||||
Scenario: Testbot - Mode should be set at via points
|
||||
Given the node map
|
||||
| a | 1 | b |
|
||||
@@ -149,7 +146,6 @@ Feature: Testbot - Travel mode
|
||||
| a,1,b | ab,ab,ab,ab | river downstream,river downstream,river downstream,river downstream |
|
||||
| b,1,a | ab,ab,ab,ab | river upstream,river upstream,river upstream,river upstream |
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - Starting at a tricky node
|
||||
Given the node map
|
||||
| | a | | | |
|
||||
@@ -164,7 +160,6 @@ Feature: Testbot - Travel mode
|
||||
| from | to | route | modes |
|
||||
| b | a | ab,ab | river upstream,river upstream |
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - Mode changes on straight way without name change
|
||||
Given the node map
|
||||
| a | 1 | b | 2 | c |
|
||||
@@ -204,7 +199,6 @@ Feature: Testbot - Travel mode
|
||||
| b | d | bc,cd,cd | route,driving,driving |
|
||||
| a | f | ab,bc,cd,de,ef,ef | driving,route,driving,driving,driving,driving |
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - Modes, triangle map
|
||||
Given the node map
|
||||
| | | | | | | d |
|
||||
@@ -239,7 +233,6 @@ Feature: Testbot - Travel mode
|
||||
| a | d | abc,cd,cd | driving,driving,driving |
|
||||
| d | a | de,ce,abc,abc | driving,river upstream,driving,driving |
|
||||
|
||||
@mokob @2166
|
||||
Scenario: Testbot - River in the middle
|
||||
Given the node map
|
||||
| a | b | c | | |
|
||||
|
||||
@@ -24,12 +24,12 @@ Feature: Projection to nearest point on road
|
||||
Scenario: Projection onto way at high latitudes, 1km distance
|
||||
When I route I should get
|
||||
| from | to | route | bearing | distance |
|
||||
| b | a | abc,abc | 225,0 +-1 | 1000m +- 7 |
|
||||
| b | c | abc,abc | 45,0 +-1 | 1000m +- 7 |
|
||||
| a | d | abc,abc | 45,0 +-1 | 1000m +- 7 |
|
||||
| d | a | abc,abc | 225,0 +-1 | 1000m +- 7 |
|
||||
| c | d | abc,abc | 225,0 +-1 | 1000m +- 8 |
|
||||
| d | c | abc,abc | 45 +-1 | 1000m +- 8 |
|
||||
| b | a | abc,abc | 0->225,225->0 | 1000m +- 7 |
|
||||
| b | c | abc,abc | 0->45,45->0 | 1000m +- 7 |
|
||||
| a | d | abc,abc | 0->45,45->0 | 1000m +- 7 |
|
||||
| d | a | abc,abc | 0->225,225->0 | 1000m +- 7 |
|
||||
| c | d | abc,abc | 0->225,224->0 | 1000m +- 8 |
|
||||
| d | c | abc,abc | 0->44,45->0 | 1000m +- 8 |
|
||||
|
||||
Scenario: Projection onto way at high latitudes, no distance
|
||||
When I route I should get
|
||||
|
||||
@@ -55,13 +55,13 @@ Feature: Status messages
|
||||
| ? | 400 | URL string malformed close to position 1: "/?" |
|
||||
| route/v1/driving | 400 | URL string malformed close to position 17: "ing" |
|
||||
| route/v1/driving/ | 400 | URL string malformed close to position 18: "ng/" |
|
||||
| route/v1/driving/1 | 400 | Query string malformed close to position 1 |
|
||||
| route/v1/driving/1 | 400 | Query string malformed close to position 19 |
|
||||
| route/v1/driving/1,1 | 400 | Number of coordinates needs to be at least two. |
|
||||
| route/v1/driving/1,1,1 | 400 | Query string malformed close to position 3 |
|
||||
| route/v1/driving/x | 400 | Query string malformed close to position 0 |
|
||||
| route/v1/driving/x,y | 400 | Query string malformed close to position 0 |
|
||||
| route/v1/driving/1,1; | 400 | Query string malformed close to position 3 |
|
||||
| route/v1/driving/1,1;1 | 400 | Query string malformed close to position 5 |
|
||||
| route/v1/driving/1,1;1,1,1 | 400 | Query string malformed close to position 7 |
|
||||
| route/v1/driving/1,1;x | 400 | Query string malformed close to position 3 |
|
||||
| route/v1/driving/1,1;x,y | 400 | Query string malformed close to position 3 |
|
||||
| route/v1/driving/1,1,1 | 400 | Query string malformed close to position 21 |
|
||||
| route/v1/driving/x | 400 | Query string malformed close to position 18 |
|
||||
| route/v1/driving/x,y | 400 | Query string malformed close to position 18 |
|
||||
| route/v1/driving/1,1; | 400 | Query string malformed close to position 21 |
|
||||
| route/v1/driving/1,1;1 | 400 | Query string malformed close to position 23 |
|
||||
| route/v1/driving/1,1;1,1,1 | 400 | Query string malformed close to position 25 |
|
||||
| route/v1/driving/1,1;x | 400 | Query string malformed close to position 21 |
|
||||
| route/v1/driving/1,1;x,y | 400 | Query string malformed close to position 21 |
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
@routing @basic @testbot
|
||||
Feature: Basic Routing
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
@smallest
|
||||
Scenario: Checking
|
||||
Given the node map
|
||||
| a | b | | c | d | e |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| cd |
|
||||
| de |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | summary |
|
||||
| a | e | ab,bc,cd,de,de | ab, bc |
|
||||
| e | a | de,cd,bc,ab,ab | de, bc |
|
||||
| a | b | ab,ab | ab |
|
||||
| b | d | bc,cd,cd | bc, cd |
|
||||
|
||||
@smallest
|
||||
Scenario: Check handling empty values
|
||||
Given the node map
|
||||
| a | b | | c | | d | f |
|
||||
| | | | | | e |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | ab |
|
||||
| bc | bc |
|
||||
| cd | |
|
||||
| de | de |
|
||||
| df | df |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | summary |
|
||||
| e | a | de,,bc,ab,ab | de, bc |
|
||||
|
||||
@smallest @todo
|
||||
Scenario: Summaries when routing on a simple network
|
||||
Given the node map
|
||||
| a | b |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | summary |
|
||||
| a | b | ab,ab | ab |
|
||||
| b | a | ab,ab | ab |
|
||||
|
||||
@repeated
|
||||
Scenario: Check handling empty values
|
||||
Given the node map
|
||||
| f | | | x | | |
|
||||
| b | c | d | e | 1 | g |
|
||||
| a | | | y | | |
|
||||
|
||||
And the ways
|
||||
| nodes | name | # |
|
||||
| ab | first | |
|
||||
| bc | first | |
|
||||
| cd | first | |
|
||||
| deg | second | |
|
||||
| bf | third | |
|
||||
| xey | cross |we need this because phantom node segments are not considered for the summary |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | summary |
|
||||
| a | 1 | first,first,second,second | first, second |
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
@routing @speed @traffic
|
||||
Feature: Traffic - turn penalties applied to turn onto which a phantom node snaps
|
||||
|
||||
Background: Simple map with phantom nodes
|
||||
Given the node map
|
||||
| | 1 | | 2 | | 3 | |
|
||||
| a:1 | | b:2 | | c:3 | | d:4 |
|
||||
| | | | | | | |
|
||||
| | | e:5 | | f:6 | | g:7 |
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ab | primary |
|
||||
| bc | primary |
|
||||
| cd | primary |
|
||||
|
||||
| be | primary |
|
||||
| cf | primary |
|
||||
| dg | primary |
|
||||
And the profile "testbot"
|
||||
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
|
||||
And the extract extra arguments "--generate-edge-lookup"
|
||||
|
||||
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
|
||||
Given the turn penalty file
|
||||
"""
|
||||
1,2,5,0
|
||||
3,4,7,-20
|
||||
"""
|
||||
And the contract extra arguments "--turn-penalty-file penalties.csv"
|
||||
When I route I should get
|
||||
| from | to | route | speed | time |
|
||||
| a | e | ab,be,be | 36 km/h | 40s +-1 |
|
||||
| 1 | e | ab,be,be | 36 km/h | 30s +-1 |
|
||||
| b | f | bc,cf,cf | 36 km/h | 40s +-1 |
|
||||
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 |
|
||||
| c | g | cd,dg,dg | 71 km/h | 20s +-1 |
|
||||
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 |
|
||||
@@ -46,7 +46,6 @@ Feature: Via points
|
||||
| a,d,c | abc,bd,bd,bd,abc,abc |
|
||||
| c,d,a | abc,bd,bd,bd,abc,abc |
|
||||
|
||||
@mokob
|
||||
Scenario: Multiple via points
|
||||
Given the node map
|
||||
| a | | | | e | f | g | |
|
||||
@@ -149,6 +148,47 @@ Feature: Via points
|
||||
| a,d,c | abc,bd,bd,bd,abc,abc |
|
||||
| c,d,a | abc,bd,bd,bd,abc,abc |
|
||||
|
||||
# See issue #2349
|
||||
Scenario: Via point at a dead end with oneway
|
||||
Given the node map
|
||||
| a | b | c |
|
||||
| | d | |
|
||||
| | e | |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abc | no |
|
||||
| bd | no |
|
||||
| ed | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,d,c | abc,bd,bd,bd,abc,abc |
|
||||
| c,d,a | abc,bd,bd,bd,abc,abc |
|
||||
|
||||
# See issue #2349
|
||||
@bug
|
||||
Scenario: Via point at a dead end with oneway
|
||||
Given the node map
|
||||
| a | b | c |
|
||||
| | d | |
|
||||
| | e | g |
|
||||
| | f | |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abc | no |
|
||||
| bd | no |
|
||||
| ed | yes |
|
||||
| dg | yes |
|
||||
| ef | no |
|
||||
| fg | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,d,c | abc,bd,bd,bd,abc,abc |
|
||||
| c,d,a | abc,bd,bd,bd,abc,abc |
|
||||
|
||||
# See issue #1896
|
||||
Scenario: Via point at a dead end with barrier
|
||||
Given the profile "car"
|
||||
|
||||
@@ -84,6 +84,7 @@ class Contractor
|
||||
const std::string &edge_segment_lookup_path,
|
||||
const std::string &edge_penalty_path,
|
||||
const std::vector<std::string> &segment_speed_path,
|
||||
const std::vector<std::string> &turn_penalty_path,
|
||||
const std::string &nodes_filename,
|
||||
const std::string &geometry_filename,
|
||||
const std::string &datasource_names_filename,
|
||||
|
||||
@@ -81,6 +81,7 @@ struct ContractorConfig
|
||||
double core_factor;
|
||||
|
||||
std::vector<std::string> segment_speed_lookup_paths;
|
||||
std::vector<std::string> turn_penalty_lookup_paths;
|
||||
std::string datasource_indexes_path;
|
||||
std::string datasource_names_path;
|
||||
};
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace contractor
|
||||
class IteratorbasedCRC32
|
||||
{
|
||||
public:
|
||||
bool using_hardware() const { return use_hardware_implementation; }
|
||||
bool UsingHardware() const { return use_hardware_implementation; }
|
||||
|
||||
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); }
|
||||
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = DetectHardwareSupport(); }
|
||||
|
||||
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
|
||||
{
|
||||
@@ -31,11 +31,11 @@ class IteratorbasedCRC32
|
||||
|
||||
if (use_hardware_implementation)
|
||||
{
|
||||
crc = compute_in_hardware(data, sizeof(value_type));
|
||||
crc = ComputeInHardware(data, sizeof(value_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
crc = compute_in_software(data, sizeof(value_type));
|
||||
crc = ComputeInSoftware(data, sizeof(value_type));
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class IteratorbasedCRC32
|
||||
}
|
||||
|
||||
private:
|
||||
bool detect_hardware_support() const
|
||||
bool DetectHardwareSupport() const
|
||||
{
|
||||
static const int sse42_bit = 0x00100000;
|
||||
const unsigned ecx = cpuid();
|
||||
@@ -51,14 +51,14 @@ class IteratorbasedCRC32
|
||||
return sse42_found;
|
||||
}
|
||||
|
||||
unsigned compute_in_software(const char *str, unsigned len)
|
||||
unsigned ComputeInSoftware(const char *str, unsigned len)
|
||||
{
|
||||
crc_processor.process_bytes(str, len);
|
||||
return crc_processor.checksum();
|
||||
}
|
||||
|
||||
// adapted from http://byteworm.com/2010/10/13/crc32/
|
||||
unsigned compute_in_hardware(const char *str, unsigned len)
|
||||
unsigned ComputeInHardware(const char *str, unsigned len)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
unsigned q = len / sizeof(unsigned);
|
||||
@@ -114,7 +114,7 @@ struct RangebasedCRC32
|
||||
return crc32(std::begin(iterable), std::end(iterable));
|
||||
}
|
||||
|
||||
bool using_hardware() const { return crc32.using_hardware(); }
|
||||
bool UsingHardware() const { return crc32.UsingHardware(); }
|
||||
|
||||
private:
|
||||
IteratorbasedCRC32 crc32;
|
||||
|
||||
@@ -115,7 +115,7 @@ class GraphContractor
|
||||
{
|
||||
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
|
||||
|
||||
inline ContractorThreadData *getThreadData()
|
||||
inline ContractorThreadData *GetThreadData()
|
||||
{
|
||||
bool exists = false;
|
||||
auto &ref = data.local(exists);
|
||||
@@ -302,7 +302,7 @@ class GraphContractor
|
||||
[this, &node_priorities, &node_depth,
|
||||
&thread_data_list](const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
||||
{
|
||||
node_priorities[x] =
|
||||
@@ -424,7 +424,7 @@ class GraphContractor
|
||||
[this, &node_priorities, &remaining_nodes,
|
||||
&thread_data_list](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||
// determine independent node set
|
||||
for (auto i = range.begin(), end = range.end(); i != end; ++i)
|
||||
{
|
||||
@@ -481,7 +481,7 @@ class GraphContractor
|
||||
[this, &remaining_nodes,
|
||||
&thread_data_list](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||
for (int position = range.begin(), end = range.end();
|
||||
position != end; ++position)
|
||||
{
|
||||
@@ -495,7 +495,7 @@ class GraphContractor
|
||||
DeleteGrainSize),
|
||||
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||
for (int position = range.begin(), end = range.end(); position != end;
|
||||
++position)
|
||||
{
|
||||
@@ -547,7 +547,7 @@ class GraphContractor
|
||||
[this, &node_priorities, &remaining_nodes, &node_depth,
|
||||
&thread_data_list](const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
ContractorThreadData *data = thread_data_list.GetThreadData();
|
||||
for (int position = range.begin(), end = range.end(); position != end;
|
||||
++position)
|
||||
{
|
||||
@@ -561,7 +561,7 @@ class GraphContractor
|
||||
number_of_contracted_nodes += end_independent_nodes_idx - begin_independent_nodes_idx;
|
||||
remaining_nodes.resize(begin_independent_nodes_idx);
|
||||
|
||||
p.printStatus(number_of_contracted_nodes);
|
||||
p.PrintStatus(number_of_contracted_nodes);
|
||||
++current_level;
|
||||
}
|
||||
|
||||
@@ -627,7 +627,7 @@ class GraphContractor
|
||||
Edge new_edge;
|
||||
for (const auto node : util::irange(0u, number_of_nodes))
|
||||
{
|
||||
p.printStatus(node);
|
||||
p.PrintStatus(node);
|
||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const NodeID target = contractor_graph->GetTarget(edge);
|
||||
@@ -710,9 +710,9 @@ class GraphContractor
|
||||
|
||||
inline void Dijkstra(const int max_distance,
|
||||
const unsigned number_of_targets,
|
||||
const int maxNodes,
|
||||
const int max_nodes,
|
||||
ContractorThreadData &data,
|
||||
const NodeID middleNode)
|
||||
const NodeID middle_node)
|
||||
{
|
||||
|
||||
ContractorHeap &heap = data.heap;
|
||||
@@ -723,7 +723,7 @@ class GraphContractor
|
||||
{
|
||||
const NodeID node = heap.DeleteMin();
|
||||
const auto distance = heap.GetKey(node);
|
||||
if (++nodes > maxNodes)
|
||||
if (++nodes > max_nodes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -742,7 +742,7 @@ class GraphContractor
|
||||
}
|
||||
}
|
||||
|
||||
RelaxNode(node, middleNode, distance, heap);
|
||||
RelaxNode(node, middle_node, distance, heap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1032,7 +1032,7 @@ class GraphContractor
|
||||
}
|
||||
// tie breaking
|
||||
if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
|
||||
bias(node, target))
|
||||
Bias(node, target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1061,7 +1061,7 @@ class GraphContractor
|
||||
}
|
||||
// tie breaking
|
||||
if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
|
||||
bias(node, target))
|
||||
Bias(node, target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1071,7 +1071,7 @@ class GraphContractor
|
||||
}
|
||||
|
||||
// This bias function takes up 22 assembly instructions in total on X86
|
||||
inline bool bias(const NodeID a, const NodeID b) const
|
||||
inline bool Bias(const NodeID a, const NodeID b) const
|
||||
{
|
||||
const unsigned short hasha = fast_hash(a);
|
||||
const unsigned short hashb = fast_hash(b);
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace json
|
||||
namespace detail
|
||||
{
|
||||
|
||||
std::string instructionTypeToString(extractor::guidance::TurnType type);
|
||||
std::string instructionModifierToString(extractor::guidance::DirectionModifier modifier);
|
||||
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
|
||||
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
|
||||
|
||||
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
|
||||
|
||||
@@ -48,13 +48,25 @@ template <typename ForwardIter> util::json::String makePolyline(ForwardIter begi
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
util::json::Object makeGeoJSONLineString(ForwardIter begin, ForwardIter end)
|
||||
util::json::Object makeGeoJSONGeometry(ForwardIter begin, ForwardIter end)
|
||||
{
|
||||
auto num_coordinates = std::distance(begin, end);
|
||||
BOOST_ASSERT(num_coordinates != 0);
|
||||
util::json::Object geojson;
|
||||
geojson.values["type"] = "LineString";
|
||||
util::json::Array coordinates;
|
||||
std::transform(begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
|
||||
geojson.values["coordinates"] = std::move(coordinates);
|
||||
if (num_coordinates > 1)
|
||||
{
|
||||
geojson.values["type"] = "LineString";
|
||||
util::json::Array coordinates;
|
||||
std::transform(begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
|
||||
geojson.values["coordinates"] = std::move(coordinates);
|
||||
}
|
||||
else if (num_coordinates > 0)
|
||||
{
|
||||
geojson.values["type"] = "Point";
|
||||
util::json::Array coordinates;
|
||||
coordinates.values.push_back(detail::coordinateToLonLat(*begin));
|
||||
geojson.values["coordinates"] = std::move(coordinates);
|
||||
}
|
||||
return geojson;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ struct MatchParameters : public RouteParameters
|
||||
{
|
||||
MatchParameters()
|
||||
: RouteParameters(false,
|
||||
false,
|
||||
false,
|
||||
RouteParameters::GeometriesType::Polyline,
|
||||
RouteParameters::OverviewType::Simplified,
|
||||
|
||||
@@ -69,7 +69,7 @@ class RouteAPI : public BaseAPI
|
||||
}
|
||||
|
||||
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
|
||||
return json::makeGeoJSONLineString(begin, end);
|
||||
return json::makeGeoJSONGeometry(begin, end);
|
||||
}
|
||||
|
||||
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
|
||||
@@ -93,8 +93,8 @@ class RouteAPI : public BaseAPI
|
||||
|
||||
auto leg_geometry = guidance::assembleGeometry(
|
||||
BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom);
|
||||
auto leg = guidance::assembleLeg(path_data, leg_geometry, phantoms.source_phantom,
|
||||
phantoms.target_phantom, reversed_target);
|
||||
auto leg = guidance::assembleLeg(facade, path_data, leg_geometry, phantoms.source_phantom,
|
||||
phantoms.target_phantom, reversed_target, parameters.steps);
|
||||
|
||||
if (parameters.steps)
|
||||
{
|
||||
@@ -132,6 +132,7 @@ class RouteAPI : public BaseAPI
|
||||
|
||||
guidance::trimShortSegments(steps, leg_geometry);
|
||||
leg.steps = guidance::postProcess(std::move(steps));
|
||||
leg.steps = guidance::collapseTurns(std::move(leg.steps));
|
||||
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), leg_geometry,
|
||||
phantoms.source_phantom,
|
||||
phantoms.target_phantom);
|
||||
@@ -169,15 +170,39 @@ class RouteAPI : public BaseAPI
|
||||
leg_geometry.locations.begin() + step.geometry_end));
|
||||
}
|
||||
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
|
||||
return static_cast<util::json::Value>(json::makeGeoJSONLineString(
|
||||
return static_cast<util::json::Value>(json::makeGeoJSONGeometry(
|
||||
leg_geometry.locations.begin() + step.geometry_begin,
|
||||
leg_geometry.locations.begin() + step.geometry_end));
|
||||
});
|
||||
}
|
||||
|
||||
return json::makeRoute(route,
|
||||
auto result = json::makeRoute(route,
|
||||
json::makeRouteLegs(std::move(legs), std::move(step_geometries)),
|
||||
std::move(json_overview));
|
||||
|
||||
if (parameters.annotation)
|
||||
{
|
||||
util::json::Array durations;
|
||||
util::json::Array distances;
|
||||
for (const auto idx : util::irange<std::size_t>(0UL, leg_geometries.size()))
|
||||
{
|
||||
auto &leg_geometry = leg_geometries[idx];
|
||||
std::for_each(leg_geometry.annotations.begin(),
|
||||
leg_geometry.annotations.end(),
|
||||
[this, &durations, &distances](const guidance::LegGeometry::Annotation &step) {
|
||||
durations.values.push_back(step.duration);
|
||||
distances.values.push_back(step.distance);
|
||||
});
|
||||
}
|
||||
|
||||
util::json::Object details;
|
||||
details.values["distance"] = std::move(distances);
|
||||
details.values["duration"] = std::move(durations);
|
||||
|
||||
result.values["annotation"] = std::move(details);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const RouteParameters ¶meters;
|
||||
|
||||
@@ -72,17 +72,20 @@ struct RouteParameters : public BaseParameters
|
||||
template <typename... Args>
|
||||
RouteParameters(const bool steps_,
|
||||
const bool alternatives_,
|
||||
const bool annotation_,
|
||||
const GeometriesType geometries_,
|
||||
const OverviewType overview_,
|
||||
const boost::optional<bool> continue_straight_,
|
||||
Args... args_)
|
||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||
geometries{geometries_}, overview{overview_}, continue_straight{continue_straight_}
|
||||
annotation{annotation_}, geometries{geometries_}, overview{overview_},
|
||||
continue_straight{continue_straight_}
|
||||
{
|
||||
}
|
||||
|
||||
bool steps = false;
|
||||
bool alternatives = false;
|
||||
bool annotation = false;
|
||||
GeometriesType geometries = GeometriesType::Polyline;
|
||||
OverviewType overview = OverviewType::Simplified;
|
||||
boost::optional<bool> continue_straight;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
// RFC 4648 "The Base16, Base32, and Base64 Data Encodings"
|
||||
// See: https://tools.ietf.org/html/rfc4648
|
||||
|
||||
@@ -36,9 +39,6 @@ using BinaryFromBase64 = boost::archive::iterators::transform_width<
|
||||
6 // from a sequence of 6 bit
|
||||
>;
|
||||
} // ns detail
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
|
||||
// Exposes all data access interfaces to the algorithms via base class ptr
|
||||
|
||||
#include "extractor/edge_based_node.hpp"
|
||||
#include "extractor/external_memory_node.hpp"
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "engine/phantom_node.hpp"
|
||||
#include "extractor/edge_based_node.hpp"
|
||||
#include "extractor/external_memory_node.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/string_util.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -17,9 +19,9 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -90,47 +92,47 @@ class BaseDataFacade
|
||||
virtual extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0;
|
||||
|
||||
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
const util::Coordinate north_east) = 0;
|
||||
const util::Coordinate north_east) const = 0;
|
||||
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance) = 0;
|
||||
const float max_distance) const = 0;
|
||||
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range) = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) = 0;
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance) = 0;
|
||||
const double max_distance) const = 0;
|
||||
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) = 0;
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance) = 0;
|
||||
const double max_distance) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) = 0;
|
||||
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const = 0;
|
||||
|
||||
virtual unsigned GetCheckSum() const = 0;
|
||||
|
||||
@@ -145,6 +147,15 @@ class BaseDataFacade
|
||||
virtual std::string GetTimestamp() const = 0;
|
||||
|
||||
virtual bool GetContinueStraightDefault() const = 0;
|
||||
|
||||
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
|
||||
|
||||
virtual util::guidance::BearingClass
|
||||
GetBearingClass(const BearingClassID bearing_class_id) const = 0;
|
||||
|
||||
virtual EntryClassID GetEntryClassID(const EdgeID eid) const = 0;
|
||||
|
||||
virtual util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,20 +6,24 @@
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
|
||||
#include "engine/geospatial_query.hpp"
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "storage/storage_config.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/io.hpp"
|
||||
#include "util/range_table.hpp"
|
||||
#include "util/rectangle.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
#include "util/range_table.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/rectangle.hpp"
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
@@ -55,8 +59,8 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
private:
|
||||
using super = BaseDataFacade;
|
||||
using QueryGraph = util::StaticGraph<typename super::EdgeData>;
|
||||
using InputEdge = typename QueryGraph::InputEdge;
|
||||
using RTreeLeaf = typename super::RTreeLeaf;
|
||||
using InputEdge = QueryGraph::InputEdge;
|
||||
using RTreeLeaf = super::RTreeLeaf;
|
||||
using InternalRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, false>::vector, false>;
|
||||
using InternalGeospatialQuery = GeospatialQuery<InternalRTree, BaseDataFacade>;
|
||||
@@ -68,7 +72,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
std::unique_ptr<QueryGraph> m_query_graph;
|
||||
std::string m_timestamp;
|
||||
|
||||
std::shared_ptr<util::ShM<util::Coordinate, false>::vector> m_coordinate_list;
|
||||
util::ShM<util::Coordinate, false>::vector m_coordinate_list;
|
||||
util::ShM<NodeID, false>::vector m_via_node_list;
|
||||
util::ShM<unsigned, false>::vector m_name_ID_list;
|
||||
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_list;
|
||||
@@ -82,12 +86,24 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
util::ShM<std::string, false>::vector m_datasource_names;
|
||||
extractor::ProfileProperties m_profile_properties;
|
||||
|
||||
boost::thread_specific_ptr<InternalRTree> m_static_rtree;
|
||||
boost::thread_specific_ptr<InternalGeospatialQuery> m_geospatial_query;
|
||||
std::unique_ptr<InternalRTree> m_static_rtree;
|
||||
std::unique_ptr<InternalGeospatialQuery> m_geospatial_query;
|
||||
boost::filesystem::path ram_index_path;
|
||||
boost::filesystem::path file_index_path;
|
||||
util::RangeTable<16, false> m_name_table;
|
||||
|
||||
// bearing classes by node based node
|
||||
util::ShM<BearingClassID, false>::vector m_bearing_class_id_table;
|
||||
// entry class IDs by edge based egde
|
||||
util::ShM<EntryClassID, false>::vector m_entry_class_id_list;
|
||||
// the look-up table for entry classes. An entry class lists the possibility of entry for all
|
||||
// available turns. For every turn, there is an associated entry class.
|
||||
util::ShM<util::guidance::EntryClass, false>::vector m_entry_class_table;
|
||||
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
|
||||
// at an intersection
|
||||
util::RangeTable<16, false> m_bearing_ranges_table;
|
||||
util::ShM<DiscreteBearing, false>::vector m_bearing_values_table;
|
||||
|
||||
void LoadProfileProperties(const boost::filesystem::path &properties_path)
|
||||
{
|
||||
boost::filesystem::ifstream in_stream(properties_path);
|
||||
@@ -96,7 +112,8 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
throw util::exception("Could not open " + properties_path.string() + " for reading.");
|
||||
}
|
||||
|
||||
in_stream.read(reinterpret_cast<char*>(&m_profile_properties), sizeof(m_profile_properties));
|
||||
in_stream.read(reinterpret_cast<char *>(&m_profile_properties),
|
||||
sizeof(m_profile_properties));
|
||||
}
|
||||
|
||||
void LoadTimestamp(const boost::filesystem::path ×tamp_path)
|
||||
@@ -112,8 +129,8 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
|
||||
void LoadGraph(const boost::filesystem::path &hsgr_path)
|
||||
{
|
||||
typename util::ShM<typename QueryGraph::NodeArrayEntry, false>::vector node_list;
|
||||
typename util::ShM<typename QueryGraph::EdgeArrayEntry, false>::vector edge_list;
|
||||
util::ShM<QueryGraph::NodeArrayEntry, false>::vector node_list;
|
||||
util::ShM<QueryGraph::EdgeArrayEntry, false>::vector edge_list;
|
||||
|
||||
util::SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
|
||||
|
||||
@@ -138,12 +155,12 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
extractor::QueryNode current_node;
|
||||
unsigned number_of_coordinates = 0;
|
||||
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
|
||||
m_coordinate_list = std::make_shared<std::vector<util::Coordinate>>(number_of_coordinates);
|
||||
m_coordinate_list.resize(number_of_coordinates);
|
||||
for (unsigned i = 0; i < number_of_coordinates; ++i)
|
||||
{
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(extractor::QueryNode));
|
||||
m_coordinate_list->at(i) = util::Coordinate(current_node.lon, current_node.lat);
|
||||
BOOST_ASSERT(m_coordinate_list->at(i).IsValid());
|
||||
m_coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
|
||||
BOOST_ASSERT(m_coordinate_list[i].IsValid());
|
||||
}
|
||||
|
||||
boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
|
||||
@@ -153,6 +170,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
m_name_ID_list.resize(number_of_edges);
|
||||
m_turn_instruction_list.resize(number_of_edges);
|
||||
m_travel_mode_list.resize(number_of_edges);
|
||||
m_entry_class_id_list.resize(number_of_edges);
|
||||
|
||||
extractor::OriginalEdgeData current_edge_data;
|
||||
for (unsigned i = 0; i < number_of_edges; ++i)
|
||||
@@ -163,6 +181,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
m_name_ID_list[i] = current_edge_data.name_id;
|
||||
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
|
||||
m_travel_mode_list[i] = current_edge_data.travel_mode;
|
||||
m_entry_class_id_list[i] = current_edge_data.entry_classid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +242,8 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
boost::filesystem::ifstream datasources_stream(datasource_indexes_file, std::ios::binary);
|
||||
if (!datasources_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + datasource_indexes_file.string() + " for reading!");
|
||||
throw util::exception("Could not open " + datasource_indexes_file.string() +
|
||||
" for reading!");
|
||||
}
|
||||
BOOST_ASSERT(datasources_stream);
|
||||
|
||||
@@ -240,7 +260,8 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
boost::filesystem::ifstream datasourcenames_stream(datasource_names_file, std::ios::binary);
|
||||
if (!datasourcenames_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + datasource_names_file.string() + " for reading!");
|
||||
throw util::exception("Could not open " + datasource_names_file.string() +
|
||||
" for reading!");
|
||||
}
|
||||
BOOST_ASSERT(datasourcenames_stream);
|
||||
std::string name;
|
||||
@@ -252,7 +273,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
|
||||
void LoadRTree()
|
||||
{
|
||||
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
|
||||
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
|
||||
|
||||
m_static_rtree.reset(new InternalRTree(ram_index_path, file_index_path, m_coordinate_list));
|
||||
m_geospatial_query.reset(
|
||||
@@ -276,6 +297,52 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
}
|
||||
}
|
||||
|
||||
void LoadIntersectionClasses(const boost::filesystem::path &intersection_class_file)
|
||||
{
|
||||
std::ifstream intersection_stream(intersection_class_file.string(), std::ios::binary);
|
||||
if (!intersection_stream)
|
||||
throw util::exception("Could not open " + intersection_class_file.string() +
|
||||
" for reading.");
|
||||
|
||||
if (!util::readAndCheckFingerprint(intersection_stream))
|
||||
throw util::exception("Fingeprint does not match in " +
|
||||
intersection_class_file.string());
|
||||
|
||||
{
|
||||
util::SimpleLogger().Write(logINFO) << "Loading Bearing Class IDs";
|
||||
std::vector<BearingClassID> bearing_class_id;
|
||||
if (!util::deserializeVector(intersection_stream, bearing_class_id))
|
||||
throw util::exception("Reading from " + intersection_class_file.string() + " failed.");
|
||||
|
||||
m_bearing_class_id_table.resize(bearing_class_id.size());
|
||||
std::copy(bearing_class_id.begin(), bearing_class_id.end(),
|
||||
&m_bearing_class_id_table[0]);
|
||||
}
|
||||
{
|
||||
util::SimpleLogger().Write(logINFO) << "Loading Bearing Classes";
|
||||
// read the range table
|
||||
intersection_stream >> m_bearing_ranges_table;
|
||||
std::vector<util::guidance::BearingClass> bearing_classes;
|
||||
// and the actual bearing values
|
||||
std::uint64_t num_bearings;
|
||||
intersection_stream >> num_bearings;
|
||||
m_bearing_values_table.resize(num_bearings);
|
||||
intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]),
|
||||
sizeof(m_bearing_values_table[0]) * num_bearings);
|
||||
if (!static_cast<bool>(intersection_stream))
|
||||
throw util::exception("Reading from " + intersection_class_file.string() + " failed.");
|
||||
}
|
||||
{
|
||||
util::SimpleLogger().Write(logINFO) << "Loading Entry Classes";
|
||||
std::vector<util::guidance::EntryClass> entry_classes;
|
||||
if (!util::deserializeVector(intersection_stream, entry_classes))
|
||||
throw util::exception("Reading from " + intersection_class_file.string() + " failed.");
|
||||
|
||||
m_entry_class_table.resize(entry_classes.size());
|
||||
std::copy(entry_classes.begin(), entry_classes.end(), &m_entry_class_table[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~InternalDataFacade()
|
||||
{
|
||||
@@ -283,7 +350,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
m_geospatial_query.reset();
|
||||
}
|
||||
|
||||
explicit InternalDataFacade(const storage::StorageConfig& config)
|
||||
explicit InternalDataFacade(const storage::StorageConfig &config)
|
||||
{
|
||||
ram_index_path = config.ram_index_path;
|
||||
file_index_path = config.file_index_path;
|
||||
@@ -301,8 +368,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
LoadGeometries(config.geometries_path);
|
||||
|
||||
util::SimpleLogger().Write() << "loading datasource info";
|
||||
LoadDatasourceInfo(config.datasource_names_path,
|
||||
config.datasource_indexes_path);
|
||||
LoadDatasourceInfo(config.datasource_names_path, config.datasource_indexes_path);
|
||||
|
||||
util::SimpleLogger().Write() << "loading timestamp";
|
||||
LoadTimestamp(config.timestamp_path);
|
||||
@@ -312,6 +378,12 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
|
||||
util::SimpleLogger().Write() << "loading street names";
|
||||
LoadStreetNames(config.names_data_path);
|
||||
|
||||
util::SimpleLogger().Write() << "loading rtree";
|
||||
LoadRTree();
|
||||
|
||||
util::SimpleLogger().Write() << "loading intersection class data";
|
||||
LoadIntersectionClasses(config.intersection_class_path);
|
||||
}
|
||||
|
||||
// search graph access
|
||||
@@ -360,7 +432,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
// node and edge information access
|
||||
util::Coordinate GetCoordinateOfNode(const unsigned id) const override final
|
||||
{
|
||||
return m_coordinate_list->at(id);
|
||||
return m_coordinate_list[id];
|
||||
}
|
||||
|
||||
extractor::guidance::TurnInstruction
|
||||
@@ -375,13 +447,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
}
|
||||
|
||||
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
const util::Coordinate north_east) override final
|
||||
const util::Coordinate north_east) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
const util::RectangleInt2D bbox{south_west.lon, north_east.lon, south_west.lat,
|
||||
north_east.lat};
|
||||
return m_geospatial_query->Search(bbox);
|
||||
@@ -389,13 +457,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance) override final
|
||||
const float max_distance) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
|
||||
}
|
||||
@@ -404,13 +468,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance,
|
||||
bearing, bearing_range);
|
||||
@@ -418,13 +478,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results) override final
|
||||
const unsigned max_results) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
|
||||
}
|
||||
@@ -432,13 +488,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance) override final
|
||||
const double max_distance) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
|
||||
}
|
||||
@@ -447,13 +499,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, bearing,
|
||||
bearing_range);
|
||||
@@ -464,40 +512,27 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance,
|
||||
bearing, bearing_range);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance) override final
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate, const double max_distance) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate) override final
|
||||
const util::Coordinate input_coordinate) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate);
|
||||
@@ -507,13 +542,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, bearing, bearing_range);
|
||||
@@ -522,13 +553,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get())
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, bearing, bearing_range);
|
||||
@@ -588,8 +615,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
result_nodes.clear();
|
||||
result_nodes.reserve(end - begin);
|
||||
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
|
||||
{
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
|
||||
result_nodes.emplace_back(edge.node_id);
|
||||
});
|
||||
}
|
||||
@@ -604,8 +630,7 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
result_weights.clear();
|
||||
result_weights.reserve(end - begin);
|
||||
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
|
||||
{
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
|
||||
result_weights.emplace_back(edge.weight);
|
||||
});
|
||||
}
|
||||
@@ -632,11 +657,9 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
}
|
||||
else
|
||||
{
|
||||
std::for_each(m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
|
||||
[&](const uint8_t &datasource_id)
|
||||
{
|
||||
result_datasources.push_back(datasource_id);
|
||||
});
|
||||
std::for_each(
|
||||
m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
|
||||
[&](const uint8_t &datasource_id) { result_datasources.push_back(datasource_id); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,7 +672,40 @@ class InternalDataFacade final : public BaseDataFacade
|
||||
|
||||
std::string GetTimestamp() const override final { return m_timestamp; }
|
||||
|
||||
bool GetContinueStraightDefault() const override final { return m_profile_properties.continue_straight_at_waypoint; }
|
||||
bool GetContinueStraightDefault() const override final
|
||||
{
|
||||
return m_profile_properties.continue_straight_at_waypoint;
|
||||
}
|
||||
|
||||
BearingClassID GetBearingClassID(const NodeID nid) const override final
|
||||
{
|
||||
return m_bearing_class_id_table.at(nid);
|
||||
}
|
||||
|
||||
util::guidance::BearingClass
|
||||
GetBearingClass(const BearingClassID bearing_class_id) const override final
|
||||
{
|
||||
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
|
||||
auto range = m_bearing_ranges_table.GetRange(bearing_class_id);
|
||||
|
||||
util::guidance::BearingClass result;
|
||||
|
||||
for (auto itr = m_bearing_values_table.begin() + range.front();
|
||||
itr != m_bearing_values_table.begin() + range.back() + 1; ++itr)
|
||||
result.add(*itr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID eid) const override final
|
||||
{
|
||||
return m_entry_class_id_list.at(eid);
|
||||
}
|
||||
|
||||
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
|
||||
{
|
||||
return m_entry_class_table.at(entry_class_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,20 @@
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_memory.hpp"
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
|
||||
#include "engine/geospatial_query.hpp"
|
||||
#include "util/make_unique.hpp"
|
||||
#include "util/range_table.hpp"
|
||||
#include "util/rectangle.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
#include "util/make_unique.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/rectangle.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@@ -29,9 +33,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -46,16 +50,15 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
private:
|
||||
using super = BaseDataFacade;
|
||||
using QueryGraph = util::StaticGraph<EdgeData, true>;
|
||||
using GraphNode = typename QueryGraph::NodeArrayEntry;
|
||||
using GraphEdge = typename QueryGraph::EdgeArrayEntry;
|
||||
using NameIndexBlock = typename util::RangeTable<16, true>::BlockT;
|
||||
using InputEdge = typename QueryGraph::InputEdge;
|
||||
using RTreeLeaf = typename super::RTreeLeaf;
|
||||
using GraphNode = QueryGraph::NodeArrayEntry;
|
||||
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
||||
using IndexBlock = util::RangeTable<16, true>::BlockT;
|
||||
using InputEdge = QueryGraph::InputEdge;
|
||||
using RTreeLeaf = super::RTreeLeaf;
|
||||
using SharedRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
|
||||
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
|
||||
using TimeStampedRTreePair = std::pair<unsigned, std::shared_ptr<SharedRTree>>;
|
||||
using RTreeNode = typename SharedRTree::TreeNode;
|
||||
using RTreeNode = SharedRTree::TreeNode;
|
||||
|
||||
storage::SharedDataLayout *data_layout;
|
||||
char *shared_memory;
|
||||
@@ -70,9 +73,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
std::unique_ptr<storage::SharedMemory> m_layout_memory;
|
||||
std::unique_ptr<storage::SharedMemory> m_large_memory;
|
||||
std::string m_timestamp;
|
||||
extractor::ProfileProperties* m_profile_properties;
|
||||
extractor::ProfileProperties *m_profile_properties;
|
||||
|
||||
std::shared_ptr<util::ShM<util::Coordinate, true>::vector> m_coordinate_list;
|
||||
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
|
||||
util::ShM<NodeID, true>::vector m_via_node_list;
|
||||
util::ShM<unsigned, true>::vector m_name_ID_list;
|
||||
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
|
||||
@@ -88,12 +91,24 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
|
||||
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
|
||||
|
||||
boost::thread_specific_ptr<std::pair<unsigned, std::shared_ptr<SharedRTree>>> m_static_rtree;
|
||||
boost::thread_specific_ptr<SharedGeospatialQuery> m_geospatial_query;
|
||||
std::unique_ptr<SharedRTree> m_static_rtree;
|
||||
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
|
||||
boost::filesystem::path file_index_path;
|
||||
|
||||
std::shared_ptr<util::RangeTable<16, true>> m_name_table;
|
||||
|
||||
// bearing classes by node based node
|
||||
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
|
||||
// entry class IDs
|
||||
util::ShM<EntryClassID, true>::vector m_entry_class_id_list;
|
||||
// the look-up table for entry classes. An entry class lists the possibility of entry for all
|
||||
// available turns. Such a class id is stored with every edge.
|
||||
util::ShM<util::guidance::EntryClass, true>::vector m_entry_class_table;
|
||||
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
|
||||
// at an intersection
|
||||
std::shared_ptr<util::RangeTable<16, true>> m_bearing_ranges_table;
|
||||
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
|
||||
|
||||
void LoadChecksum()
|
||||
{
|
||||
m_check_sum = *data_layout->GetBlockPtr<unsigned>(shared_memory,
|
||||
@@ -103,8 +118,8 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
void LoadProfileProperties()
|
||||
{
|
||||
m_profile_properties =
|
||||
data_layout->GetBlockPtr<extractor::ProfileProperties>(shared_memory, storage::SharedDataLayout::PROPERTIES);
|
||||
m_profile_properties = data_layout->GetBlockPtr<extractor::ProfileProperties>(
|
||||
shared_memory, storage::SharedDataLayout::PROPERTIES);
|
||||
}
|
||||
|
||||
void LoadTimestamp()
|
||||
@@ -119,17 +134,15 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
void LoadRTree()
|
||||
{
|
||||
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
|
||||
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
|
||||
|
||||
auto tree_ptr = data_layout->GetBlockPtr<RTreeNode>(
|
||||
shared_memory, storage::SharedDataLayout::R_SEARCH_TREE);
|
||||
m_static_rtree.reset(new TimeStampedRTreePair(
|
||||
CURRENT_TIMESTAMP,
|
||||
util::make_unique<SharedRTree>(
|
||||
tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
|
||||
file_index_path, m_coordinate_list)));
|
||||
m_static_rtree.reset(new SharedRTree(
|
||||
tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
|
||||
file_index_path, m_coordinate_list));
|
||||
m_geospatial_query.reset(
|
||||
new SharedGeospatialQuery(*m_static_rtree->second, m_coordinate_list, *this));
|
||||
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
|
||||
}
|
||||
|
||||
void LoadGraph()
|
||||
@@ -140,9 +153,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
auto graph_edges_ptr = data_layout->GetBlockPtr<GraphEdge>(
|
||||
shared_memory, storage::SharedDataLayout::GRAPH_EDGE_LIST);
|
||||
|
||||
typename util::ShM<GraphNode, true>::vector node_list(
|
||||
util::ShM<GraphNode, true>::vector node_list(
|
||||
graph_nodes_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_NODE_LIST]);
|
||||
typename util::ShM<GraphEdge, true>::vector edge_list(
|
||||
util::ShM<GraphEdge, true>::vector edge_list(
|
||||
graph_edges_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_EDGE_LIST]);
|
||||
m_query_graph.reset(new QueryGraph(node_list, edge_list));
|
||||
}
|
||||
@@ -151,37 +164,42 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
{
|
||||
auto coordinate_list_ptr = data_layout->GetBlockPtr<util::Coordinate>(
|
||||
shared_memory, storage::SharedDataLayout::COORDINATE_LIST);
|
||||
m_coordinate_list = util::make_unique<util::ShM<util::Coordinate, true>::vector>(
|
||||
coordinate_list_ptr,
|
||||
m_coordinate_list.reset(coordinate_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
|
||||
|
||||
auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
|
||||
shared_memory, storage::SharedDataLayout::TRAVEL_MODE);
|
||||
typename util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
|
||||
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
|
||||
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
|
||||
m_travel_mode_list = std::move(travel_mode_list);
|
||||
|
||||
auto turn_instruction_list_ptr =
|
||||
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
|
||||
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
|
||||
typename util::ShM<extractor::guidance::TurnInstruction, true>::vector
|
||||
turn_instruction_list(
|
||||
turn_instruction_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
|
||||
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
|
||||
turn_instruction_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
|
||||
m_turn_instruction_list = std::move(turn_instruction_list);
|
||||
|
||||
auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
|
||||
shared_memory, storage::SharedDataLayout::NAME_ID_LIST);
|
||||
typename util::ShM<unsigned, true>::vector name_id_list(
|
||||
util::ShM<unsigned, true>::vector name_id_list(
|
||||
name_id_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_ID_LIST]);
|
||||
m_name_ID_list = std::move(name_id_list);
|
||||
|
||||
auto entry_class_id_list_ptr = data_layout->GetBlockPtr<EntryClassID>(
|
||||
shared_memory, storage::SharedDataLayout::ENTRY_CLASSID);
|
||||
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
|
||||
entry_class_id_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASSID]);
|
||||
m_entry_class_id_list = std::move(entry_class_id_list);
|
||||
}
|
||||
|
||||
void LoadViaNodeList()
|
||||
{
|
||||
auto via_node_list_ptr = data_layout->GetBlockPtr<NodeID>(
|
||||
shared_memory, storage::SharedDataLayout::VIA_NODE_LIST);
|
||||
typename util::ShM<NodeID, true>::vector via_node_list(
|
||||
util::ShM<NodeID, true>::vector via_node_list(
|
||||
via_node_list_ptr, data_layout->num_entries[storage::SharedDataLayout::VIA_NODE_LIST]);
|
||||
m_via_node_list = std::move(via_node_list);
|
||||
}
|
||||
@@ -190,16 +208,16 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
{
|
||||
auto offsets_ptr = data_layout->GetBlockPtr<unsigned>(
|
||||
shared_memory, storage::SharedDataLayout::NAME_OFFSETS);
|
||||
auto blocks_ptr = data_layout->GetBlockPtr<NameIndexBlock>(
|
||||
auto blocks_ptr = data_layout->GetBlockPtr<IndexBlock>(
|
||||
shared_memory, storage::SharedDataLayout::NAME_BLOCKS);
|
||||
typename util::ShM<unsigned, true>::vector name_offsets(
|
||||
util::ShM<unsigned, true>::vector name_offsets(
|
||||
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_OFFSETS]);
|
||||
typename util::ShM<NameIndexBlock, true>::vector name_blocks(
|
||||
util::ShM<IndexBlock, true>::vector name_blocks(
|
||||
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_BLOCKS]);
|
||||
|
||||
auto names_list_ptr = data_layout->GetBlockPtr<char>(
|
||||
shared_memory, storage::SharedDataLayout::NAME_CHAR_LIST);
|
||||
typename util::ShM<char, true>::vector names_char_list(
|
||||
util::ShM<char, true>::vector names_char_list(
|
||||
names_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_CHAR_LIST]);
|
||||
m_name_table = util::make_unique<util::RangeTable<16, true>>(
|
||||
name_offsets, name_blocks, static_cast<unsigned>(names_char_list.size()));
|
||||
@@ -216,7 +234,7 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
auto core_marker_ptr = data_layout->GetBlockPtr<unsigned>(
|
||||
shared_memory, storage::SharedDataLayout::CORE_MARKER);
|
||||
typename util::ShM<bool, true>::vector is_core_node(
|
||||
util::ShM<bool, true>::vector is_core_node(
|
||||
core_marker_ptr, data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER]);
|
||||
m_is_core_node = std::move(is_core_node);
|
||||
}
|
||||
@@ -225,7 +243,7 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
{
|
||||
auto geometries_index_ptr = data_layout->GetBlockPtr<unsigned>(
|
||||
shared_memory, storage::SharedDataLayout::GEOMETRIES_INDEX);
|
||||
typename util::ShM<unsigned, true>::vector geometry_begin_indices(
|
||||
util::ShM<unsigned, true>::vector geometry_begin_indices(
|
||||
geometries_index_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_INDEX]);
|
||||
m_geometry_indices = std::move(geometry_begin_indices);
|
||||
@@ -233,40 +251,74 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
auto geometries_list_ptr =
|
||||
data_layout->GetBlockPtr<extractor::CompressedEdgeContainer::CompressedEdge>(
|
||||
shared_memory, storage::SharedDataLayout::GEOMETRIES_LIST);
|
||||
typename util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector
|
||||
geometry_list(geometries_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]);
|
||||
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector geometry_list(
|
||||
geometries_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]);
|
||||
m_geometry_list = std::move(geometry_list);
|
||||
|
||||
auto datasources_list_ptr = data_layout->GetBlockPtr<uint8_t>(
|
||||
shared_memory, storage::SharedDataLayout::DATASOURCES_LIST);
|
||||
typename util::ShM<uint8_t, true>::vector datasources_list(
|
||||
util::ShM<uint8_t, true>::vector datasources_list(
|
||||
datasources_list_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::DATASOURCES_LIST]);
|
||||
m_datasource_list = std::move(datasources_list);
|
||||
|
||||
auto datasource_name_data_ptr = data_layout->GetBlockPtr<char>(
|
||||
shared_memory, storage::SharedDataLayout::DATASOURCE_NAME_DATA);
|
||||
typename util::ShM<char, true>::vector datasource_name_data(
|
||||
util::ShM<char, true>::vector datasource_name_data(
|
||||
datasource_name_data_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_DATA]);
|
||||
m_datasource_name_data = std::move(datasource_name_data);
|
||||
|
||||
auto datasource_name_offsets_ptr = data_layout->GetBlockPtr<std::size_t>(
|
||||
shared_memory, storage::SharedDataLayout::DATASOURCE_NAME_OFFSETS);
|
||||
typename util::ShM<std::size_t, true>::vector datasource_name_offsets(
|
||||
util::ShM<std::size_t, true>::vector datasource_name_offsets(
|
||||
datasource_name_offsets_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_OFFSETS]);
|
||||
m_datasource_name_offsets = std::move(datasource_name_offsets);
|
||||
|
||||
auto datasource_name_lengths_ptr = data_layout->GetBlockPtr<std::size_t>(
|
||||
shared_memory, storage::SharedDataLayout::DATASOURCE_NAME_LENGTHS);
|
||||
typename util::ShM<std::size_t, true>::vector datasource_name_lengths(
|
||||
util::ShM<std::size_t, true>::vector datasource_name_lengths(
|
||||
datasource_name_lengths_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_LENGTHS]);
|
||||
m_datasource_name_lengths = std::move(datasource_name_lengths);
|
||||
}
|
||||
|
||||
void LoadIntersectionClasses()
|
||||
{
|
||||
auto bearing_class_id_ptr = data_layout->GetBlockPtr<BearingClassID>(
|
||||
shared_memory, storage::SharedDataLayout::BEARING_CLASSID);
|
||||
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
|
||||
bearing_class_id_ptr,
|
||||
data_layout->num_entries[storage::SharedDataLayout::BEARING_CLASSID]);
|
||||
m_bearing_class_id_table = std::move(bearing_class_id_table);
|
||||
|
||||
auto bearing_class_ptr = data_layout->GetBlockPtr<DiscreteBearing>(
|
||||
shared_memory, storage::SharedDataLayout::BEARING_VALUES);
|
||||
typename util::ShM<DiscreteBearing, true>::vector bearing_class_table(
|
||||
bearing_class_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_VALUES]);
|
||||
m_bearing_values_table = std::move(bearing_class_table);
|
||||
|
||||
auto offsets_ptr = data_layout->GetBlockPtr<unsigned>(
|
||||
shared_memory, storage::SharedDataLayout::BEARING_OFFSETS);
|
||||
auto blocks_ptr = data_layout->GetBlockPtr<IndexBlock>(
|
||||
shared_memory, storage::SharedDataLayout::BEARING_BLOCKS);
|
||||
util::ShM<unsigned, true>::vector bearing_offsets(
|
||||
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_OFFSETS]);
|
||||
util::ShM<IndexBlock, true>::vector bearing_blocks(
|
||||
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_BLOCKS]);
|
||||
|
||||
m_bearing_ranges_table = util::make_unique<util::RangeTable<16, true>>(
|
||||
bearing_offsets, bearing_blocks, static_cast<unsigned>(m_bearing_values_table.size()));
|
||||
|
||||
auto entry_class_ptr = data_layout->GetBlockPtr<util::guidance::EntryClass>(
|
||||
shared_memory, storage::SharedDataLayout::ENTRY_CLASS);
|
||||
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
|
||||
entry_class_ptr, data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASS]);
|
||||
m_entry_class_table = std::move(entry_class_table);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~SharedDataFacade() {}
|
||||
|
||||
@@ -353,15 +405,14 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
LoadNames();
|
||||
LoadCoreInformation();
|
||||
LoadProfileProperties();
|
||||
LoadRTree();
|
||||
LoadIntersectionClasses();
|
||||
|
||||
util::SimpleLogger().Write() << "number of geometries: "
|
||||
<< m_coordinate_list->size();
|
||||
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
|
||||
<< m_coordinate_list.size();
|
||||
for (unsigned i = 0; i < m_coordinate_list.size(); ++i)
|
||||
{
|
||||
if (!GetCoordinateOfNode(i).IsValid())
|
||||
{
|
||||
util::SimpleLogger().Write() << "coordinate " << i << " not valid";
|
||||
}
|
||||
BOOST_ASSERT(GetCoordinateOfNode(i).IsValid());
|
||||
}
|
||||
}
|
||||
util::SimpleLogger().Write(logDEBUG) << "Releasing exclusive lock";
|
||||
@@ -414,7 +465,7 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
// node and edge information access
|
||||
util::Coordinate GetCoordinateOfNode(const NodeID id) const override final
|
||||
{
|
||||
return m_coordinate_list->at(id);
|
||||
return m_coordinate_list[id];
|
||||
}
|
||||
|
||||
virtual void GetUncompressedGeometry(const EdgeID id,
|
||||
@@ -426,8 +477,7 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
result_nodes.clear();
|
||||
result_nodes.reserve(end - begin);
|
||||
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
|
||||
{
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
|
||||
result_nodes.emplace_back(edge.node_id);
|
||||
});
|
||||
}
|
||||
@@ -442,8 +492,7 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
result_weights.clear();
|
||||
result_weights.reserve(end - begin);
|
||||
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
|
||||
{
|
||||
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
|
||||
result_weights.emplace_back(edge.weight);
|
||||
});
|
||||
}
|
||||
@@ -465,13 +514,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
}
|
||||
|
||||
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
const util::Coordinate north_east) override final
|
||||
const util::Coordinate north_east) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
const util::RectangleInt2D bbox{south_west.lon, north_east.lon, south_west.lat,
|
||||
north_east.lat};
|
||||
return m_geospatial_query->Search(bbox);
|
||||
@@ -479,13 +524,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance) override final
|
||||
const float max_distance) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
|
||||
}
|
||||
@@ -494,13 +535,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance,
|
||||
bearing, bearing_range);
|
||||
@@ -508,13 +545,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results) override final
|
||||
const unsigned max_results) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
|
||||
}
|
||||
@@ -522,13 +555,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance) override final
|
||||
const double max_distance) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
|
||||
}
|
||||
@@ -537,13 +566,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, bearing,
|
||||
bearing_range);
|
||||
@@ -554,26 +579,18 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance,
|
||||
bearing, bearing_range);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate) override final
|
||||
const util::Coordinate input_coordinate) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate);
|
||||
@@ -581,13 +598,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance) override final
|
||||
const double max_distance) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance);
|
||||
@@ -597,13 +610,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, bearing, bearing_range);
|
||||
@@ -612,13 +621,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range) override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
|
||||
{
|
||||
LoadRTree();
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
}
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, bearing, bearing_range);
|
||||
@@ -684,11 +689,9 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
}
|
||||
else
|
||||
{
|
||||
std::for_each(m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
|
||||
[&](const uint8_t &datasource_id)
|
||||
{
|
||||
result_datasources.push_back(datasource_id);
|
||||
});
|
||||
std::for_each(
|
||||
m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
|
||||
[&](const uint8_t &datasource_id) { result_datasources.push_back(datasource_id); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,7 +712,37 @@ class SharedDataFacade final : public BaseDataFacade
|
||||
|
||||
std::string GetTimestamp() const override final { return m_timestamp; }
|
||||
|
||||
bool GetContinueStraightDefault() const override final { return m_profile_properties->continue_straight_at_waypoint; }
|
||||
bool GetContinueStraightDefault() const override final
|
||||
{
|
||||
return m_profile_properties->continue_straight_at_waypoint;
|
||||
}
|
||||
|
||||
BearingClassID GetBearingClassID(const NodeID id) const override final
|
||||
{
|
||||
return m_bearing_class_id_table.at(id);
|
||||
}
|
||||
|
||||
util::guidance::BearingClass
|
||||
GetBearingClass(const BearingClassID bearing_class_id) const override final
|
||||
{
|
||||
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
|
||||
auto range = m_bearing_ranges_table->GetRange(bearing_class_id);
|
||||
util::guidance::BearingClass result;
|
||||
for (auto itr = m_bearing_values_table.begin() + range.front();
|
||||
itr != m_bearing_values_table.begin() + range.back() + 1; ++itr)
|
||||
result.add(*itr);
|
||||
return result;
|
||||
}
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID eid) const override final
|
||||
{
|
||||
return m_entry_class_id_list.at(eid);
|
||||
}
|
||||
|
||||
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
|
||||
{
|
||||
return m_entry_class_table.at(entry_class_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace engine
|
||||
|
||||
// Implements complex queries on top of an RTree and builds PhantomNodes from it.
|
||||
//
|
||||
// Only holds a weak reference on the RTree!
|
||||
// Only holds a weak reference on the RTree and coordinates!
|
||||
template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
{
|
||||
using EdgeData = typename RTreeT::EdgeData;
|
||||
@@ -31,9 +31,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
|
||||
public:
|
||||
GeospatialQuery(RTreeT &rtree_,
|
||||
std::shared_ptr<CoordinateList> coordinates_,
|
||||
const CoordinateList &coordinates_,
|
||||
DataFacadeT &datafacade_)
|
||||
: rtree(rtree_), coordinates(std::move(coordinates_)), datafacade(datafacade_)
|
||||
: rtree(rtree_), coordinates(coordinates_), datafacade(datafacade_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Returns nearest PhantomNodes in the given bearing range within max_distance.
|
||||
// Does not filter by small/big component!
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance)
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance) const
|
||||
{
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
@@ -56,7 +56,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
[this, max_distance, input_coordinate](const std::size_t,
|
||||
const CandidateSegment &segment)
|
||||
{
|
||||
return checkSegmentDistance(input_coordinate, segment, max_distance);
|
||||
return CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
@@ -68,18 +68,18 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range)
|
||||
const int bearing_range) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, bearing, bearing_range, max_distance](const CandidateSegment &segment)
|
||||
{
|
||||
return checkSegmentBearing(segment, bearing, bearing_range);
|
||||
return CheckSegmentBearing(segment, bearing, bearing_range);
|
||||
},
|
||||
[this, max_distance, input_coordinate](const std::size_t,
|
||||
const CandidateSegment &segment)
|
||||
{
|
||||
return checkSegmentDistance(input_coordinate, segment, max_distance);
|
||||
return CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
@@ -91,13 +91,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range)
|
||||
const int bearing_range) const
|
||||
{
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
[this, bearing, bearing_range](const CandidateSegment &segment)
|
||||
{
|
||||
return checkSegmentBearing(segment, bearing, bearing_range);
|
||||
return CheckSegmentBearing(segment, bearing, bearing_range);
|
||||
},
|
||||
[max_results](const std::size_t num_results, const CandidateSegment &)
|
||||
{
|
||||
@@ -115,19 +115,19 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range)
|
||||
const int bearing_range) const
|
||||
{
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
[this, bearing, bearing_range](const CandidateSegment &segment)
|
||||
{
|
||||
return checkSegmentBearing(segment, bearing, bearing_range);
|
||||
return CheckSegmentBearing(segment, bearing, bearing_range);
|
||||
},
|
||||
[this, max_distance, max_results, input_coordinate](
|
||||
const std::size_t num_results, const CandidateSegment &segment)
|
||||
{
|
||||
return num_results >= max_results ||
|
||||
checkSegmentDistance(input_coordinate, segment, max_distance);
|
||||
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
@@ -136,7 +136,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Returns max_results nearest PhantomNodes.
|
||||
// Does not filter by small/big component!
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results)
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const
|
||||
{
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
@@ -157,7 +157,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance)
|
||||
const double max_distance) const
|
||||
{
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
@@ -169,7 +169,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
const std::size_t num_results, const CandidateSegment &segment)
|
||||
{
|
||||
return num_results >= max_results ||
|
||||
checkSegmentDistance(input_coordinate, segment, max_distance);
|
||||
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
@@ -179,7 +179,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance)
|
||||
const double max_distance) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -200,7 +200,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
input_coordinate](const std::size_t num_results, const CandidateSegment &segment)
|
||||
{
|
||||
return (num_results > 0 && has_big_component) ||
|
||||
checkSegmentDistance(input_coordinate, segment, max_distance);
|
||||
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
if (results.size() == 0)
|
||||
@@ -216,7 +216,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate)
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -251,7 +251,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate, const int bearing, const int bearing_range)
|
||||
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -266,7 +266,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
|
||||
if (use_segment)
|
||||
{
|
||||
use_directions = checkSegmentBearing(segment, bearing, bearing_range);
|
||||
use_directions = CheckSegmentBearing(segment, bearing, bearing_range);
|
||||
if (use_directions.first || use_directions.second)
|
||||
{
|
||||
has_big_component = has_big_component || !segment.data.component.is_tiny;
|
||||
@@ -297,7 +297,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range)
|
||||
const int bearing_range) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -312,7 +312,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
|
||||
if (use_segment)
|
||||
{
|
||||
use_directions = checkSegmentBearing(segment, bearing, bearing_range);
|
||||
use_directions = CheckSegmentBearing(segment, bearing, bearing_range);
|
||||
if (use_directions.first || use_directions.second)
|
||||
{
|
||||
has_big_component = has_big_component || !segment.data.component.is_tiny;
|
||||
@@ -326,7 +326,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
input_coordinate](const std::size_t num_results, const CandidateSegment &segment)
|
||||
{
|
||||
return (num_results > 0 && has_big_component) ||
|
||||
checkSegmentDistance(input_coordinate, segment, max_distance);
|
||||
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
if (results.size() == 0)
|
||||
@@ -360,7 +360,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
double ratio;
|
||||
const auto current_perpendicular_distance =
|
||||
util::coordinate_calculation::perpendicularDistance(
|
||||
coordinates->at(data.u), coordinates->at(data.v), input_coordinate,
|
||||
coordinates[data.u], coordinates[data.v], input_coordinate,
|
||||
point_on_segment, ratio);
|
||||
|
||||
// Find the node-based-edge that this belongs to, and directly
|
||||
@@ -416,9 +416,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
return transformed;
|
||||
}
|
||||
|
||||
bool checkSegmentDistance(const Coordinate input_coordinate,
|
||||
bool CheckSegmentDistance(const Coordinate input_coordinate,
|
||||
const CandidateSegment &segment,
|
||||
const double max_distance)
|
||||
const double max_distance) const
|
||||
{
|
||||
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
|
||||
!segment.data.forward_segment_id.enabled);
|
||||
@@ -432,9 +432,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
max_distance;
|
||||
}
|
||||
|
||||
std::pair<bool, bool> checkSegmentBearing(const CandidateSegment &segment,
|
||||
std::pair<bool, bool> CheckSegmentBearing(const CandidateSegment &segment,
|
||||
const int filter_bearing,
|
||||
const int filter_bearing_range)
|
||||
const int filter_bearing_range) const
|
||||
{
|
||||
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
|
||||
!segment.data.forward_segment_id.enabled);
|
||||
@@ -442,7 +442,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
!segment.data.reverse_segment_id.enabled);
|
||||
|
||||
const double forward_edge_bearing = util::coordinate_calculation::bearing(
|
||||
coordinates->at(segment.data.u), coordinates->at(segment.data.v));
|
||||
coordinates[segment.data.u], coordinates[segment.data.v]);
|
||||
|
||||
const double backward_edge_bearing = (forward_edge_bearing + 180) > 360
|
||||
? (forward_edge_bearing - 180)
|
||||
@@ -459,8 +459,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
return std::make_pair(forward_bearing_valid, backward_bearing_valid);
|
||||
}
|
||||
|
||||
RTreeT &rtree;
|
||||
const std::shared_ptr<CoordinateList> coordinates;
|
||||
const RTreeT &rtree;
|
||||
const CoordinateList &coordinates;
|
||||
DataFacadeT &datafacade;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,34 +43,40 @@ LegGeometry assembleGeometry(const DataFacadeT &facade,
|
||||
geometry.segment_offsets.push_back(0);
|
||||
geometry.locations.push_back(source_node.location);
|
||||
|
||||
auto cumulative_distance = 0.;
|
||||
auto current_distance = 0.;
|
||||
auto prev_coordinate = geometry.locations.front();
|
||||
for (const auto &path_point : leg_data)
|
||||
{
|
||||
auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
||||
current_distance +=
|
||||
current_distance =
|
||||
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
|
||||
cumulative_distance += current_distance;
|
||||
|
||||
// all changes to this check have to be matched with assemble_steps
|
||||
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
||||
{
|
||||
geometry.segment_distances.push_back(current_distance);
|
||||
geometry.segment_distances.push_back(cumulative_distance);
|
||||
geometry.segment_offsets.push_back(geometry.locations.size());
|
||||
current_distance = 0.;
|
||||
cumulative_distance = 0.;
|
||||
}
|
||||
|
||||
prev_coordinate = coordinate;
|
||||
geometry.annotations.emplace_back(LegGeometry::Annotation{current_distance, path_point.duration_until_turn / 10.});
|
||||
geometry.locations.push_back(std::move(coordinate));
|
||||
}
|
||||
current_distance +=
|
||||
current_distance =
|
||||
util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location);
|
||||
cumulative_distance += current_distance;
|
||||
// segment leading to the target node
|
||||
geometry.segment_distances.push_back(current_distance);
|
||||
geometry.segment_distances.push_back(cumulative_distance);
|
||||
geometry.annotations.emplace_back(LegGeometry::Annotation{current_distance, target_node.forward_weight / 10.});
|
||||
geometry.segment_offsets.push_back(geometry.locations.size());
|
||||
geometry.locations.push_back(target_node.location);
|
||||
|
||||
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
||||
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
||||
BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ENGINE_GUIDANCE_ASSEMBLE_LEG_HPP_
|
||||
#define ENGINE_GUIDANCE_ASSEMBLE_LEG_HPP_
|
||||
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
#include "engine/guidance/leg_geometry.hpp"
|
||||
#include "engine/guidance/route_leg.hpp"
|
||||
#include "engine/guidance/route_step.hpp"
|
||||
@@ -22,12 +23,104 @@ namespace engine
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
const constexpr std::size_t MAX_USED_SEGMENTS = 2;
|
||||
struct NamedSegment
|
||||
{
|
||||
EdgeWeight duration;
|
||||
std::uint32_t position;
|
||||
std::uint32_t name_id;
|
||||
};
|
||||
|
||||
inline RouteLeg assembleLeg(const std::vector<PathData> &route_data,
|
||||
template <std::size_t SegmentNumber>
|
||||
|
||||
std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathData> &route_data)
|
||||
{
|
||||
// merges segments with same name id
|
||||
const auto collapse_segments = [](std::vector<NamedSegment> &segments)
|
||||
{
|
||||
auto out = segments.begin();
|
||||
auto end = segments.end();
|
||||
|
||||
// Do nothing if we were given an empty array
|
||||
if (out == end)
|
||||
{
|
||||
return end;
|
||||
}
|
||||
|
||||
for (auto in = std::next(out); in != end; ++in)
|
||||
{
|
||||
if (in->name_id == out->name_id)
|
||||
{
|
||||
out->duration += in->duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
++out;
|
||||
BOOST_ASSERT(out != end);
|
||||
*out = *in;
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(out != end);
|
||||
return ++out;
|
||||
};
|
||||
|
||||
std::vector<NamedSegment> segments(route_data.size());
|
||||
std::uint32_t index = 0;
|
||||
std::transform(
|
||||
route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point)
|
||||
{
|
||||
return NamedSegment{point.duration_until_turn, index++, point.name_id};
|
||||
});
|
||||
// this makes sure that the segment with the lowest position comes first
|
||||
std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
|
||||
{
|
||||
return lhs.name_id < rhs.name_id ||
|
||||
(lhs.name_id == rhs.name_id && lhs.position < rhs.position);
|
||||
});
|
||||
auto new_end = collapse_segments(segments);
|
||||
segments.resize(new_end - segments.begin());
|
||||
|
||||
// Filter out segments with an empty name (name_id == 0)
|
||||
new_end = std::remove_if(segments.begin(), segments.end(), [](const NamedSegment &segment)
|
||||
{
|
||||
return segment.name_id == 0;
|
||||
});
|
||||
segments.resize(new_end - segments.begin());
|
||||
|
||||
// sort descending
|
||||
std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
|
||||
{
|
||||
return lhs.duration > rhs.duration ||
|
||||
(lhs.duration == rhs.duration && lhs.position < rhs.position);
|
||||
});
|
||||
|
||||
// make sure the segments are sorted by position
|
||||
segments.resize(std::min(segments.size(), SegmentNumber));
|
||||
std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
|
||||
{
|
||||
return lhs.position < rhs.position;
|
||||
});
|
||||
|
||||
std::array<std::uint32_t, SegmentNumber> summary;
|
||||
std::fill(summary.begin(), summary.end(), 0);
|
||||
std::transform(segments.begin(), segments.end(), summary.begin(),
|
||||
[](const NamedSegment &segment)
|
||||
{
|
||||
return segment.name_id;
|
||||
});
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
|
||||
inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
||||
const std::vector<PathData> &route_data,
|
||||
const LegGeometry &leg_geometry,
|
||||
const PhantomNode &source_node,
|
||||
const PhantomNode &target_node,
|
||||
const bool target_traversed_in_reverse)
|
||||
const bool target_traversed_in_reverse,
|
||||
const bool needs_summary)
|
||||
{
|
||||
const auto target_duration =
|
||||
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight) /
|
||||
@@ -70,7 +163,26 @@ inline RouteLeg assembleLeg(const std::vector<PathData> &route_data,
|
||||
10.0;
|
||||
}
|
||||
|
||||
return RouteLeg{duration, distance, {}};
|
||||
std::string summary;
|
||||
if (needs_summary)
|
||||
{
|
||||
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(route_data);
|
||||
|
||||
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
|
||||
BOOST_ASSERT(summary_array.begin() != summary_array.end());
|
||||
summary = std::accumulate(std::next(summary_array.begin()), summary_array.end(),
|
||||
facade.GetNameForID(summary_array.front()),
|
||||
[&facade](std::string previous, const std::uint32_t name_id)
|
||||
{
|
||||
if (name_id != 0)
|
||||
{
|
||||
previous += ", " + facade.GetNameForID(name_id);
|
||||
}
|
||||
return previous;
|
||||
});
|
||||
}
|
||||
|
||||
return RouteLeg{duration, distance, summary, {}};
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
|
||||
@@ -12,8 +12,12 @@
|
||||
#include "util/bearing.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
@@ -24,14 +28,10 @@ namespace guidance
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
||||
const LegGeometry &leg_geometry,
|
||||
const std::size_t segment_index);
|
||||
|
||||
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
|
||||
const WaypointType waypoint_type,
|
||||
const LegGeometry &leg_geometry);
|
||||
|
||||
std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry);
|
||||
std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry);
|
||||
std::pair<short, short> getIntermediateBearings(const LegGeometry &leg_geometry,
|
||||
const std::size_t segment_index);
|
||||
} // ns detail
|
||||
|
||||
template <typename DataFacadeT>
|
||||
@@ -63,34 +63,67 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
||||
std::size_t segment_index = 0;
|
||||
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
||||
|
||||
auto bearings = detail::getDepartBearings(leg_geometry);
|
||||
|
||||
StepManeuver maneuver{source_node.location, bearings.first,
|
||||
bearings.second, extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
WaypointType::Depart, 0};
|
||||
Intersection intersection{
|
||||
source_node.location,
|
||||
std::vector<short>({bearings.second}),
|
||||
std::vector<bool>({true}), Intersection::NO_INDEX, 0};
|
||||
|
||||
if (leg_data.size() > 0)
|
||||
{
|
||||
|
||||
StepManeuver maneuver = detail::stepManeuverFromGeometry(
|
||||
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
|
||||
maneuver.location = source_node.location;
|
||||
|
||||
// PathData saves the information we need of the segment _before_ the turn,
|
||||
// but a RouteStep is with regard to the segment after the turn.
|
||||
// We need to skip the first segment because it is already covered by the
|
||||
// initial start of a route
|
||||
int segment_duration = 0;
|
||||
for (const auto &path_point : leg_data)
|
||||
|
||||
// some name changes are not announced in our processing. For these, we have to keep the
|
||||
// first name on the segment
|
||||
auto step_name_id = source_node.name_id;
|
||||
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
|
||||
{
|
||||
const auto &path_point = leg_data[leg_data_index];
|
||||
segment_duration += path_point.duration_until_turn;
|
||||
|
||||
// all changes to this check have to be matched with assemble_geometry
|
||||
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
||||
{
|
||||
BOOST_ASSERT(segment_duration >= 0);
|
||||
const auto name = facade.GetNameForID(path_point.name_id);
|
||||
const auto name = facade.GetNameForID(step_name_id);
|
||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||
steps.push_back(RouteStep{path_point.name_id, name, NO_ROTARY_NAME,
|
||||
segment_duration / 10.0, distance, path_point.travel_mode,
|
||||
maneuver, leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1});
|
||||
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
|
||||
leg_geometry, segment_index);
|
||||
|
||||
if (leg_data_index + 1 < leg_data.size())
|
||||
{
|
||||
step_name_id = leg_data[leg_data_index + 1].name_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
step_name_id = target_node.name_id;
|
||||
}
|
||||
steps.push_back(RouteStep{
|
||||
step_name_id, name, NO_ROTARY_NAME, segment_duration / 10.0, distance,
|
||||
path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
|
||||
|
||||
bearings = detail::getIntermediateBearings(leg_geometry, segment_index);
|
||||
const auto entry_class = facade.GetEntryClass(path_point.entry_classid);
|
||||
const auto bearing_class = facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node));
|
||||
intersection.in = bearing_class.findMatchingBearing(util::bearing::reverseBearing(bearings.first));
|
||||
intersection.out = bearing_class.findMatchingBearing(bearings.second);
|
||||
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
||||
intersection.bearings.clear();
|
||||
std::copy(bearing_class.getAvailableBearings().begin(), bearing_class.getAvailableBearings().end(),
|
||||
std::back_inserter(intersection.bearings));
|
||||
intersection.entry.clear();
|
||||
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
|
||||
{
|
||||
intersection.entry.push_back(entry_class.allowsEntry(idx));
|
||||
}
|
||||
maneuver = {intersection.location, bearings.first, bearings.second, path_point.turn_instruction, WaypointType::None, 0};
|
||||
segment_index++;
|
||||
segment_duration = 0;
|
||||
}
|
||||
@@ -98,10 +131,10 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||
const int duration = segment_duration + target_duration;
|
||||
BOOST_ASSERT(duration >= 0);
|
||||
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
|
||||
NO_ROTARY_NAME, duration / 10., distance, target_mode, maneuver,
|
||||
leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1});
|
||||
steps.push_back(RouteStep{
|
||||
step_name_id, facade.GetNameForID(step_name_id), NO_ROTARY_NAME, duration / 10.,
|
||||
distance, target_mode, maneuver, leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
|
||||
}
|
||||
// In this case the source + target are on the same edge segment
|
||||
else
|
||||
@@ -112,29 +145,42 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
||||
// |---| source_duration
|
||||
// |---------| target_duration
|
||||
|
||||
StepManeuver maneuver = detail::stepManeuverFromGeometry(
|
||||
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
|
||||
int duration = target_duration - source_duration;
|
||||
BOOST_ASSERT(duration >= 0);
|
||||
|
||||
steps.push_back(RouteStep{source_node.name_id, facade.GetNameForID(source_node.name_id),
|
||||
NO_ROTARY_NAME, duration / 10.,
|
||||
leg_geometry.segment_distances[segment_index], source_mode,
|
||||
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1});
|
||||
steps.push_back(RouteStep{
|
||||
source_node.name_id, facade.GetNameForID(source_node.name_id), NO_ROTARY_NAME,
|
||||
duration / 10., leg_geometry.segment_distances[segment_index], source_mode,
|
||||
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
|
||||
}
|
||||
|
||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||
bearings = detail::getArriveBearings(leg_geometry);
|
||||
// This step has length zero, the only reason we need it is the target location
|
||||
auto final_maneuver = detail::stepManeuverFromGeometry(
|
||||
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, leg_geometry);
|
||||
maneuver = {intersection.location, bearings.first, bearings.second, extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, 0};
|
||||
intersection = {
|
||||
target_node.location,
|
||||
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
|
||||
std::vector<bool>({true}), 0, Intersection::NO_INDEX};
|
||||
|
||||
BOOST_ASSERT(!leg_geometry.locations.empty());
|
||||
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
|
||||
NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode,
|
||||
final_maneuver, leg_geometry.locations.size()-1,
|
||||
leg_geometry.locations.size()});
|
||||
std::move(maneuver), leg_geometry.locations.size() - 1,
|
||||
leg_geometry.locations.size(),
|
||||
{intersection}});
|
||||
|
||||
|
||||
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
||||
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
||||
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
||||
BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart);
|
||||
|
||||
BOOST_ASSERT(steps.back().intersections.size() == 1);
|
||||
BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1);
|
||||
BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1);
|
||||
BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive);
|
||||
return steps;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,13 @@ struct LegGeometry
|
||||
// length of the segment in meters
|
||||
std::vector<double> segment_distances;
|
||||
|
||||
// Per-coordinate metadata
|
||||
struct Annotation {
|
||||
double distance;
|
||||
double duration;
|
||||
};
|
||||
std::vector<Annotation> annotations;
|
||||
|
||||
std::size_t FrontIndex(std::size_t segment_index) const
|
||||
{
|
||||
return segment_offsets[segment_index];
|
||||
|
||||
@@ -17,6 +17,13 @@ namespace guidance
|
||||
// passed as none-reference to modify in-place and move out again
|
||||
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps);
|
||||
|
||||
// Multiple possible reasons can result in unnecessary/confusing instructions
|
||||
// A prime example would be a segregated intersection. Turning around at this
|
||||
// intersection would result in two instructions to turn left.
|
||||
// Collapsing such turns into a single turn instruction, we give a clearer
|
||||
// set of instructionst that is not cluttered by unnecessary turns/name changes.
|
||||
std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps);
|
||||
|
||||
// trim initial/final segment of very short length.
|
||||
// This function uses in/out parameter passing to modify both steps and geometry in place.
|
||||
// We use this method since both steps and geometry are closely coupled logically but
|
||||
@@ -30,6 +37,9 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
|
||||
const PhantomNode &source_node,
|
||||
const PhantomNode &target_node);
|
||||
|
||||
//remove steps invalidated by post-processing
|
||||
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
|
||||
|
||||
// postProcess will break the connection between the leg geometry
|
||||
// for which a segment is supposed to represent exactly the coordinates
|
||||
// between routing maneuvers and the route steps itself.
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include "engine/guidance/route_step.hpp"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
@@ -16,6 +19,7 @@ struct RouteLeg
|
||||
{
|
||||
double duration;
|
||||
double distance;
|
||||
std::string summary;
|
||||
std::vector<RouteStep> steps;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include "engine/guidance/step_maneuver.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@@ -21,6 +24,27 @@ namespace guidance
|
||||
// Notable exceptions are Departure and Arrival steps.
|
||||
// Departue: s --> a --> b. Represents the segment s,a with location being s.
|
||||
// Arrive: a --> b --> t. The segment (b,t) is already covered by the previous segment.
|
||||
|
||||
// A represenetation of intermediate intersections
|
||||
struct Intersection
|
||||
{
|
||||
static const constexpr std::size_t NO_INDEX = std::numeric_limits<std::size_t>::max();
|
||||
util::Coordinate location;
|
||||
std::vector<short> bearings;
|
||||
std::vector<bool> entry;
|
||||
std::size_t in;
|
||||
std::size_t out;
|
||||
};
|
||||
|
||||
inline Intersection getInvalidIntersection()
|
||||
{
|
||||
return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}},
|
||||
{},
|
||||
{},
|
||||
Intersection::NO_INDEX,
|
||||
Intersection::NO_INDEX};
|
||||
}
|
||||
|
||||
struct RouteStep
|
||||
{
|
||||
unsigned name_id;
|
||||
@@ -33,7 +57,22 @@ struct RouteStep
|
||||
// indices into the locations array stored the LegGeometry
|
||||
std::size_t geometry_begin;
|
||||
std::size_t geometry_end;
|
||||
std::vector<Intersection> intersections;
|
||||
};
|
||||
|
||||
inline RouteStep getInvalidRouteStep()
|
||||
{
|
||||
return {0,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
getInvalidStepManeuver(),
|
||||
0,
|
||||
0,
|
||||
{getInvalidIntersection()}};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef ENGINE_GUIDANCE_STEP_MANEUVER_HPP
|
||||
#define ENGINE_GUIDANCE_STEP_MANEUVER_HPP
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
@@ -21,24 +21,26 @@ enum class WaypointType : std::uint8_t
|
||||
Depart,
|
||||
};
|
||||
|
||||
//A represenetation of intermediate intersections
|
||||
struct IntermediateIntersection
|
||||
{
|
||||
double duration;
|
||||
double distance;
|
||||
util::Coordinate location;
|
||||
};
|
||||
|
||||
struct StepManeuver
|
||||
{
|
||||
util::Coordinate location;
|
||||
double bearing_before;
|
||||
double bearing_after;
|
||||
short bearing_before;
|
||||
short bearing_after;
|
||||
extractor::guidance::TurnInstruction instruction;
|
||||
WaypointType waypoint_type;
|
||||
unsigned exit;
|
||||
std::vector<IntermediateIntersection> intersections;
|
||||
};
|
||||
|
||||
inline StepManeuver getInvalidStepManeuver()
|
||||
{
|
||||
return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}},
|
||||
0,
|
||||
0,
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
WaypointType::None,
|
||||
0};
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace engine
|
||||
} // namespace osrmn
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#ifndef OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_
|
||||
#define OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_
|
||||
#ifndef OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
|
||||
#define OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
|
||||
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "util/bearing.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
@@ -23,9 +25,12 @@ inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruct
|
||||
{
|
||||
return (instruction.type == extractor::guidance::TurnType::EnterRoundabout ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterRotary ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersection ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary);
|
||||
}
|
||||
|
||||
@@ -33,8 +38,10 @@ inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruct
|
||||
{
|
||||
return (instruction.type == extractor::guidance::TurnType::ExitRoundabout ||
|
||||
instruction.type == extractor::guidance::TurnType::ExitRotary ||
|
||||
instruction.type == extractor::guidance::TurnType::ExitRoundaboutIntersection ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary);
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
|
||||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
|
||||
}
|
||||
|
||||
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
|
||||
@@ -42,7 +49,7 @@ inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruc
|
||||
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
|
||||
}
|
||||
|
||||
inline extractor::guidance::DirectionModifier angleToDirectionModifier(const double bearing)
|
||||
inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(const double bearing)
|
||||
{
|
||||
if (bearing < 135)
|
||||
{
|
||||
@@ -56,8 +63,14 @@ inline extractor::guidance::DirectionModifier angleToDirectionModifier(const dou
|
||||
return extractor::guidance::DirectionModifier::Left;
|
||||
}
|
||||
|
||||
inline double angularDeviation(const double angle, const double from)
|
||||
{
|
||||
const double deviation = std::abs(angle - from);
|
||||
return std::min(360 - deviation, deviation);
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_ */
|
||||
#endif /* OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_ */
|
||||
|
||||
+1
-10
@@ -63,18 +63,9 @@ struct Hint
|
||||
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
||||
};
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static_assert(sizeof(Hint) == 60 + 4, "Hint is bigger than expected");
|
||||
constexpr std::size_t ENCODED_HINT_SIZE = 88;
|
||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||
#else
|
||||
// PhantomNode is bigger under windows because MSVC does not support bit packing
|
||||
static_assert(sizeof(Hint) == 72 + 4, "Hint is bigger than expected");
|
||||
constexpr std::size_t ENCODED_HINT_SIZE = 104;
|
||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||
#endif
|
||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint), "ENCODED_HINT_SIZE does not match size of Hint");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define RAW_ROUTE_DATA_H
|
||||
|
||||
#include "engine/phantom_node.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
@@ -29,6 +29,8 @@ struct PathData
|
||||
extractor::guidance::TurnInstruction turn_instruction;
|
||||
// travel mode of the street that leads to the turn
|
||||
extractor::TravelMode travel_mode : 4;
|
||||
// entry class of the turn, indicating possibility of turns
|
||||
EntryClassID entry_classid;
|
||||
};
|
||||
|
||||
struct InternalRouteResult
|
||||
|
||||
@@ -23,7 +23,7 @@ struct NormalDistribution
|
||||
}
|
||||
|
||||
// FIXME implement log-probability version since it's faster
|
||||
double density_function(const double val) const
|
||||
double Density(const double val) const
|
||||
{
|
||||
using namespace boost::math::constants;
|
||||
|
||||
@@ -44,7 +44,7 @@ struct LaplaceDistribution
|
||||
}
|
||||
|
||||
// FIXME implement log-probability version since it's faster
|
||||
double density_function(const double val) const
|
||||
double Density(const double val) const
|
||||
{
|
||||
const double x = std::abs(val - location);
|
||||
return 1.0 / (2. * scale) * std::exp(-x / scale);
|
||||
@@ -79,9 +79,9 @@ class BayesClassifier
|
||||
ClassificationT classify(const ValueT &v) const
|
||||
{
|
||||
const double positive_postpriori =
|
||||
positive_apriori_probability * positive_distribution.density_function(v);
|
||||
positive_apriori_probability * positive_distribution.Density(v);
|
||||
const double negative_postpriori =
|
||||
negative_apriori_probability * negative_distribution.density_function(v);
|
||||
negative_apriori_probability * negative_distribution.Density(v);
|
||||
const double norm = positive_postpriori + negative_postpriori;
|
||||
|
||||
if (positive_postpriori > negative_postpriori)
|
||||
|
||||
@@ -82,10 +82,10 @@ template <class CandidateLists> struct HiddenMarkovModel
|
||||
}
|
||||
}
|
||||
|
||||
clear(0);
|
||||
Clear(0);
|
||||
}
|
||||
|
||||
void clear(std::size_t initial_timestamp)
|
||||
void Clear(std::size_t initial_timestamp)
|
||||
{
|
||||
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_distances.size() &&
|
||||
path_distances.size() == pruned.size() && pruned.size() == breakage.size());
|
||||
|
||||
@@ -149,13 +149,11 @@ struct PhantomNode
|
||||
unsigned reverse_packed_geometry_id;
|
||||
struct ComponentType
|
||||
{
|
||||
uint32_t id : 31;
|
||||
bool is_tiny : 1;
|
||||
std::uint32_t id : 31;
|
||||
std::uint32_t is_tiny : 1;
|
||||
} component;
|
||||
// bit-fields are broken on Windows
|
||||
#ifndef _MSC_VER
|
||||
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to be 4 bytes big");
|
||||
#endif
|
||||
|
||||
util::Coordinate location;
|
||||
util::Coordinate input_location;
|
||||
unsigned short fwd_segment_position;
|
||||
@@ -165,11 +163,7 @@ struct PhantomNode
|
||||
extractor::TravelMode backward_travel_mode;
|
||||
};
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static_assert(sizeof(PhantomNode) == 60, "PhantomNode has more padding then expected");
|
||||
#else
|
||||
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
|
||||
#endif
|
||||
|
||||
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ class TripPlugin final : public BasePlugin
|
||||
int max_locations_trip;
|
||||
|
||||
InternalRouteResult ComputeRoute(const std::vector<PhantomNode> &phantom_node_list,
|
||||
const api::TripParameters ¶meters,
|
||||
const std::vector<NodeID> &trip);
|
||||
|
||||
public:
|
||||
|
||||
@@ -162,8 +162,6 @@ class AlternativeRouting final
|
||||
if (path_is_a_loop)
|
||||
{
|
||||
// Self Loop
|
||||
BOOST_ASSERT(forward_heap1.GetData(middle_node).parent == middle_node &&
|
||||
reverse_heap1.GetData(middle_node).parent == middle_node);
|
||||
packed_forward_path.push_back(middle_node);
|
||||
packed_forward_path.push_back(middle_node);
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
|
||||
split_points.push_back(split_index);
|
||||
|
||||
// note: this preserves everything before split_index
|
||||
model.clear(split_index);
|
||||
model.Clear(split_index);
|
||||
std::size_t new_start = model.initialize(split_index);
|
||||
// no new start was found -> stop viterbi calculation
|
||||
if (new_start == map_matching::INVALID_STATE)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef ROUTING_BASE_HPP
|
||||
#define ROUTING_BASE_HPP
|
||||
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "engine/internal_route_result.hpp"
|
||||
#include "engine/search_engine_data.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <numeric>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -226,6 +226,11 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
recursion_stack.emplace(*std::prev(current), *current);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(*packed_path_begin == phantom_node_pair.source_phantom.forward_segment_id.id ||
|
||||
*packed_path_begin == phantom_node_pair.source_phantom.reverse_segment_id.id);
|
||||
BOOST_ASSERT(*std::prev(packed_path_end) == phantom_node_pair.target_phantom.forward_segment_id.id ||
|
||||
*std::prev(packed_path_end) == phantom_node_pair.target_phantom.reverse_segment_id.id);
|
||||
|
||||
std::pair<NodeID, NodeID> edge;
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
@@ -301,8 +306,6 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
|
||||
|
||||
BOOST_ASSERT(weight_vector.size() == id_vector.size());
|
||||
// ed.distance should be total_weight + penalties (turn, stop, etc)
|
||||
BOOST_ASSERT(ed.distance >= total_weight);
|
||||
const bool is_first_segment = unpacked_path.empty();
|
||||
|
||||
const std::size_t start_index =
|
||||
@@ -319,13 +322,12 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
for (std::size_t i = start_index; i < end_index; ++i)
|
||||
{
|
||||
unpacked_path.push_back(
|
||||
PathData{id_vector[i],
|
||||
name_index,
|
||||
weight_vector[i],
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
travel_mode});
|
||||
PathData{id_vector[i], name_index, weight_vector[i],
|
||||
extractor::guidance::TurnInstruction::NO_TURN(), travel_mode,
|
||||
INVALID_ENTRY_CLASSID});
|
||||
}
|
||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||
unpacked_path.back().entry_classid = facade->GetEntryClassID(ed.id);
|
||||
unpacked_path.back().turn_instruction = turn_instruction;
|
||||
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
|
||||
}
|
||||
@@ -350,7 +352,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
start_index =
|
||||
id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1;
|
||||
}
|
||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
|
||||
end_index =
|
||||
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -373,19 +376,16 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
// t: fwd_segment 3
|
||||
// -> (U, v), (v, w), (w, x)
|
||||
// note that (x, t) is _not_ included but needs to be added later.
|
||||
BOOST_ASSERT(start_index <= end_index);
|
||||
for (std::size_t i = start_index; i != end_index; ++i)
|
||||
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
|
||||
{
|
||||
BOOST_ASSERT(i < id_vector.size());
|
||||
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
|
||||
unpacked_path.push_back(
|
||||
PathData{id_vector[i],
|
||||
phantom_node_pair.target_phantom.name_id,
|
||||
weight_vector[i],
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
target_traversed_in_reverse
|
||||
? phantom_node_pair.target_phantom.backward_travel_mode
|
||||
: phantom_node_pair.target_phantom.forward_travel_mode});
|
||||
unpacked_path.push_back(PathData{
|
||||
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
||||
: phantom_node_pair.target_phantom.forward_travel_mode,
|
||||
INVALID_ENTRY_CLASSID});
|
||||
}
|
||||
|
||||
if (unpacked_path.size() > 0)
|
||||
@@ -397,8 +397,17 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
// However the first segment duration needs to be adjusted to the fact that the source
|
||||
// phantom is in the middle of the segment. We do this by subtracting v--s from the
|
||||
// duration.
|
||||
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
|
||||
unpacked_path.front().duration_until_turn -= source_weight;
|
||||
|
||||
// Since it's possible duration_until_turn can be less than source_weight here if
|
||||
// a negative enough turn penalty is used to modify this edge weight during
|
||||
// osrm-contract, we clamp to 0 here so as not to return a negative duration
|
||||
// for this segment.
|
||||
|
||||
// TODO this creates a scenario where it's possible the duration from a phantom
|
||||
// node to the first turn would be the same as from end to end of a segment,
|
||||
// which is obviously incorrect and not ideal...
|
||||
unpacked_path.front().duration_until_turn =
|
||||
std::max(unpacked_path.front().duration_until_turn - source_weight, 0);
|
||||
}
|
||||
|
||||
// there is no equivalent to a node-based node in an edge-expanded graph.
|
||||
@@ -559,9 +568,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
// make sure to correctly unpack loops
|
||||
if (distance != forward_heap.GetKey(middle) + reverse_heap.GetKey(middle))
|
||||
{
|
||||
// self loop
|
||||
BOOST_ASSERT(forward_heap.GetData(middle).parent == middle &&
|
||||
reverse_heap.GetData(middle).parent == middle);
|
||||
// self loop makes up the full path
|
||||
packed_leg.push_back(middle);
|
||||
packed_leg.push_back(middle);
|
||||
}
|
||||
@@ -636,9 +643,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
}
|
||||
// TODO check if unordered_set might be faster
|
||||
// sort by id and increasing by distance
|
||||
auto entry_point_comparator =
|
||||
[](const std::pair<NodeID, EdgeWeight> &lhs, const std::pair<NodeID, EdgeWeight> &rhs)
|
||||
{
|
||||
auto entry_point_comparator = [](const std::pair<NodeID, EdgeWeight> &lhs,
|
||||
const std::pair<NodeID, EdgeWeight> &rhs) {
|
||||
return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second);
|
||||
};
|
||||
std::sort(forward_entry_points.begin(), forward_entry_points.end(), entry_point_comparator);
|
||||
@@ -774,18 +780,50 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
|
||||
nodes.target_phantom = target_phantom;
|
||||
UnpackPath(packed_path.begin(), packed_path.end(), nodes, unpacked_path);
|
||||
|
||||
util::Coordinate previous_coordinate = source_phantom.location;
|
||||
util::Coordinate current_coordinate;
|
||||
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
|
||||
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
||||
|
||||
double distance = 0;
|
||||
double prev_lat =
|
||||
static_cast<double>(toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
double prev_lon =
|
||||
static_cast<double>(toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
double prev_cos = std::cos(prev_lat);
|
||||
for (const auto &p : unpacked_path)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(p.turn_via_node);
|
||||
distance += util::coordinate_calculation::haversineDistance(previous_coordinate,
|
||||
current_coordinate);
|
||||
previous_coordinate = current_coordinate;
|
||||
const auto current_coordinate = facade->GetCoordinateOfNode(p.turn_via_node);
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
||||
|
||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
distance += EARTH_RADIUS * charv;
|
||||
|
||||
prev_lat = current_lat;
|
||||
prev_lon = current_lon;
|
||||
prev_cos = current_cos;
|
||||
}
|
||||
distance += util::coordinate_calculation::haversineDistance(previous_coordinate,
|
||||
target_phantom.location);
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
||||
|
||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
distance += EARTH_RADIUS * charv;
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,15 +57,13 @@ class ShortestPathRouting final
|
||||
if (search_from_forward_node)
|
||||
{
|
||||
forward_heap.Insert(source_phantom.forward_segment_id.id,
|
||||
total_distance_to_forward -
|
||||
source_phantom.GetForwardWeightPlusOffset(),
|
||||
-source_phantom.GetForwardWeightPlusOffset(),
|
||||
source_phantom.forward_segment_id.id);
|
||||
}
|
||||
if (search_from_reverse_node)
|
||||
{
|
||||
forward_heap.Insert(source_phantom.reverse_segment_id.id,
|
||||
total_distance_to_reverse -
|
||||
source_phantom.GetReverseWeightPlusOffset(),
|
||||
-source_phantom.GetReverseWeightPlusOffset(),
|
||||
source_phantom.reverse_segment_id.id);
|
||||
}
|
||||
if (search_to_forward_node)
|
||||
@@ -107,6 +105,7 @@ class ShortestPathRouting final
|
||||
super::Search(forward_heap, reverse_heap, new_total_distance, leg_packed_path,
|
||||
needs_loop_forwad, needs_loop_backwards);
|
||||
}
|
||||
new_total_distance += std::min(total_distance_to_forward,total_distance_to_reverse);
|
||||
}
|
||||
|
||||
// searches shortest path between:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user