Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c7293f2024 | |||
| ddc8aed25d | |||
| 5f7410057c | |||
| d55d46e64e | |||
| a83150d311 | |||
| b073bf36f3 | |||
| aaea94f776 | |||
| 055079192c | |||
| c542fc2087 | |||
| 64b9b6e888 | |||
| c58052ca04 | |||
| df4d1cb9e6 | |||
| 3349964b96 | |||
| 443ebc2551 | |||
| e6b1e3564a | |||
| 3aeb39ba95 | |||
| 51fbb4fcbd | |||
| f618531cbb | |||
| 3f737fce46 | |||
| 11df411da7 | |||
| 5f208b913c | |||
| 3131bffe11 | |||
| 4f3a7c1ec3 | |||
| 321d1988a0 | |||
| b707fcdadc | |||
| 4285660c72 | |||
| 111e689b09 | |||
| ebbb497af2 | |||
| dd9ad9fa08 | |||
| dc55edbeb1 | |||
| 1c59563c9c | |||
| f4e1f6a752 | |||
| 8c1e014d42 | |||
| b27fa42b0a | |||
| 73e008e1b0 | |||
| 45fe4b80dd | |||
| 65732db266 | |||
| 55a7e1082f | |||
| 34d5ba8fdd | |||
| ec26756084 | |||
| 0f55f24bfe | |||
| 07f2c8fd4c | |||
| 3289d53617 | |||
| 1ea5e44094 | |||
| ee208cd450 | |||
| 4370fd126d | |||
| 15a2fdd1f8 | |||
| 0eedcf69bc | |||
| 62abea30f5 | |||
| 3364be1860 | |||
| a5eeca9b51 | |||
| 1a09ff6005 | |||
| 2794a52902 | |||
| cb796e4cfc | |||
| 522ec4fc2e | |||
| 15dc5899b0 | |||
| 7e932ffbc3 | |||
| 810596bb83 | |||
| acabf0075c | |||
| 1ed72db210 | |||
| 6bdf95dfb4 | |||
| 785ae89cd8 | |||
| 16680191de | |||
| 59b70c4d11 | |||
| f96bae40ac | |||
| ba974c73bf | |||
| e498ad3ee7 | |||
| 1de031ed06 | |||
| d6ac924b94 | |||
| ee24473cbb | |||
| c19a3cec1c | |||
| f3694be1a0 | |||
| 306d86ce58 | |||
| 2c001b63a5 | |||
| e162dda836 | |||
| 10c532bd4c | |||
| c8a7bc1d6a | |||
| 9ca3c69b49 | |||
| d1cf8c1fd5 | |||
| 018742f50f | |||
| b82d21f856 | |||
| cfaadf198f | |||
| 6698b5e07e | |||
| 37794a5e8a | |||
| a88fef2937 | |||
| da474a16a9 | |||
| 59bbfeb67f | |||
| 4e9e2ed5bd | |||
| e0593c7ca2 | |||
| 1f69df0d89 | |||
| 05706879a0 | |||
| 7e49b36198 |
@@ -7,6 +7,8 @@
|
|||||||
#############################
|
#############################
|
||||||
osrm-deps
|
osrm-deps
|
||||||
|
|
||||||
|
.ycm_extra_conf.py
|
||||||
|
|
||||||
# Compiled source #
|
# Compiled source #
|
||||||
###################
|
###################
|
||||||
*.com
|
*.com
|
||||||
|
|||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
*
|
|
||||||
!README.md
|
|
||||||
!CHANGELOG.md
|
|
||||||
!CONTRIBUTING.MD
|
|
||||||
!LICENCE.TXT
|
|
||||||
!package.json
|
|
||||||
!example
|
|
||||||
!lib/*.js
|
|
||||||
!profiles/*
|
|
||||||
!profiles/lib/*
|
|
||||||
+129
-24
@@ -7,8 +7,9 @@ git:
|
|||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
nodejs:
|
node_js:
|
||||||
- "4"
|
- "4"
|
||||||
|
- "6"
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
@@ -16,6 +17,7 @@ notifications:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
- "5.7"
|
||||||
# enable building tags
|
# enable building tags
|
||||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||||
|
|
||||||
@@ -36,6 +38,8 @@ env:
|
|||||||
- CCACHE_VERSION=3.3.1
|
- CCACHE_VERSION=3.3.1
|
||||||
- CMAKE_VERSION=3.7.2
|
- CMAKE_VERSION=3.7.2
|
||||||
- MASON="$(pwd)/scripts/mason.sh"
|
- MASON="$(pwd)/scripts/mason.sh"
|
||||||
|
- ENABLE_NODE_BINDINGS=On
|
||||||
|
- NODE="4"
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
@@ -45,12 +49,14 @@ matrix:
|
|||||||
|
|
||||||
# Debug Builds
|
# Debug Builds
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "gcc-6-debug"
|
compiler: "gcc-6-debug-cov-asan"
|
||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', '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++-6', '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-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang-4.0-debug"
|
compiler: "clang-4.0-debug"
|
||||||
@@ -61,12 +67,12 @@ matrix:
|
|||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "mason-linux-debug-santize"
|
compiler: "mason-linux-debug-asan"
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON ENABLE_NODE_BINDINGS=ON
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
|
||||||
|
|
||||||
# Release Builds
|
# Release Builds
|
||||||
- os: linux
|
- os: linux
|
||||||
@@ -75,7 +81,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "gcc-6-release"
|
compiler: "gcc-6-release"
|
||||||
@@ -104,6 +110,8 @@ matrix:
|
|||||||
compiler: "mason-osx-release"
|
compiler: "mason-osx-release"
|
||||||
# we use the xcode provides clang and don't install our own
|
# we use the xcode provides clang and don't install our own
|
||||||
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
|
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
# Disabled because of CI slowness
|
# Disabled because of CI slowness
|
||||||
#- os: linux
|
#- os: linux
|
||||||
@@ -132,11 +140,112 @@ matrix:
|
|||||||
#- packages: ['clang-4.0', '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-4.0', '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-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||||
|
|
||||||
|
# Node build jobs. These skip running the tests.
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
compiler: "node-4-mason-linux-release"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['libstdc++-5-dev']
|
||||||
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
|
||||||
|
install:
|
||||||
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
|
- |
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
|
-DENABLE_CCACHE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||||
|
- make --jobs=${JOBS}
|
||||||
|
- popd
|
||||||
|
script:
|
||||||
|
- npm run nodejs-tests
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
compiler: "node-4-mason-linux-release"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['libstdc++-5-dev']
|
||||||
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
|
||||||
|
install:
|
||||||
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
|
- |
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
|
-DENABLE_CCACHE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||||
|
- make --jobs=${JOBS}
|
||||||
|
- popd
|
||||||
|
script:
|
||||||
|
- npm run nodejs-tests
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
compiler: "node-6-mason-linux-release"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['libstdc++-5-dev']
|
||||||
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
|
||||||
|
install:
|
||||||
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
|
- |
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
|
-DENABLE_CCACHE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||||
|
- make --jobs=${JOBS}
|
||||||
|
- popd
|
||||||
|
script:
|
||||||
|
- npm run nodejs-tests
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
sudo: false
|
||||||
|
compiler: "node-6-mason-linux-release"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['libstdc++-5-dev']
|
||||||
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
|
||||||
|
install:
|
||||||
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
|
- |
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
|
-DENABLE_CCACHE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||||
|
- make --jobs=${JOBS}
|
||||||
|
- popd
|
||||||
|
script:
|
||||||
|
- npm run nodejs-tests
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
- source $NVM_DIR/nvm.sh
|
||||||
|
- nvm install $NODE
|
||||||
|
- nvm use $NODE
|
||||||
|
- node --version
|
||||||
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
|
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
|
||||||
- |
|
- |
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
if [[ -z $JOBS ]]; then
|
||||||
export JOBS=$((`nproc` + 1))
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
|
export JOBS=$((`nproc` + 1))
|
||||||
|
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||||
|
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
- |
|
- |
|
||||||
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
||||||
@@ -144,8 +253,10 @@ before_install:
|
|||||||
fi
|
fi
|
||||||
- |
|
- |
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||||
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
|
||||||
sudo mdutil -i off /
|
sudo mdutil -i off /
|
||||||
|
fi
|
||||||
|
- |
|
||||||
|
if [[ ! -f $(which yarn) ]]; then
|
||||||
npm install -g yarn
|
npm install -g yarn
|
||||||
fi
|
fi
|
||||||
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
||||||
@@ -173,15 +284,17 @@ before_install:
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
|
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
|
||||||
|
- export OSRM_INSTALL_DIR="$(pwd)/install-osrm"
|
||||||
|
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
|
||||||
|
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
||||||
|
- mkdir ${OSRM_BUILD_DIR}
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- |
|
- |
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||||
fi
|
fi
|
||||||
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
|
|
||||||
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
|
||||||
- |
|
- |
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||||
@@ -191,7 +304,8 @@ install:
|
|||||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||||
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
||||||
-DBUILD_TOOLS=ON \
|
-DBUILD_TOOLS=ON \
|
||||||
-DENABLE_CCACHE=ON
|
-DENABLE_CCACHE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||||
- echo "travis_fold:start:MAKE"
|
- echo "travis_fold:start:MAKE"
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- make tests --jobs=${JOBS}
|
- make tests --jobs=${JOBS}
|
||||||
@@ -201,10 +315,11 @@ install:
|
|||||||
- sudo make install
|
- sudo make install
|
||||||
- |
|
- |
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||||
sudo ldconfig
|
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${OSRM_INSTALL_DIR}/lib
|
||||||
fi
|
fi
|
||||||
- popd
|
- popd
|
||||||
- mkdir example/build && pushd example/build
|
- mkdir example/build && pushd example/build
|
||||||
|
- export PKG_CONFIG_PATH=${OSRM_INSTALL_DIR}/lib/pkgconfig
|
||||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||||
- make --jobs=${JOBS}
|
- make --jobs=${JOBS}
|
||||||
- popd
|
- popd
|
||||||
@@ -224,19 +339,9 @@ script:
|
|||||||
- ./unit_tests/server-tests
|
- ./unit_tests/server-tests
|
||||||
- ./unit_tests/partition-tests
|
- ./unit_tests/partition-tests
|
||||||
- |
|
- |
|
||||||
if [ -n "${ENABLE_NODE_BINDINGS}" ] && [ -z "${ENABLE_SANITIZER}" ]; then
|
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
|
||||||
npm run nodejs-tests
|
npm run nodejs-tests
|
||||||
fi
|
fi
|
||||||
- popd
|
- popd
|
||||||
- yarn test
|
- yarn test
|
||||||
|
|
||||||
after_success:
|
|
||||||
- |
|
|
||||||
if [ -n "${ENABLE_COVERAGE}" ]; then
|
|
||||||
bash <(curl -s https://codecov.io/bash)
|
|
||||||
fi
|
|
||||||
|
|
||||||
- |
|
|
||||||
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
|
|
||||||
./scripts/travis/publish.sh
|
|
||||||
fi
|
|
||||||
|
|||||||
+34
-1
@@ -1,17 +1,50 @@
|
|||||||
- Track preprocessing flag in the map matching plugin.
|
# 5.7.2
|
||||||
|
- Changes from 5.7.1:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes segmentation fault caused by the fix for 3977
|
||||||
|
|
||||||
|
# 5.7.1
|
||||||
|
- Changes from 5.7.0:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes 3995: Negative duration caused by rounding issues.
|
||||||
|
- Fixes 3977: Fixes exit number in roundabout if starting inside the roundabout
|
||||||
|
- Fixes 3981: The NodeJS documentation was outdated and incomplete.
|
||||||
|
- Fixes 4010: Performance regression while parsing CSV files. Now 5x faster.
|
||||||
|
- Fixes 3919: Turn penalties on the cyclabilty metric were disabled.
|
||||||
|
- Fixes 3992: Table plugin not checking for valid phantom nodes
|
||||||
|
- Fixes 4013: `continue_straight` interaction with bearing constraints
|
||||||
|
- Fixes 4063: Potential overflow in custom profiles for restricted ways
|
||||||
|
- Fixes 4030: Roundabout edge-case crashes post-processing
|
||||||
|
|
||||||
# 5.7.0
|
# 5.7.0
|
||||||
- Changes from 5.6
|
- Changes from 5.6
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixed 505: Invalid distance value for distance as routing weight.
|
||||||
|
- Fixed 3958: Fix traffic light penalties for non-turns
|
||||||
|
- Fixed 3933: crash when collapsing instructions
|
||||||
|
- Algorithm:
|
||||||
|
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
|
||||||
|
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
|
||||||
|
- Allows for fast metric updates in below a minute on continental sized networks (osrm-customize)
|
||||||
|
- Plugins supported: `match` and `route`
|
||||||
|
- Quickstart: `osrm-extract data.osm.pbf`, `osrm-partition data.osrm`, `osrm-customize data.osrm`, `osrm-routed --algorithm=MLD data.osrm`
|
||||||
- NodeJs Bindings
|
- NodeJs Bindings
|
||||||
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
|
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
|
||||||
|
- `OSRM` object has new option `algorihtm="CH","CoreCH","MLD"`
|
||||||
- Internals
|
- Internals
|
||||||
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
|
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
|
||||||
- Files
|
- Files
|
||||||
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
|
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
|
||||||
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
|
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
|
||||||
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
|
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
|
||||||
|
- `osrm-extract` creates new file `.osrm.cnbg` and `.cnbg_to_ebg`
|
||||||
|
- `osrm-partition` creates new file `.osrm.partition` and `.osrm.cells`
|
||||||
|
- `osrm-customize` creates new file `.osrm.mldgr`
|
||||||
- Profiles
|
- Profiles
|
||||||
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
|
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
|
||||||
|
- Map Matching:
|
||||||
|
- new option `gaps=split|ignore` to enable/disbale track splitting
|
||||||
|
- new option `tidy=true|false` to simplify traces automatically
|
||||||
|
|
||||||
# 5.6.3
|
# 5.6.3
|
||||||
- Changes from 5.6.0
|
- Changes from 5.6.0
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ endif()
|
|||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
set(OSRM_VERSION_MAJOR 5)
|
||||||
set(OSRM_VERSION_MINOR 7)
|
set(OSRM_VERSION_MINOR 7)
|
||||||
set(OSRM_VERSION_PATCH 0)
|
set(OSRM_VERSION_PATCH 2)
|
||||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||||
|
|
||||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|||||||
+126
-127
@@ -1,66 +1,59 @@
|
|||||||
# OSRM
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
||||||
|
|
||||||
The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance requires a `.osrm` network,
|
## OSRM
|
||||||
which is prepared by the OSRM Backend C++ library.
|
|
||||||
|
|
||||||
|
The `OSRM` method is the main constructor for creating an OSRM instance.
|
||||||
|
An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
||||||
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
|
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
|
||||||
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
|
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
|
||||||
|
|
||||||
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
|
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
|
||||||
node_modules/osrm/lib/binding/osrm-contract data.osrm
|
node_modules/osrm/lib/binding/osrm-contract data.osrm
|
||||||
|
|
||||||
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation or further details.
|
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
|
||||||
|
|
||||||
Once you have a complete `network.osrm` file, you can calculate networks in javascript with this library using the
|
Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
|
||||||
methods below. To create an OSRM instance with your network you need to construct an instance like this:
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM('network.osrm');
|
var osrm = new OSRM('network.osrm');
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Methods
|
**Parameters**
|
||||||
|
|
||||||
| Service | Description |
|
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Options for creating an OSRM object or string to the `.osrm` file. (optional, default `{shared_memory:true}`)
|
||||||
| -------------------------- | --------------------------------------------------------- |
|
- `options.algorithm` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
|
||||||
| [`osrm.route`](#route) | shortest path between given coordinates |
|
Make sure you prepared the dataset with the correct toolchain.
|
||||||
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
|
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
|
||||||
| [`osrm.table`](#table) | computes distance tables for given coordinates |
|
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
||||||
| [`osrm.match`](#match) | matches given coordinates to the road network |
|
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
|
||||||
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
|
|
||||||
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
|
|
||||||
|
|
||||||
#### General Options
|
### route
|
||||||
|
|
||||||
Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options, outlined below.
|
|
||||||
|
|
||||||
| Option | Values | Description | Format |
|
|
||||||
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
|
|
||||||
| coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
|
|
||||||
| bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
|
|
||||||
| radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
|
|
||||||
| hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
|
|
||||||
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
|
|
||||||
|
|
||||||
## route
|
|
||||||
|
|
||||||
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
|
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
|
||||||
- `options.alternatives` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Search for alternative routes and return as well. _Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route leg. (optional, default `false`)
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
- `options.continue_straight` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. `null`/`true`/`false`
|
- `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes and return as well.
|
||||||
|
_Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
|
||||||
|
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`)
|
||||||
|
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
|
||||||
|
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
||||||
|
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||||
|
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
|
||||||
|
`null`/`true`/`false`
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM("berlin-latest.osrm");
|
var osrm = new OSRM("berlin-latest.osrm");
|
||||||
osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, function(err, result) {
|
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
|
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
|
||||||
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
||||||
@@ -69,7 +62,7 @@ osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, funct
|
|||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
|
||||||
|
|
||||||
## nearest
|
### nearest
|
||||||
|
|
||||||
Snaps a coordinate to the street network and returns the nearest n matches.
|
Snaps a coordinate to the street network and returns the nearest n matches.
|
||||||
|
|
||||||
@@ -78,7 +71,12 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
|
|||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
|
||||||
- `options.number` **\[[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)]** Number of nearest segments that should be returned.
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
|
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
|
||||||
Must be an integer greater than or equal to `1`. (optional, default `1`)
|
Must be an integer greater than or equal to `1`. (optional, default `1`)
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
@@ -98,19 +96,26 @@ osrm.nearest(options, function(err, response) {
|
|||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
|
||||||
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
|
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
|
||||||
Each object has an additional `distance` property, which is the distance in meters to the supplied
|
Each object has an additional `distance` property, which is the distance in meters to the supplied input coordinate.
|
||||||
input coordinate.
|
|
||||||
|
|
||||||
## table
|
### table
|
||||||
|
|
||||||
Computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
|
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
|
||||||
|
tables.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
|
||||||
- `options.sources` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
|
- `options.sources` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to
|
||||||
|
use
|
||||||
location with given index as source. Default is to use all.
|
location with given index as source. Default is to use all.
|
||||||
- `options.destinations` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
|
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
|
||||||
|
#coordinates`) to use location with given index as destination. Default is to use all.
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
@@ -132,24 +137,25 @@ osrm.table(options, function(err, response) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
|
||||||
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
|
**`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.
|
||||||
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
|
Values are given in seconds.
|
||||||
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
|
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
|
||||||
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
|
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
|
||||||
|
|
||||||
## tile
|
### tile
|
||||||
|
|
||||||
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
|
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
|
||||||
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
|
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,
|
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,
|
so are in sync with actual routing results, and let you examine which roads are actually
|
||||||
|
routable,
|
||||||
and what weights they have applied.
|
and what weights they have applied.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
|
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
|
||||||
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
|
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](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/>.
|
and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
@@ -164,7 +170,7 @@ osrm.tile([0, 0, 0], function(err, response) {
|
|||||||
|
|
||||||
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
|
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
|
||||||
|
|
||||||
## match
|
### match
|
||||||
|
|
||||||
Map matching matches given GPS points to the road network in the most plausible way.
|
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
|
Please note the request might result multiple sub-traces. Large jumps in the timestamps
|
||||||
@@ -175,15 +181,16 @@ if they can not be matched successfully.
|
|||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
|
||||||
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
and per step). Can also be `geojson`. (optional, default `polyline`)
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified`
|
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
|
||||||
according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
|
||||||
- `options.timestamps` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>]** Timestamp of the input location (integers, UNIX-like timestamp).
|
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
||||||
- `options.radiuses` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** Standard deviation of GPS precision used for map matching.
|
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||||
If applicable use GPS accuracy (`double >= 0`, default `5m`).
|
- `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp).
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
@@ -203,69 +210,54 @@ osrm.match(options, function(err, response) {
|
|||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
|
||||||
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) objects representing all points of the trace in order.
|
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) 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
|
If the trace point was ommited by map matching because it is an outlier, the entry will be null.
|
||||||
`Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
|
Each `Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
|
||||||
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
|
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
|
||||||
the waypoint inside the matched route.
|
the waypoint inside the matched route.
|
||||||
**`matchings`** is an array of [`Route`](#route) objects that
|
**`matchings`** is an array of [`Route`](#route) objects that assemble the trace. Each `Route` object has an additional `confidence` property,
|
||||||
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
|
which is the confidence of the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
|
||||||
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
|
|
||||||
|
|
||||||
## trip
|
### 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 fastest path, as TSP is NP-hard it is only an approximation. Note that all input coordinates have to be connected for the trip service to work.
|
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
|
||||||
|
(farthest-insertion algorithm) for 10 or _ more waypoints and uses brute force for less than 10
|
||||||
**Parameters**
|
waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
|
only an approximation.
|
||||||
- `options.roundtrip` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route is a roundtrip. (optional, default `true`)
|
|
||||||
- `options.source` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route starts at `any` coordinate. Can also be `first`. (optional, default `any`)
|
|
||||||
- `options.destination` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route ends at `any` coordinate. Can also be `last`. (optional, default `any`)
|
|
||||||
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
|
|
||||||
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
|
|
||||||
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
|
|
||||||
and per step). Can also be `geojson`. (optional, default `polyline`)
|
|
||||||
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
|
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
|
||||||
|
|
||||||
**Fixing Start and End Points**
|
|
||||||
|
|
||||||
It is possible to explicitly set the start or end coordinate of the trip. When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
|
|
||||||
|
|
||||||
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
|
|
||||||
|
|
||||||
|
Note that all input coordinates have to be connected for the trip service to work.
|
||||||
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
|
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
|
||||||
Right now, the following combinations are possible:
|
Right now, the following combinations are possible:
|
||||||
|
|
||||||
| roundtrip | source | destination | supported |
|
| roundtrip | source | destination | supported |
|
||||||
| :-- | :-- | :-- | :-- |
|
| :-------- | :----- | :---------- | :-------- |
|
||||||
| true | first | last | **yes** |
|
| true | first | last | **yes** |
|
||||||
| true | first | any | **yes** |
|
| true | first | any | **yes** |
|
||||||
| true | any | last | **yes** |
|
| true | any | last | **yes** |
|
||||||
| true | any | any | **yes** |
|
| true | any | any | **yes** |
|
||||||
| false | first | last | **yes** |
|
| false | first | last | **yes** |
|
||||||
| false | first | any | no |
|
| false | first | any | no |
|
||||||
| false | any | last | no |
|
| false | any | last | no |
|
||||||
| false | any | any | no |
|
| false | any | any | no |
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
|
||||||
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
|
||||||
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
|
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
|
||||||
|
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
|
||||||
|
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
||||||
|
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
|
||||||
|
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
|
||||||
|
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
|
||||||
|
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
|
||||||
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
Roundtrip Request
|
|
||||||
```javascript
|
|
||||||
var osrm = new OSRM('network.osrm');
|
|
||||||
var options = {
|
|
||||||
coordinates: [
|
|
||||||
[13.36761474609375, 52.51663871100423],
|
|
||||||
[13.374481201171875, 52.506191342034576]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
osrm.trip(options, function(err, response) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.log(response.waypoints); // array of Waypoint objects
|
|
||||||
console.log(response.trips); // array of Route objects
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Non Roundtrip Request
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM('network.osrm');
|
var osrm = new OSRM('network.osrm');
|
||||||
var options = {
|
var options = {
|
||||||
@@ -285,49 +277,56 @@ osrm.trip(options, function(err, response) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
|
||||||
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
|
**`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
|
||||||
Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of the
|
Each Waypoint object has the following additional properties,
|
||||||
sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
|
1) `trips_index`: index to trips of the sub-trip the point was matched to, and
|
||||||
|
2) `waypoint_index`: index of the point in the trip.
|
||||||
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
||||||
|
|
||||||
# Responses
|
## Responses
|
||||||
|
|
||||||
Responses
|
Responses
|
||||||
|
|
||||||
## Route
|
### Route
|
||||||
|
|
||||||
Represents a route through (potentially multiple) waypoints.
|
Represents a route through (potentially multiple) waypoints.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](../http.md#route)
|
||||||
|
|
||||||
## RouteLeg
|
### RouteLeg
|
||||||
|
|
||||||
Represents a route between two waypoints.
|
Represents a route between two waypoints.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](../http.md#routeleg)
|
||||||
|
|
||||||
## RouteStep
|
### 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.
|
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.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
|
||||||
|
|
||||||
## StepManeuver
|
### StepManeuver
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmanuever)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
|
||||||
|
|
||||||
## Waypoint
|
### Waypoint
|
||||||
|
|
||||||
Object used to describe waypoint on a route.
|
Object used to describe waypoint on a route.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
@routing @bicycle @alley
|
||||||
|
Feature: Bicycle - Route around alleys
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
require 'bicycle'
|
||||||
|
properties.weight_name = 'cyclability'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Bicycle - Avoid taking alleys
|
||||||
|
Given the query options
|
||||||
|
| annotations | nodes |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-----b-----c
|
||||||
|
| : |
|
||||||
|
d.....e.....f
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | service |
|
||||||
|
| abc | residential | |
|
||||||
|
| def | service | alley |
|
||||||
|
| ad | residential | |
|
||||||
|
| be | service | alley |
|
||||||
|
| cf | residential | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | a:nodes | weight | # |
|
||||||
|
| a | f | 1:2:3:6 | 200.4 | Avoids d,e,f |
|
||||||
|
| a | e | 1:2:5 | 176.4 | Take the alley b,e if neccessary |
|
||||||
|
| d | f | 4:1:2:3:6 | 252.6 | Avoids the alley d,e,f |
|
||||||
|
|
||||||
@@ -34,3 +34,39 @@ Feature: Turn Penalties
|
|||||||
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
|
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
|
||||||
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
|
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
|
||||||
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
|
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
|
||||||
|
|
||||||
|
Scenario: Bicycle - Turn penalties on cyclability
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
require 'bicycle'
|
||||||
|
properties.weight_name = 'cyclability'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a--b-----c
|
||||||
|
|
|
||||||
|
|
|
||||||
|
d
|
||||||
|
|
||||||
|
e--------f-----------g
|
||||||
|
/
|
||||||
|
/
|
||||||
|
/
|
||||||
|
h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | residential |
|
||||||
|
| bd | residential |
|
||||||
|
| efg | residential |
|
||||||
|
| fh | residential |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | distance | weight | # |
|
||||||
|
| a | c | 900m +- 1 | 216 | Going straight has no penalties |
|
||||||
|
| a | d | 900m +- 1 | 220.2 | Turning right had penalties |
|
||||||
|
| e | g | 2100m +- 4| 503.9 | Going straght has no penalties |
|
||||||
|
| e | h | 2100m +- 4| 515.1 | Turn sharp right has even higher penalties|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
@routing @car @traffic_light
|
||||||
|
Feature: Car - Handle traffic lights
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
|
||||||
|
Scenario: Car - Encounters a traffic light
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
|
||||||
|
d-3-e-4-f
|
||||||
|
|
||||||
|
g-h-i k-l-m
|
||||||
|
| |
|
||||||
|
j n
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
| def | primary |
|
||||||
|
| ghi | primary |
|
||||||
|
| klm | primary |
|
||||||
|
| hj | primary |
|
||||||
|
| ln | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway |
|
||||||
|
| e | traffic_signals |
|
||||||
|
| l | traffic_signals |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | time | # |
|
||||||
|
| 1 | 2 | 11.1s | no turn with no traffic light |
|
||||||
|
| 3 | 4 | 13.1s | no turn with traffic light |
|
||||||
|
| g | j | 18.7s | turn with no traffic light |
|
||||||
|
| k | n | 20.7s | turn with traffic light |
|
||||||
@@ -48,7 +48,6 @@ Feature: Traffic - turn penalties
|
|||||||
| mn | primary |
|
| mn | primary |
|
||||||
| mp | primary |
|
| mp | primary |
|
||||||
And the profile "car"
|
And the profile "car"
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
|
|
||||||
Scenario: Weighting not based on turn penalty file
|
Scenario: Weighting not based on turn penalty file
|
||||||
When I route I should get
|
When I route I should get
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ Feature: Car - weights
|
|||||||
| cd | primary | yes |
|
| cd | primary | yes |
|
||||||
| be | service | yes |
|
| be | service | yes |
|
||||||
| ec | service | yes |
|
| ec | service | yes |
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the speed file
|
And the speed file
|
||||||
@@ -62,3 +61,28 @@ Feature: Car - weights
|
|||||||
| from | to | route | speed | weight |
|
| from | to | route | speed | weight |
|
||||||
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
||||||
| a | e | ab,be,be | 14 km/h | 112 |
|
| a | e | ab,be,be | 14 km/h | 112 |
|
||||||
|
|
||||||
|
Scenario: Distance weights
|
||||||
|
Given the profile file "car" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.weight_name = 'distance'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c
|
||||||
|
|
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| bd |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route | distance | weights | times |
|
||||||
|
| a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
|
||||||
|
| b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
|
||||||
|
| a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s |
|
||||||
|
|||||||
@@ -1019,3 +1019,39 @@ Feature: Collapse
|
|||||||
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
|
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
|
||||||
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
|
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
|
||||||
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
|
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
|
||||||
|
|
||||||
|
|
||||||
|
# http://www.openstreetmap.org/way/92415447 #3933
|
||||||
|
Scenario: Use total angle for turn instruction if entry step has large distance
|
||||||
|
# """
|
||||||
|
# kf-_ a
|
||||||
|
# | - b
|
||||||
|
# | c
|
||||||
|
# |d
|
||||||
|
# e
|
||||||
|
# |
|
||||||
|
# i
|
||||||
|
# """
|
||||||
|
|
||||||
|
And the node locations
|
||||||
|
| node | lat | lon | #id |
|
||||||
|
| a | -33.9644254 | 151.1378673 | 33226063 |
|
||||||
|
| b | -33.9644373 | 151.1377172 | 1072787030 |
|
||||||
|
| c | -33.9644791 | 151.1374452 | 4222903609 |
|
||||||
|
| d | -33.9645661 | 151.1372654 | 4222903610 |
|
||||||
|
| e | -33.9646986 | 151.1371539 | 4222903611 |
|
||||||
|
| f | -33.964386 | 151.1372133 | 1072786875 |
|
||||||
|
| i | -33.9661796 | 151.1368491 | 2781176918 |
|
||||||
|
| k | -33.9643781 | 151.1371422 | 1684173853 |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway | #id |
|
||||||
|
| ab | trunk | President Avenue | yes | 92415447 |
|
||||||
|
| bcde | trunk | President Avenue | yes | 422534457 |
|
||||||
|
| bf | trunk | President Avenue | yes | 447779786 |
|
||||||
|
| fk | trunk | President Avenue | yes | 179293012 |
|
||||||
|
| fei | trunk | Princes Highway | yes | 130099670 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns | locations |
|
||||||
|
| a,i | President Avenue,Princes Highway,Princes Highway | depart,turn left,arrive | a,b,i |
|
||||||
|
|||||||
@@ -222,6 +222,43 @@ Feature: Basic Roundabout
|
|||||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
||||||
|
|
||||||
|
Scenario: Mixed Entry and Exit - clockwise order
|
||||||
|
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 |
|
||||||
|
| behkb | 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-3,arrive |
|
||||||
|
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
||||||
|
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
|
||||||
|
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
||||||
|
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
|
||||||
|
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
||||||
|
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
|
||||||
|
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
||||||
|
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
|
||||||
|
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
||||||
|
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
|
||||||
|
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
||||||
|
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
|
||||||
|
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||||
|
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
|
||||||
|
|
||||||
Scenario: Mixed Entry and Exit - segregated roads, different names
|
Scenario: Mixed Entry and Exit - segregated roads, different names
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@@ -681,3 +718,105 @@ Feature: Basic Roundabout
|
|||||||
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
|
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
|
||||||
| u,s | ug,ds,ds | depart,roundabout-exit-4,arrive |
|
| u,s | ug,ds,ds | depart,roundabout-exit-4,arrive |
|
||||||
| u,t | ug,ft,ft | depart,roundabout-exit-5,arrive |
|
| u,t | ug,ft,ft | depart,roundabout-exit-5,arrive |
|
||||||
|
|
||||||
|
|
||||||
|
@3762
|
||||||
|
Scenario: Only Enter
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
b
|
||||||
|
i c e ~ ~ ~ f - h
|
||||||
|
j d
|
||||||
|
k g
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | junction | route |
|
||||||
|
| ab | | |
|
||||||
|
| ef | | ferry |
|
||||||
|
| fh | | |
|
||||||
|
| dg | | |
|
||||||
|
| ic | | |
|
||||||
|
| jk | | |
|
||||||
|
| bcjdeb | roundabout | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Drive through roundabout
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
b e d f
|
||||||
|
c
|
||||||
|
g h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | junction | oneway |
|
||||||
|
| abcda | roundabout | yes |
|
||||||
|
| edf | | |
|
||||||
|
| gch | | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route | turns |
|
||||||
|
| e,f | 90 90 | edf,edf,edf | depart,roundabout-exit-1,arrive |
|
||||||
|
| e,h | 90 135 | edf,gch,gch | depart,roundabout-exit-2,arrive |
|
||||||
|
| g,f | 45 90 | gch,edf,edf | depart,roundabout-exit-2,arrive |
|
||||||
|
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
|
||||||
|
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |
|
||||||
|
|
||||||
|
@4030 @4075
|
||||||
|
Scenario: Service roundabout with service exits
|
||||||
|
# Counting of service exits must be adjusted in #4075
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
e
|
||||||
|
f a d
|
||||||
|
g b1c
|
||||||
|
h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | junction |
|
||||||
|
| abcda | service | roundabout |
|
||||||
|
| de | service | |
|
||||||
|
| af | service | |
|
||||||
|
| bg | tertiary | |
|
||||||
|
| bh | service | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns |
|
||||||
|
| 1 | e | abcda,de,de | depart,roundabout-exit-1,arrive |
|
||||||
|
| 1 | f | abcda,af,af | depart,roundabout-exit-1,arrive |
|
||||||
|
| 1 | g | abcda,bg,bg | depart,roundabout-exit-1,arrive |
|
||||||
|
| 1 | h | abcda,bh,bh | depart,roundabout-exit-1,arrive |
|
||||||
|
|
||||||
|
Scenario: CCW and CW roundabouts with overlaps
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a d g h
|
||||||
|
|
||||||
|
b c j i
|
||||||
|
f e k l
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | junction |
|
||||||
|
| abcda | tertiary | roundabout |
|
||||||
|
| ed | tertiary | |
|
||||||
|
| af | tertiary | |
|
||||||
|
| ghijg | tertiary | roundabout |
|
||||||
|
| kg | tertiary | |
|
||||||
|
| hl | tertiary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | distance |
|
||||||
|
| e | f | ed,af,af | depart,roundabout-exit-1,arrive | 80.1m |
|
||||||
|
| f | e | af,ed,ed | depart,roundabout-exit-1,arrive | 120.1m |
|
||||||
|
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
|
||||||
|
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,30 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
|
|||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
|
|
||||||
Scenario: Logging weight with updates over factor of 2, long segment
|
Scenario: Logging weight with updates over factor of 2, long segment
|
||||||
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
||||||
|
Then stderr should not contain "Speed values were used to update 2 segment(s)"
|
||||||
And stderr should contain "Segment: 1,2"
|
And stderr should contain "Segment: 1,2"
|
||||||
And stderr should contain "Segment: 1,3"
|
And stderr should contain "Segment: 1,3"
|
||||||
And I route I should get
|
And I route I should get
|
||||||
| from | to | route | speed |
|
| from | to | route | speed |
|
||||||
| a | b | ab,ab | 100 km/h |
|
| a | b | ab,ab | 100 km/h |
|
||||||
| a | c | ac,ac | 100 km/h |
|
| a | c | ac,ac | 100 km/h |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Logging using weigts as durations for non-duration profile
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
properties.weight_name = 'steps'
|
||||||
|
function way_function(way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.weight = 1
|
||||||
|
result.duration = 1
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
||||||
|
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"
|
||||||
|
|||||||
@@ -16,10 +16,13 @@ module.exports = function () {
|
|||||||
|
|
||||||
var headers = new Set(table.raw()[0]);
|
var headers = new Set(table.raw()[0]);
|
||||||
|
|
||||||
|
got.code = 'unknown';
|
||||||
if (res.body.length) {
|
if (res.body.length) {
|
||||||
json = JSON.parse(res.body);
|
json = JSON.parse(res.body);
|
||||||
|
got.code = json.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (headers.has('status')) {
|
if (headers.has('status')) {
|
||||||
got.status = json.status.toString();
|
got.status = json.status.toString();
|
||||||
}
|
}
|
||||||
@@ -33,7 +36,7 @@ module.exports = function () {
|
|||||||
got['#'] = row['#'];
|
got['#'] = row['#'];
|
||||||
}
|
}
|
||||||
|
|
||||||
var subMatchings = [],
|
var subMatchings = [''],
|
||||||
turns = '',
|
turns = '',
|
||||||
route = '',
|
route = '',
|
||||||
duration = '',
|
duration = '',
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ module.exports = function () {
|
|||||||
|
|
||||||
r.query = this.query;
|
r.query = this.query;
|
||||||
r.json = JSON.parse(body);
|
r.json = JSON.parse(body);
|
||||||
|
r.code = r.json.code;
|
||||||
r.status = res.statusCode === 200 ? 'x' : null;
|
r.status = res.statusCode === 200 ? 'x' : null;
|
||||||
if (r.status) {
|
if (r.status) {
|
||||||
r.route = this.wayList(r.json.routes[0]);
|
r.route = this.wayList(r.json.routes[0]);
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ module.exports = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var json;
|
var json;
|
||||||
|
got.code = 'unknown';
|
||||||
if (res.body.length) {
|
if (res.body.length) {
|
||||||
json = JSON.parse(res.body);
|
json = JSON.parse(res.body);
|
||||||
|
got.code = json.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('status')) {
|
if (headers.has('status')) {
|
||||||
@@ -153,11 +155,11 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (row.source) {
|
if (row.source) {
|
||||||
params.source = got.source = row.source;
|
params.source = got.source = row.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row.destination) {
|
if (row.destination) {
|
||||||
params.destination = got.destination = row.destination;
|
params.destination = got.destination = row.destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row.hasOwnProperty('roundtrip')) { //roundtrip is a boolean so row.roundtrip alone doesn't work as a check here
|
if (row.hasOwnProperty('roundtrip')) { //roundtrip is a boolean so row.roundtrip alone doesn't work as a check here
|
||||||
params.roundtrip = got.roundtrip = row.roundtrip;
|
params.roundtrip = got.roundtrip = row.roundtrip;
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ module.exports = function () {
|
|||||||
|
|
||||||
let json = JSON.parse(body);
|
let json = JSON.parse(body);
|
||||||
|
|
||||||
|
got.code = json.code;
|
||||||
|
|
||||||
let hasRoute = json.code === 'Ok';
|
let hasRoute = json.code === 'Ok';
|
||||||
|
|
||||||
if (hasRoute) {
|
if (hasRoute) {
|
||||||
@@ -79,102 +81,102 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (headers.has('route')) {
|
if (headers.has('route')) {
|
||||||
got.route = (instructions || '').trim();
|
got.route = (instructions || '').trim();
|
||||||
|
|
||||||
if (headers.has('summary')) {
|
|
||||||
got.summary = (summary || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('alternative')) {
|
|
||||||
// TODO examine more than first alternative?
|
|
||||||
got.alternative ='';
|
|
||||||
if (json.routes && json.routes.length > 1)
|
|
||||||
got.alternative = this.wayList(json.routes[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var distance = hasRoute && json.routes[0].distance,
|
|
||||||
time = hasRoute && json.routes[0].duration,
|
|
||||||
weight = hasRoute && json.routes[0].weight;
|
|
||||||
|
|
||||||
if (headers.has('distance')) {
|
|
||||||
if (row.distance.length) {
|
|
||||||
if (!row.distance.match(/\d+m/))
|
|
||||||
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
|
||||||
got.distance = instructions ? util.format('%dm', distance) : '';
|
|
||||||
} else {
|
|
||||||
got.distance = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('weight')) {
|
|
||||||
if (row.weight.length) {
|
|
||||||
if (!row.weight.match(/[\d\.]+/))
|
|
||||||
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
|
||||||
got.weight = instructions ? util.format('%d', weight) : '';
|
|
||||||
} else {
|
|
||||||
got.weight = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('time')) {
|
|
||||||
if (!row.time.match(/\d+s/))
|
|
||||||
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
|
||||||
got.time = instructions ? util.format('%ds', time) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('lanes')) {
|
|
||||||
got.lanes = (lanes || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('speed')) {
|
|
||||||
if (row.speed !== '' && instructions) {
|
|
||||||
if (!row.speed.match(/\d+ km\/h/))
|
|
||||||
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
|
||||||
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
|
||||||
got.speed = util.format('%d km/h', speed);
|
|
||||||
} else {
|
|
||||||
got.speed = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('intersections')) {
|
|
||||||
got.intersections = (intersections || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('locations')){
|
|
||||||
got.locations = (locations || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if header matches 'a:*', parse out the values for *
|
|
||||||
// and return in that header
|
|
||||||
headers.forEach((k) => {
|
|
||||||
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
|
||||||
if (k.match(/^a:/)) {
|
|
||||||
let a_type = k.slice(2);
|
|
||||||
if (whitelist.indexOf(a_type) == -1)
|
|
||||||
return cb(new Error('Unrecognized annotation field', a_type));
|
|
||||||
if (annotation && !annotation[a_type])
|
|
||||||
return cb(new Error('Annotation not found in response', a_type));
|
|
||||||
got[k] = annotation && annotation[a_type] || '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var putValue = (key, value) => {
|
|
||||||
if (headers.has(key)) got[key] = instructions ? value : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
putValue('ref', refs);
|
|
||||||
putValue('bearing', bearings);
|
|
||||||
putValue('turns', turns);
|
|
||||||
putValue('modes', modes);
|
|
||||||
putValue('times', times);
|
|
||||||
putValue('distances', distances);
|
|
||||||
putValue('pronunciations', pronunciations);
|
|
||||||
putValue('destinations', destinations);
|
|
||||||
putValue('weight_name', weight_name);
|
|
||||||
putValue('weights', weights);
|
|
||||||
putValue('weight', weight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers.has('summary')) {
|
||||||
|
got.summary = (summary || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('alternative')) {
|
||||||
|
// TODO examine more than first alternative?
|
||||||
|
got.alternative ='';
|
||||||
|
if (json.routes && json.routes.length > 1)
|
||||||
|
got.alternative = this.wayList(json.routes[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var distance = hasRoute && json.routes[0].distance,
|
||||||
|
time = hasRoute && json.routes[0].duration,
|
||||||
|
weight = hasRoute && json.routes[0].weight;
|
||||||
|
|
||||||
|
if (headers.has('distance')) {
|
||||||
|
if (row.distance.length) {
|
||||||
|
if (!row.distance.match(/\d+m/))
|
||||||
|
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
||||||
|
got.distance = instructions ? util.format('%dm', distance) : '';
|
||||||
|
} else {
|
||||||
|
got.distance = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('weight')) {
|
||||||
|
if (row.weight.length) {
|
||||||
|
if (!row.weight.match(/[\d\.]+/))
|
||||||
|
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
||||||
|
got.weight = instructions ? util.format('%d', weight) : '';
|
||||||
|
} else {
|
||||||
|
got.weight = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('time')) {
|
||||||
|
if (!row.time.match(/\d+s/))
|
||||||
|
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
||||||
|
got.time = instructions ? util.format('%ds', time) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('lanes')) {
|
||||||
|
got.lanes = (lanes || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('speed')) {
|
||||||
|
if (row.speed !== '' && instructions) {
|
||||||
|
if (!row.speed.match(/\d+ km\/h/))
|
||||||
|
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
||||||
|
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
||||||
|
got.speed = util.format('%d km/h', speed);
|
||||||
|
} else {
|
||||||
|
got.speed = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('intersections')) {
|
||||||
|
got.intersections = (intersections || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('locations')){
|
||||||
|
got.locations = (locations || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if header matches 'a:*', parse out the values for *
|
||||||
|
// and return in that header
|
||||||
|
headers.forEach((k) => {
|
||||||
|
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
||||||
|
if (k.match(/^a:/)) {
|
||||||
|
let a_type = k.slice(2);
|
||||||
|
if (whitelist.indexOf(a_type) == -1)
|
||||||
|
return cb(new Error('Unrecognized annotation field', a_type));
|
||||||
|
if (annotation && !annotation[a_type])
|
||||||
|
return cb(new Error('Annotation not found in response', a_type));
|
||||||
|
got[k] = annotation && annotation[a_type] || '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var putValue = (key, value) => {
|
||||||
|
if (headers.has(key)) got[key] = instructions ? value : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
putValue('ref', refs);
|
||||||
|
putValue('bearing', bearings);
|
||||||
|
putValue('turns', turns);
|
||||||
|
putValue('modes', modes);
|
||||||
|
putValue('times', times);
|
||||||
|
putValue('distances', distances);
|
||||||
|
putValue('pronunciations', pronunciations);
|
||||||
|
putValue('destinations', destinations);
|
||||||
|
putValue('weight_name', weight_name);
|
||||||
|
putValue('weights', weights);
|
||||||
|
putValue('weight', weight);
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ Feature: Basic Map Matching
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the query options
|
Given the query options
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
|
|
||||||
@@ -213,7 +212,7 @@ Feature: Basic Map Matching
|
|||||||
|
|
||||||
And the speed file
|
And the speed file
|
||||||
"""
|
"""
|
||||||
1,2,36
|
1,2,36,10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
@@ -240,7 +239,7 @@ Feature: Basic Map Matching
|
|||||||
|
|
||||||
And the speed file
|
And the speed file
|
||||||
"""
|
"""
|
||||||
1,2,36
|
1,2,36,10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
|||||||
@@ -36,3 +36,38 @@ Feature: Projection to nearest point on road
|
|||||||
| from | to | route | distance |
|
| from | to | route | distance |
|
||||||
| d | b | abc,abc | 0m |
|
| d | b | abc,abc | 0m |
|
||||||
| b | d | abc,abc | 0m |
|
| b | d | abc,abc | 0m |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Projection results negative duration
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
function segment_function (segment)
|
||||||
|
segment.weight = 5.5
|
||||||
|
segment.duration = 2.8
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node locations
|
||||||
|
| node | lon | lat |
|
||||||
|
| e | -51.218994 | -30.023866 |
|
||||||
|
| f | -51.218918 | -30.023741 |
|
||||||
|
| 1 | -51.219109 | -30.023766 |
|
||||||
|
| 2 | -51.219109 | -30.023764 |
|
||||||
|
| 3 | -51.219109 | -30.023763 |
|
||||||
|
| 4 | -51.219109 | -30.023762 |
|
||||||
|
| 5 | -51.219109 | -30.023761 |
|
||||||
|
| 6 | -51.219109 | -30.023756 |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ef |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | time | weight |
|
||||||
|
| 1,4 | ef,ef | 0.4m | 0.1s | 0.1 |
|
||||||
|
| 2,4 | ef,ef | 0.1m | 0s | 0 |
|
||||||
|
| 3,4 | ef,ef | 0.1m | 0s | 0 |
|
||||||
|
| 4,4 | ef,ef | 0m | 0s | 0 |
|
||||||
|
| 5,4 | ef,ef | 0.1m | 0s | 0.1 |
|
||||||
|
| 6,4 | ef,ef | 0.6m | 0.1s | 0.2 |
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ Feature: Traffic - speeds
|
|||||||
| df | primary |
|
| df | primary |
|
||||||
| fb | primary |
|
| fb | primary |
|
||||||
And the profile "testbot"
|
And the profile "testbot"
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file
|
Scenario: Weighting based on speed file
|
||||||
@@ -30,12 +29,12 @@ Feature: Traffic - speeds
|
|||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the speed file
|
And the speed file
|
||||||
"""
|
"""
|
||||||
1,2,0
|
1,2,0,0
|
||||||
2,1,0
|
2,1,0,0
|
||||||
2,3,27
|
2,3,27,7.5
|
||||||
3,2,27
|
3,2,27,7.5
|
||||||
1,4,27
|
1,4,27,7.5
|
||||||
4,1,27
|
4,1,27,7.5
|
||||||
"""
|
"""
|
||||||
And the query options
|
And the query options
|
||||||
| annotations | datasources |
|
| annotations | datasources |
|
||||||
@@ -56,12 +55,12 @@ Feature: Traffic - speeds
|
|||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the speed file
|
And the speed file
|
||||||
"""
|
"""
|
||||||
1,2,1,20020.7
|
1,2,1,0.2777777
|
||||||
2,1,1,20020.7
|
2,1,1
|
||||||
2,3,27,741.5
|
2,3,27
|
||||||
3,2,27,741.5
|
3,2,27,7.5
|
||||||
1,4,27,1275.7
|
1,4,27,7.5
|
||||||
4,1,27,1275.7
|
4,1,27,7.5
|
||||||
"""
|
"""
|
||||||
And the query options
|
And the query options
|
||||||
| annotations | datasources |
|
| annotations | datasources |
|
||||||
@@ -89,26 +88,26 @@ Feature: Traffic - speeds
|
|||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the speed file
|
And the speed file
|
||||||
"""
|
"""
|
||||||
1,2,1,20020.789
|
1,2,1,0.27777777
|
||||||
2,1,1,20020.123
|
2,1,1,0.27777777
|
||||||
2,3,27,741.56789
|
2,3,27,7.5
|
||||||
3,2,27,741.3
|
3,2,27
|
||||||
1,4,1,34445.12
|
1,4,1
|
||||||
4,1,1,34445.3
|
4,1,1
|
||||||
"""
|
"""
|
||||||
And the query options
|
And the query options
|
||||||
| annotations | datasources |
|
| annotations | datasources |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed | weights | a:datasources |
|
| from | to | route | speed | weights | a:datasources |
|
||||||
| a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
|
| a | b | ab,ab | 1 km/h | 20020.735,0 | 1:0 |
|
||||||
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
|
| a | c | ab,bc,bc | 2 km/h | 20020.735,741.509,0 | 1:1:0 |
|
||||||
| b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
|
| b | c | bc,bc | 27 km/h | 741.509,0 | 1:0 |
|
||||||
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
|
| a | d | ab,eb,de,de | 2 km/h | 20020.735,378.169,400.415,0 | 1:0:0 |
|
||||||
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
|
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
|
||||||
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
|
| g | b | ab,ab | 1 km/h | 10010.365,0 | 1:0 |
|
||||||
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
|
| a | g | ab,ab | 1 km/h | 10010.37,0 | 1 |
|
||||||
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
|
| g | a | ab,ab | 1 km/h | 10010.37,0 | 1:1 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Speeds that isolate a single node (a)
|
Scenario: Speeds that isolate a single node (a)
|
||||||
@@ -121,10 +120,10 @@ Feature: Traffic - speeds
|
|||||||
"""
|
"""
|
||||||
1,2,0
|
1,2,0
|
||||||
2,1,0
|
2,1,0
|
||||||
2,3,27
|
2,3,27,7.5
|
||||||
3,2,27
|
3,2,27,7.5
|
||||||
1,4,0
|
1,4,0,0
|
||||||
4,1,0
|
4,1,0,0
|
||||||
"""
|
"""
|
||||||
And the query options
|
And the query options
|
||||||
| annotations | true |
|
| annotations | true |
|
||||||
@@ -154,3 +153,11 @@ Feature: Traffic - speeds
|
|||||||
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
And stderr should contain "malformed"
|
And stderr should contain "malformed"
|
||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
|
|
||||||
|
Scenario: Check with an empty speed file
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
And the data has been extracted
|
||||||
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
|
And it should exit successfully
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
|
|||||||
| dg | primary |
|
| dg | primary |
|
||||||
And the profile "testbot"
|
And the profile "testbot"
|
||||||
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
|
# 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
|
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
|
||||||
Given the turn penalty file
|
Given the turn penalty file
|
||||||
|
|||||||
@@ -352,3 +352,64 @@ Feature: Via points
|
|||||||
| waypoints | bearings | route | turns |
|
| waypoints | bearings | route | turns |
|
||||||
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
|
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
|
||||||
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
|
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
|
||||||
|
|
||||||
|
Scenario: Continue Straight in presence of Bearings
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
h - a 1 b -- g
|
||||||
|
| |
|
||||||
|
| |- 2 c - f
|
||||||
|
| 3
|
||||||
|
e ------ d - i
|
||||||
|
|
|
||||||
|
j
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| continue_straight | false |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | no |
|
||||||
|
| bc | no |
|
||||||
|
| cdea | no |
|
||||||
|
| ah | yes |
|
||||||
|
| bg | yes |
|
||||||
|
| cf | yes |
|
||||||
|
| di | yes |
|
||||||
|
| dj | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route |
|
||||||
|
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,cdea,cdea |
|
||||||
|
|
||||||
|
Scenario: Continue Straight in presence of Bearings
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
h - a 1 b -- g
|
||||||
|
| |
|
||||||
|
| |- 2 c - f
|
||||||
|
| 3
|
||||||
|
e ------ d - i
|
||||||
|
|
|
||||||
|
j
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| continue_straight | true |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | no |
|
||||||
|
| bc | no |
|
||||||
|
| cdea | no |
|
||||||
|
| ah | yes |
|
||||||
|
| bg | yes |
|
||||||
|
| cf | yes |
|
||||||
|
| di | yes |
|
||||||
|
| dj | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route |
|
||||||
|
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,ab,cdea,cdea,cdea |
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ Feature: Weight tests
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the query options
|
Given the query options
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
|
|
||||||
@@ -284,8 +283,8 @@ Feature: Weight tests
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | distance | weights | times |
|
| waypoints | route | distance | weights | times |
|
||||||
| a,d | , | 59.9m | 62,0 | 24s,0s |
|
| a,d | , | 59.9m | 20.5,0 | 24s,0s |
|
||||||
| a,e | ,, | 60.1m | 68.7,10,0 | 38.5s,11s,0s |
|
| a,e | ,, | 60.1m | 27.2,10,0 | 38.5s,11s,0s |
|
||||||
| d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s |
|
| d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s |
|
||||||
|
|
||||||
@traffic @speed
|
@traffic @speed
|
||||||
@@ -320,6 +319,6 @@ Feature: Weight tests
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | distance | weights | times |
|
| waypoints | route | distance | weights | times |
|
||||||
| a,d | abcd,abcd | 59.9m | 6.993,0 | 7s,0s |
|
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
||||||
| a,e | abcd,ce,ce | 60.1m | 6.002,2.002,0 | 6s,2s,0s |
|
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
||||||
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
Feature: Check zero speed updates
|
||||||
|
|
||||||
|
Scenario: Matching on restricted way, single segment
|
||||||
|
Given the query options
|
||||||
|
| geometries | geojson |
|
||||||
|
| annotations | true |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1--b--c-2-d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcd |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | code |
|
||||||
|
| 12 | NoMatch |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Matching restricted way, both segments
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1--b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | code |
|
||||||
|
| 12 | NoMatch |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Matching on restricted oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1--b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | yes |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | code |
|
||||||
|
| 12 | NoMatch |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Routing on restricted way
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | code |
|
||||||
|
| 1 | 2 | NoRoute |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Routing on restricted oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | yes |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | bearings | code |
|
||||||
|
| 1 | 2 | 270 270 | NoRoute |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Via routing on restricted oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c-3-d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | code |
|
||||||
|
| 1,2,3 | NoRoute |
|
||||||
|
| 3,2,1 | NoRoute |
|
||||||
|
|
||||||
|
|
||||||
|
@trip
|
||||||
|
Scenario: Trip
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
| cb |
|
||||||
|
| da |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
1,2,0
|
||||||
|
2,1,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I plan a trip I should get
|
||||||
|
| waypoints | trips | code |
|
||||||
|
| a,b,c,d | abcda | NoTrips |
|
||||||
|
| d,b,c,a | dbcad | NoTrips |
|
||||||
@@ -80,6 +80,8 @@ inline Result keep_all(const MatchParameters ¶ms)
|
|||||||
|
|
||||||
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(!params.coordinates.empty());
|
||||||
|
|
||||||
Result result;
|
Result result;
|
||||||
|
|
||||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||||
@@ -91,10 +93,8 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
Thresholds running{0., 0};
|
Thresholds running{0., 0};
|
||||||
|
|
||||||
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
|
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
|
||||||
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
|
for (std::size_t current = 0, next = 1; next < params.coordinates.size() - 1; ++current, ++next)
|
||||||
{
|
{
|
||||||
const auto next = current + 1;
|
|
||||||
|
|
||||||
auto distance_delta = util::coordinate_calculation::haversineDistance(
|
auto distance_delta = util::coordinate_calculation::haversineDistance(
|
||||||
params.coordinates[current], params.coordinates[next]);
|
params.coordinates[current], params.coordinates[next]);
|
||||||
running.distance_in_meters += distance_delta;
|
running.distance_in_meters += distance_delta;
|
||||||
@@ -130,7 +130,11 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
// Always use the last coordinate if more than two original coordinates
|
||||||
|
if (params.coordinates.size() > 1)
|
||||||
|
{
|
||||||
|
result.tidied_to_original.push_back(params.coordinates.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||||
|
|||||||
@@ -167,8 +167,8 @@ class RouteAPI : public BaseAPI
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
guidance::trimShortSegments(steps, leg_geometry);
|
guidance::trimShortSegments(steps, leg_geometry);
|
||||||
leg.steps = guidance::collapseTurnInstructions(std::move(steps));
|
leg.steps = guidance::postProcess(std::move(steps));
|
||||||
leg.steps = guidance::postProcess(std::move(leg.steps));
|
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
|
||||||
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
||||||
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
|
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
|
||||||
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
||||||
|
|||||||
@@ -416,6 +416,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
|
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check phantom node segments validity
|
||||||
|
auto areSegmentsValid = [](auto first, auto last) -> bool {
|
||||||
|
return std::find(first, last, INVALID_EDGE_WEIGHT) == last;
|
||||||
|
};
|
||||||
|
bool is_forward_valid_source =
|
||||||
|
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
|
||||||
|
bool is_forward_valid_target =
|
||||||
|
areSegmentsValid(forward_weight_vector.begin(),
|
||||||
|
forward_weight_vector.begin() + data.fwd_segment_position + 1);
|
||||||
|
bool is_reverse_valid_source =
|
||||||
|
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
|
||||||
|
bool is_reverse_valid_target = areSegmentsValid(
|
||||||
|
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
|
||||||
|
|
||||||
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
||||||
forward_weight,
|
forward_weight,
|
||||||
reverse_weight,
|
reverse_weight,
|
||||||
@@ -425,6 +439,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_duration,
|
reverse_duration,
|
||||||
forward_duration_offset,
|
forward_duration_offset,
|
||||||
reverse_duration_offset,
|
reverse_duration_offset,
|
||||||
|
is_forward_valid_source,
|
||||||
|
is_forward_valid_target,
|
||||||
|
is_reverse_valid_source,
|
||||||
|
is_reverse_valid_target,
|
||||||
point_on_segment,
|
point_on_segment,
|
||||||
input_coordinate},
|
input_coordinate},
|
||||||
current_perpendicular_distance};
|
current_perpendicular_distance};
|
||||||
|
|||||||
@@ -170,10 +170,13 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
weight = weight + target_weight;
|
weight = weight + target_weight;
|
||||||
if (route_data.empty())
|
if (route_data.empty())
|
||||||
{
|
{
|
||||||
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
|
|
||||||
: source_node.forward_duration);
|
|
||||||
weight -=
|
weight -=
|
||||||
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
|
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
|
||||||
|
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
|
||||||
|
: source_node.forward_duration);
|
||||||
|
// use rectified linear unit function to avoid negative duration values
|
||||||
|
// due to flooring errors in phantom snapping
|
||||||
|
duration = std::max(0, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string summary;
|
std::string summary;
|
||||||
|
|||||||
@@ -222,10 +222,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
// u-------------v
|
// u-------------v
|
||||||
// | |---------| source_weight
|
// | |---------| source_weight
|
||||||
// | |---| target_weight
|
// | |---| target_weight
|
||||||
|
BOOST_ASSERT(target_weight >= source_weight);
|
||||||
const EdgeWeight weight = target_weight - source_weight;
|
const EdgeWeight weight = target_weight - source_weight;
|
||||||
const EdgeWeight duration = target_duration - source_duration;
|
|
||||||
BOOST_ASSERT(weight >= 0);
|
// use rectified linear unit function to avoid negative duration values
|
||||||
BOOST_ASSERT(duration >= 0);
|
// due to flooring errors in phantom snapping
|
||||||
|
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
|
||||||
|
const EdgeWeight duration = std::max(0, target_duration - source_duration);
|
||||||
|
|
||||||
steps.push_back(RouteStep{source_node.name_id,
|
steps.push_back(RouteStep{source_node.name_id,
|
||||||
facade.GetNameForID(source_node.name_id).to_string(),
|
facade.GetNameForID(source_node.name_id).to_string(),
|
||||||
|
|||||||
@@ -46,37 +46,6 @@ namespace engine
|
|||||||
|
|
||||||
struct PhantomNode
|
struct PhantomNode
|
||||||
{
|
{
|
||||||
PhantomNode(SegmentID forward_segment_id,
|
|
||||||
SegmentID reverse_segment_id,
|
|
||||||
unsigned name_id,
|
|
||||||
EdgeWeight forward_weight,
|
|
||||||
EdgeWeight reverse_weight,
|
|
||||||
EdgeWeight forward_weight_offset,
|
|
||||||
EdgeWeight reverse_weight_offset,
|
|
||||||
EdgeWeight forward_duration,
|
|
||||||
EdgeWeight reverse_duration,
|
|
||||||
EdgeWeight forward_duration_offset,
|
|
||||||
EdgeWeight reverse_duration_offset,
|
|
||||||
unsigned packed_geometry_id_,
|
|
||||||
bool is_tiny_component,
|
|
||||||
unsigned component_id,
|
|
||||||
util::Coordinate location,
|
|
||||||
util::Coordinate input_location,
|
|
||||||
unsigned short fwd_segment_position,
|
|
||||||
extractor::TravelMode forward_travel_mode,
|
|
||||||
extractor::TravelMode backward_travel_mode)
|
|
||||||
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
|
|
||||||
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
|
|
||||||
forward_weight_offset(forward_weight_offset),
|
|
||||||
reverse_weight_offset(reverse_weight_offset), forward_duration(forward_duration),
|
|
||||||
reverse_duration(reverse_duration), forward_duration_offset(forward_duration_offset),
|
|
||||||
reverse_duration_offset(reverse_duration_offset), packed_geometry_id(packed_geometry_id_),
|
|
||||||
component{component_id, is_tiny_component}, location(std::move(location)),
|
|
||||||
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
|
|
||||||
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PhantomNode()
|
PhantomNode()
|
||||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
@@ -86,7 +55,9 @@ struct PhantomNode
|
|||||||
forward_duration_offset(0), reverse_duration_offset(0),
|
forward_duration_offset(0), reverse_duration_offset(0),
|
||||||
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
||||||
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE), is_valid_forward_source(false),
|
||||||
|
is_valid_forward_target(false), is_valid_reverse_source(false),
|
||||||
|
is_valid_reverse_target(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +105,23 @@ struct PhantomNode
|
|||||||
|
|
||||||
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
||||||
|
|
||||||
|
bool IsValidForwardSource() const
|
||||||
|
{
|
||||||
|
return forward_segment_id.enabled && is_valid_forward_source;
|
||||||
|
}
|
||||||
|
bool IsValidForwardTarget() const
|
||||||
|
{
|
||||||
|
return forward_segment_id.enabled && is_valid_forward_target;
|
||||||
|
}
|
||||||
|
bool IsValidReverseSource() const
|
||||||
|
{
|
||||||
|
return reverse_segment_id.enabled && is_valid_reverse_source;
|
||||||
|
}
|
||||||
|
bool IsValidReverseTarget() const
|
||||||
|
{
|
||||||
|
return reverse_segment_id.enabled && is_valid_reverse_target;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
||||||
|
|
||||||
template <class OtherT>
|
template <class OtherT>
|
||||||
@@ -146,6 +134,10 @@ struct PhantomNode
|
|||||||
EdgeWeight reverse_duration,
|
EdgeWeight reverse_duration,
|
||||||
EdgeWeight forward_duration_offset,
|
EdgeWeight forward_duration_offset,
|
||||||
EdgeWeight reverse_duration_offset,
|
EdgeWeight reverse_duration_offset,
|
||||||
|
bool is_valid_forward_source,
|
||||||
|
bool is_valid_forward_target,
|
||||||
|
bool is_valid_reverse_source,
|
||||||
|
bool is_valid_reverse_target,
|
||||||
const util::Coordinate location,
|
const util::Coordinate location,
|
||||||
const util::Coordinate input_location)
|
const util::Coordinate input_location)
|
||||||
: forward_segment_id{other.forward_segment_id},
|
: forward_segment_id{other.forward_segment_id},
|
||||||
@@ -159,7 +151,11 @@ struct PhantomNode
|
|||||||
component{other.component.id, other.component.is_tiny}, location{location},
|
component{other.component.id, other.component.is_tiny}, location{location},
|
||||||
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
||||||
forward_travel_mode{other.forward_travel_mode},
|
forward_travel_mode{other.forward_travel_mode},
|
||||||
backward_travel_mode{other.backward_travel_mode}
|
backward_travel_mode{other.backward_travel_mode},
|
||||||
|
is_valid_forward_source{is_valid_forward_source},
|
||||||
|
is_valid_forward_target{is_valid_forward_target},
|
||||||
|
is_valid_reverse_source{is_valid_reverse_source},
|
||||||
|
is_valid_reverse_target{is_valid_reverse_target}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,8 +183,14 @@ struct PhantomNode
|
|||||||
unsigned short fwd_segment_position;
|
unsigned short fwd_segment_position;
|
||||||
// note 4 bits would suffice for each,
|
// note 4 bits would suffice for each,
|
||||||
// but the saved byte would be padding anyway
|
// but the saved byte would be padding anyway
|
||||||
extractor::TravelMode forward_travel_mode;
|
extractor::TravelMode forward_travel_mode : 4;
|
||||||
extractor::TravelMode backward_travel_mode;
|
extractor::TravelMode backward_travel_mode : 4;
|
||||||
|
// is phantom node valid to be used as source or target
|
||||||
|
private:
|
||||||
|
bool is_valid_forward_source : 1;
|
||||||
|
bool is_valid_forward_target : 1;
|
||||||
|
bool is_valid_reverse_source : 1;
|
||||||
|
bool is_valid_reverse_target : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SearchEngineData<Algorithm> &heaps;
|
SearchEngineData<Algorithm> &heaps;
|
||||||
|
|
||||||
// Owned by shared-ptr passed to the query
|
// Owned by shared-ptr passed to the query
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade;
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,11 +21,15 @@ namespace routing_algorithms
|
|||||||
/// by the previous route.
|
/// by the previous route.
|
||||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||||
/// not fully contracted graphs.
|
/// not fully contracted graphs.
|
||||||
template <typename Algorithm>
|
InternalRouteResult directShortestPathSearch(
|
||||||
InternalRouteResult
|
SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
const PhantomNodes &phantom_nodes);
|
||||||
const PhantomNodes &phantom_nodes);
|
|
||||||
|
InternalRouteResult directShortestPathSearch(
|
||||||
|
SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||||
|
const PhantomNodes &phantom_nodes);
|
||||||
|
|
||||||
InternalRouteResult directShortestPathSearch(
|
InternalRouteResult directShortestPathSearch(
|
||||||
SearchEngineData<mld::Algorithm> &engine_working_data,
|
SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||||
|
|||||||
@@ -41,54 +41,44 @@ bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &targ
|
|||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
|
|
||||||
template <bool DIRECTION, typename Heap>
|
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node);
|
||||||
{
|
|
||||||
BOOST_ASSERT(phantom_node.IsValid());
|
|
||||||
|
|
||||||
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
|
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
if (phantom_node.forward_segment_id.enabled)
|
const PhantomNode &phantom_node);
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
phantom_node.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
if (phantom_node.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
phantom_node.reverse_segment_id.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool DIRECTION>
|
|
||||||
void insertNodesInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
|
||||||
const PhantomNode &phantom_node)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(phantom_node.IsValid());
|
|
||||||
|
|
||||||
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
|
|
||||||
if (phantom_node.forward_segment_id.enabled)
|
|
||||||
{
|
|
||||||
heap.Insert(
|
|
||||||
phantom_node.forward_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
{phantom_node.forward_segment_id.id, weight_sign * phantom_node.GetForwardDuration()});
|
|
||||||
}
|
|
||||||
if (phantom_node.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
heap.Insert(
|
|
||||||
phantom_node.reverse_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
{phantom_node.reverse_segment_id.id, weight_sign * phantom_node.GetReverseDuration()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Heap>
|
template <typename Heap>
|
||||||
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
||||||
{
|
{
|
||||||
insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
|
const auto &source = nodes.source_phantom;
|
||||||
insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
|
if (source.IsValidForwardSource())
|
||||||
|
{
|
||||||
|
forward_heap.Insert(source.forward_segment_id.id,
|
||||||
|
-source.GetForwardWeightPlusOffset(),
|
||||||
|
source.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.IsValidReverseSource())
|
||||||
|
{
|
||||||
|
forward_heap.Insert(source.reverse_segment_id.id,
|
||||||
|
-source.GetReverseWeightPlusOffset(),
|
||||||
|
source.reverse_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &target = nodes.target_phantom;
|
||||||
|
if (target.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
reverse_heap.Insert(target.forward_segment_id.id,
|
||||||
|
target.GetForwardWeightPlusOffset(),
|
||||||
|
target.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
reverse_heap.Insert(target.reverse_segment_id.id,
|
||||||
|
target.GetReverseWeightPlusOffset(),
|
||||||
|
target.reverse_segment_id.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FacadeT>
|
template <typename FacadeT>
|
||||||
|
|||||||
@@ -350,63 +350,29 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHe
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
std::int32_t &weight,
|
std::int32_t &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
|
const PhantomNodes &phantom_nodes,
|
||||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
|
|
||||||
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
|
||||||
EdgeWeight &weight,
|
|
||||||
std::vector<NodeID> &packed_leg,
|
|
||||||
const bool force_loop_forward,
|
|
||||||
const bool force_loop_reverse,
|
|
||||||
const PhantomNodes & /*phantom_nodes*/,
|
|
||||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
|
||||||
{
|
|
||||||
search(facade,
|
|
||||||
forward_heap,
|
|
||||||
reverse_heap,
|
|
||||||
weight,
|
|
||||||
packed_leg,
|
|
||||||
force_loop_forward,
|
|
||||||
force_loop_reverse,
|
|
||||||
duration_upper_bound);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double
|
double
|
||||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
|
|
||||||
inline double
|
|
||||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
|
||||||
const PhantomNode &source_phantom,
|
|
||||||
const PhantomNode &target_phantom,
|
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
|
||||||
{
|
|
||||||
return getNetworkDistance(
|
|
||||||
facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
|
|
||||||
}
|
|
||||||
} // namespace ch
|
} // namespace ch
|
||||||
|
|
||||||
namespace corech
|
namespace corech
|
||||||
@@ -420,11 +386,10 @@ namespace corech
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_core_heap,
|
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_core_heap,
|
|
||||||
int &weight,
|
int &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
@@ -436,11 +401,10 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorit
|
|||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double
|
double
|
||||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_core_heap,
|
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_core_heap,
|
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||||
|
|||||||
@@ -181,13 +181,20 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
|
|||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
|
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
|
||||||
search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
|
EdgeWeight weight_upper_bound,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
|
if (forward_heap.Empty() || reverse_heap.Empty())
|
||||||
|
{
|
||||||
|
return std::make_tuple(
|
||||||
|
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||||
|
}
|
||||||
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
|
|
||||||
@@ -196,7 +203,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|||||||
|
|
||||||
// run two-Target Dijkstra routing step.
|
// run two-Target Dijkstra routing step.
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = weight_upper_bound;
|
||||||
EdgeWeight forward_heap_min = forward_heap.MinKey();
|
EdgeWeight forward_heap_min = forward_heap.MinKey();
|
||||||
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
|
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
|
||||||
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
||||||
@@ -231,7 +238,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|||||||
};
|
};
|
||||||
|
|
||||||
// No path found for both target nodes?
|
// No path found for both target nodes?
|
||||||
if (weight == INVALID_EDGE_WEIGHT || SPECIAL_NODEID == middle)
|
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
|
||||||
{
|
{
|
||||||
return std::make_tuple(
|
return std::make_tuple(
|
||||||
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||||
@@ -292,11 +299,13 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|||||||
NodeID subpath_source, subpath_target;
|
NodeID subpath_source, subpath_target;
|
||||||
std::vector<EdgeID> subpath;
|
std::vector<EdgeID> subpath;
|
||||||
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
||||||
search(facade,
|
search(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
force_loop_forward,
|
force_loop_forward,
|
||||||
force_loop_reverse,
|
force_loop_reverse,
|
||||||
|
INVALID_EDGE_WEIGHT,
|
||||||
sublevel,
|
sublevel,
|
||||||
parent_cell_id);
|
parent_cell_id);
|
||||||
BOOST_ASSERT(!subpath.empty());
|
BOOST_ASSERT(!subpath.empty());
|
||||||
@@ -309,25 +318,29 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
|||||||
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
|
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO reorder parameters
|
||||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps for shortest path search
|
// Alias to be compatible with the overload for CoreCH that needs 4 heaps for shortest path search
|
||||||
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &,
|
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
const PhantomNodes &phantom_nodes,
|
const PhantomNodes &phantom_nodes,
|
||||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
(void)duration_upper_bound; // TODO: limiting search radius is not implemented for MLD
|
|
||||||
|
|
||||||
NodeID source_node, target_node;
|
NodeID source_node, target_node;
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(
|
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
||||||
facade, forward_heap, reverse_heap, force_loop_forward, force_loop_reverse, phantom_nodes);
|
facade,
|
||||||
|
forward_heap,
|
||||||
|
reverse_heap,
|
||||||
|
force_loop_forward,
|
||||||
|
force_loop_reverse,
|
||||||
|
weight_upper_bound,
|
||||||
|
phantom_nodes);
|
||||||
|
|
||||||
if (weight != INVALID_EDGE_WEIGHT)
|
if (weight != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
@@ -367,14 +380,13 @@ void unpackPath(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline double
|
inline double
|
||||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap & /*forward_core_heap*/,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap & /*reverse_core_heap*/,
|
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int /*duration_upper_bound*/)
|
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
@@ -382,14 +394,22 @@ getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorith
|
|||||||
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||||
|
|
||||||
EdgeWeight weight;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
NodeID source_node, target_node;
|
NodeID source_node, target_node;
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
std::tie(weight, source_node, target_node, unpacked_edges) = search(
|
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
|
||||||
facade, forward_heap, reverse_heap, DO_NOT_FORCE_LOOPS, DO_NOT_FORCE_LOOPS, phantom_nodes);
|
facade,
|
||||||
|
forward_heap,
|
||||||
|
reverse_heap,
|
||||||
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
weight_upper_bound,
|
||||||
|
phantom_nodes);
|
||||||
|
|
||||||
if (weight == INVALID_EDGE_WEIGHT)
|
if (weight == INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<PathData> unpacked_path;
|
std::vector<PathData> unpacked_path;
|
||||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ namespace osrm
|
|||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Algorithm-dependent heaps
|
||||||
|
// - CH algorithms use CH heaps
|
||||||
|
// - CoreCH algorithms use CoreCH heaps that can be upcasted to CH heaps when CH algorithms reused
|
||||||
|
// by CoreCH at calling ch::routingStep, ch::retrievePackedPathFromSingleHeap and ch::unpackPath
|
||||||
|
// - MLD algorithms use MLD heaps
|
||||||
|
|
||||||
|
template <typename Algorithm> struct SearchEngineData
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
struct HeapData
|
struct HeapData
|
||||||
{
|
{
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
@@ -24,7 +34,7 @@ struct ManyToManyHeapData : HeapData
|
|||||||
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
|
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Algorithm> struct SearchEngineData
|
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||||
{
|
{
|
||||||
using QueryHeap = util::
|
using QueryHeap = util::
|
||||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||||
@@ -55,6 +65,12 @@ template <typename Algorithm> struct SearchEngineData
|
|||||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct SearchEngineData<routing_algorithms::corech::Algorithm>
|
||||||
|
: public SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
struct MultiLayerDijkstraHeapData
|
struct MultiLayerDijkstraHeapData
|
||||||
{
|
{
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
@@ -75,12 +91,8 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
|||||||
|
|
||||||
static SearchEngineHeapPtr forward_heap_1;
|
static SearchEngineHeapPtr forward_heap_1;
|
||||||
static SearchEngineHeapPtr reverse_heap_1;
|
static SearchEngineHeapPtr reverse_heap_1;
|
||||||
static SearchEngineHeapPtr forward_heap_2;
|
|
||||||
static SearchEngineHeapPtr reverse_heap_2;
|
|
||||||
|
|
||||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
void InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,9 +159,6 @@ class EdgeBasedGraphFactory
|
|||||||
|
|
||||||
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
||||||
|
|
||||||
void FlushVectorToStream(storage::io::FileWriter &edge_data_file,
|
|
||||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
|
||||||
|
|
||||||
std::size_t restricted_turns_counter;
|
std::size_t restricted_turns_counter;
|
||||||
std::size_t skipped_uturns_counter;
|
std::size_t skipped_uturns_counter;
|
||||||
std::size_t skipped_barrier_turns_counter;
|
std::size_t skipped_barrier_turns_counter;
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ template <typename TurnDataT>
|
|||||||
inline void readTurnData(const boost::filesystem::path &path, TurnDataT &turn_data)
|
inline void readTurnData(const boost::filesystem::path &path, TurnDataT &turn_data)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
||||||
std::is_same<TurnDataView, TurnDataT>::value,
|
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||||
|
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||||
"");
|
"");
|
||||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::io::FileReader reader{path, fingerprint};
|
||||||
@@ -130,7 +131,8 @@ template <typename TurnDataT>
|
|||||||
inline void writeTurnData(const boost::filesystem::path &path, const TurnDataT &turn_data)
|
inline void writeTurnData(const boost::filesystem::path &path, const TurnDataT &turn_data)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
||||||
std::is_same<TurnDataView, TurnDataT>::value,
|
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||||
|
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||||
"");
|
"");
|
||||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::io::FileWriter writer{path, fingerprint};
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using TurnDataExternalContainer = detail::TurnDataContainerImpl<storage::Ownership::External>;
|
||||||
using TurnDataContainer = detail::TurnDataContainerImpl<storage::Ownership::Container>;
|
using TurnDataContainer = detail::TurnDataContainerImpl<storage::Ownership::Container>;
|
||||||
using TurnDataView = detail::TurnDataContainerImpl<storage::Ownership::View>;
|
using TurnDataView = detail::TurnDataContainerImpl<storage::Ownership::View>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "osrm/trip_parameters.hpp"
|
#include "osrm/trip_parameters.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/make_unique.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -81,7 +80,7 @@ inline void ParseResult(const osrm::Status &result_status, const std::string & /
|
|||||||
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
|
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
|
||||||
{
|
{
|
||||||
Nan::HandleScope scope;
|
Nan::HandleScope scope;
|
||||||
auto engine_config = boost::make_unique<osrm::EngineConfig>();
|
auto engine_config = std::make_unique<osrm::EngineConfig>();
|
||||||
|
|
||||||
if (args.Length() == 0)
|
if (args.Length() == 0)
|
||||||
{
|
{
|
||||||
@@ -631,7 +630,7 @@ inline route_parameters_ptr
|
|||||||
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
route_parameters_ptr params = boost::make_unique<osrm::RouteParameters>();
|
route_parameters_ptr params = std::make_unique<osrm::RouteParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return route_parameters_ptr();
|
return route_parameters_ptr();
|
||||||
@@ -681,7 +680,7 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
|||||||
inline tile_parameters_ptr
|
inline tile_parameters_ptr
|
||||||
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
|
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
|
||||||
{
|
{
|
||||||
tile_parameters_ptr params = boost::make_unique<osrm::TileParameters>();
|
tile_parameters_ptr params = std::make_unique<osrm::TileParameters>();
|
||||||
|
|
||||||
if (args.Length() < 2)
|
if (args.Length() < 2)
|
||||||
{
|
{
|
||||||
@@ -742,7 +741,7 @@ inline nearest_parameters_ptr
|
|||||||
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
nearest_parameters_ptr params = boost::make_unique<osrm::NearestParameters>();
|
nearest_parameters_ptr params = std::make_unique<osrm::NearestParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return nearest_parameters_ptr();
|
return nearest_parameters_ptr();
|
||||||
@@ -781,7 +780,7 @@ inline table_parameters_ptr
|
|||||||
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
table_parameters_ptr params = boost::make_unique<osrm::TableParameters>();
|
table_parameters_ptr params = std::make_unique<osrm::TableParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return table_parameters_ptr();
|
return table_parameters_ptr();
|
||||||
@@ -875,7 +874,7 @@ inline trip_parameters_ptr
|
|||||||
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
trip_parameters_ptr params = boost::make_unique<osrm::TripParameters>();
|
trip_parameters_ptr params = std::make_unique<osrm::TripParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return trip_parameters_ptr();
|
return trip_parameters_ptr();
|
||||||
@@ -970,7 +969,7 @@ inline match_parameters_ptr
|
|||||||
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
match_parameters_ptr params = boost::make_unique<osrm::MatchParameters>();
|
match_parameters_ptr params = std::make_unique<osrm::MatchParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return match_parameters_ptr();
|
return match_parameters_ptr();
|
||||||
|
|||||||
@@ -1,16 +1,39 @@
|
|||||||
#ifndef OSRM_STORAGE_SERIALIZATION_HPP
|
#ifndef OSRM_STORAGE_SERIALIZATION_HPP
|
||||||
#define OSRM_STORAGE_SERIALIZATION_HPP
|
#define OSRM_STORAGE_SERIALIZATION_HPP
|
||||||
|
|
||||||
|
#include "util/integer_range.hpp"
|
||||||
#include "util/vector_view.hpp"
|
#include "util/vector_view.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace storage
|
namespace storage
|
||||||
{
|
{
|
||||||
namespace serialization
|
namespace serialization
|
||||||
{
|
{
|
||||||
|
template <typename T> inline void read(storage::io::FileReader &reader, stxxl::vector<T> &vec)
|
||||||
|
{
|
||||||
|
auto size = reader.ReadOne<std::uint64_t>();
|
||||||
|
vec.reserve(size);
|
||||||
|
for (auto idx : util::irange<std::size_t>(0, size))
|
||||||
|
{
|
||||||
|
(void)idx;
|
||||||
|
vec.push_back(reader.ReadOne<T>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void write(storage::io::FileWriter &writer, const stxxl::vector<T> &vec)
|
||||||
|
{
|
||||||
|
writer.WriteOne(vec.size());
|
||||||
|
for (auto idx : util::irange<std::size_t>(0, vec.size()))
|
||||||
|
{
|
||||||
|
writer.WriteOne<T>(vec[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> void read(io::FileReader &reader, std::vector<T> &data)
|
template <typename T> void read(io::FileReader &reader, std::vector<T> &data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ namespace storage
|
|||||||
enum class Ownership
|
enum class Ownership
|
||||||
{
|
{
|
||||||
Container,
|
Container,
|
||||||
View
|
View,
|
||||||
|
External
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,12 @@
|
|||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/spin_mutex.h>
|
#include <tbb/spin_mutex.h>
|
||||||
|
|
||||||
#include <boost/interprocess/file_mapping.hpp>
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
#include <boost/interprocess/mapped_region.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
#include <boost/spirit/include/phoenix.hpp>
|
#include <boost/spirit/include/phoenix.hpp>
|
||||||
#include <boost/spirit/include/qi.hpp>
|
#include <boost/spirit/include/qi.hpp>
|
||||||
#include <boost/spirit/include/support_line_pos_iterator.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -24,20 +23,15 @@ namespace osrm
|
|||||||
namespace updater
|
namespace updater
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
namespace qi = boost::spirit::qi;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functor to parse a list of CSV files using "key,value,comment" grammar.
|
// Functor to parse a list of CSV files using "key,value,comment" grammar.
|
||||||
// Key and Value structures must be a model of Random Access Sequence.
|
// Key and Value structures must be a model of Random Access Sequence.
|
||||||
// Also the Value structure must have source member that will be filled
|
// Also the Value structure must have source member that will be filled
|
||||||
// with the corresponding file index in the CSV filenames vector.
|
// with the corresponding file index in the CSV filenames vector.
|
||||||
template <typename Key, typename Value> struct CSVFilesParser
|
template <typename Key, typename Value> struct CSVFilesParser
|
||||||
{
|
{
|
||||||
using Iterator = boost::spirit::line_pos_iterator<boost::spirit::istream_iterator>;
|
using Iterator = boost::iostreams::mapped_file_source::iterator;
|
||||||
using KeyRule = qi::rule<Iterator, Key()>;
|
using KeyRule = boost::spirit::qi::rule<Iterator, Key()>;
|
||||||
using ValueRule = qi::rule<Iterator, Value()>;
|
using ValueRule = boost::spirit::qi::rule<Iterator, Value()>;
|
||||||
|
|
||||||
CSVFilesParser(std::size_t start_index, const KeyRule &key_rule, const ValueRule &value_rule)
|
CSVFilesParser(std::size_t start_index, const KeyRule &key_rule, const ValueRule &value_rule)
|
||||||
: start_index(start_index), key_rule(key_rule), value_rule(value_rule)
|
: start_index(start_index), key_rule(key_rule), value_rule(value_rule)
|
||||||
@@ -95,30 +89,46 @@ template <typename Key, typename Value> struct CSVFilesParser
|
|||||||
// Parse a single CSV file and return result as a vector<Key, Value>
|
// Parse a single CSV file and return result as a vector<Key, Value>
|
||||||
auto ParseCSVFile(const std::string &filename, std::size_t file_id) const
|
auto ParseCSVFile(const std::string &filename, std::size_t file_id) const
|
||||||
{
|
{
|
||||||
std::ifstream input_stream(filename, std::ios::binary);
|
namespace qi = boost::spirit::qi;
|
||||||
input_stream.unsetf(std::ios::skipws);
|
|
||||||
|
|
||||||
boost::spirit::istream_iterator sfirst(input_stream), slast;
|
|
||||||
Iterator first(sfirst), last(slast);
|
|
||||||
|
|
||||||
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
|
|
||||||
ValueRule value_source =
|
|
||||||
value_rule[qi::_val = qi::_1, boost::phoenix::bind(&Value::source, qi::_val) = file_id];
|
|
||||||
qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
|
|
||||||
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
|
|
||||||
std::vector<std::pair<Key, Value>> result;
|
std::vector<std::pair<Key, Value>> result;
|
||||||
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
|
try
|
||||||
|
|
||||||
if (!ok || first != last)
|
|
||||||
{
|
{
|
||||||
const auto message =
|
if (boost::filesystem::file_size(filename) == 0)
|
||||||
boost::format("CSV file %1% malformed on line %2%") % filename % first.position();
|
return result;
|
||||||
|
|
||||||
|
boost::iostreams::mapped_file_source mmap(filename);
|
||||||
|
auto first = mmap.begin(), last = mmap.end();
|
||||||
|
|
||||||
|
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
|
||||||
|
ValueRule value_source =
|
||||||
|
value_rule[qi::_val = qi::_1, bind(&Value::source, qi::_val) = file_id];
|
||||||
|
qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
|
||||||
|
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
|
||||||
|
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
|
||||||
|
|
||||||
|
if (!ok || first != last)
|
||||||
|
{
|
||||||
|
auto begin_of_line = first - 1;
|
||||||
|
while (begin_of_line >= mmap.begin() && *begin_of_line != '\n')
|
||||||
|
--begin_of_line;
|
||||||
|
auto line_number = std::count(mmap.begin(), first, '\n') + 1;
|
||||||
|
const auto message = boost::format("CSV file %1% malformed on line %2%:\n %3%\n") %
|
||||||
|
filename % std::to_string(line_number) %
|
||||||
|
std::string(begin_of_line + 1, std::find(first, last, '\n'));
|
||||||
|
throw util::exception(message.str() + SOURCE_REF);
|
||||||
|
}
|
||||||
|
|
||||||
|
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
catch (const boost::exception &e)
|
||||||
|
{
|
||||||
|
const auto message = boost::format("exception in loading %1%:\n %2%") % filename %
|
||||||
|
boost::diagnostic_information(e);
|
||||||
throw util::exception(message.str() + SOURCE_REF);
|
throw util::exception(message.str() + SOURCE_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
|
|
||||||
|
|
||||||
return std::move(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t start_index;
|
const std::size_t start_index;
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ struct Segment final
|
|||||||
|
|
||||||
struct SpeedSource final
|
struct SpeedSource final
|
||||||
{
|
{
|
||||||
SpeedSource() : speed(0), weight(std::numeric_limits<double>::quiet_NaN()) {}
|
SpeedSource() : speed(0), rate(std::numeric_limits<double>::quiet_NaN()) {}
|
||||||
unsigned speed;
|
unsigned speed;
|
||||||
double weight;
|
double rate;
|
||||||
std::uint8_t source;
|
std::uint8_t source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,9 @@
|
|||||||
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
(void)cond; \
|
(void)(cond); \
|
||||||
(void)coordinate; \
|
(void)(coordinate); \
|
||||||
(void)msg; \
|
(void)(msg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "storage/shared_memory_ownership.hpp"
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
|
||||||
|
#include <stxxl/vector>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/iterator/iterator_facade.hpp>
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
#include <boost/iterator/reverse_iterator.hpp>
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
@@ -174,10 +176,16 @@ template <typename DataT> void swap(vector_view<DataT> &lhs, vector_view<DataT>
|
|||||||
std::swap(lhs.m_size, rhs.m_size);
|
std::swap(lhs.m_size, rhs.m_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename DataT, storage::Ownership Ownership>
|
||||||
|
using InternalOrExternalVector =
|
||||||
|
typename std::conditional<Ownership == storage::Ownership::External,
|
||||||
|
stxxl::vector<DataT>,
|
||||||
|
std::vector<DataT>>::type;
|
||||||
|
|
||||||
template <typename DataT, storage::Ownership Ownership>
|
template <typename DataT, storage::Ownership Ownership>
|
||||||
using ViewOrVector = typename std::conditional<Ownership == storage::Ownership::View,
|
using ViewOrVector = typename std::conditional<Ownership == storage::Ownership::View,
|
||||||
vector_view<DataT>,
|
vector_view<DataT>,
|
||||||
std::vector<DataT>>::type;
|
InternalOrExternalVector<DataT, Ownership>>::type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.7.0-latest.6",
|
"version": "5.7.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
|
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
|
||||||
"clean": "rm -rf test/cache",
|
"clean": "rm -rf test/cache",
|
||||||
"docs": "./scripts/build_api_docs.sh",
|
"docs": "./scripts/build_api_docs.sh",
|
||||||
"install": "node-pre-gyp install --fallback-to-build=false",
|
"install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh",
|
||||||
"nodejs-tests": "make -C test/data && ./lib/binding/osrm-datastore test/data/ch/monaco.osrm && node test/nodejs/index.js | faucet"
|
"nodejs-tests": "make -C test/data && ./lib/binding/osrm-datastore test/data/ch/monaco.osrm && node test/nodejs/index.js | faucet"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
+27
-22
@@ -101,6 +101,10 @@ local profile = {
|
|||||||
'tertiary_link'
|
'tertiary_link'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
service_penalties = {
|
||||||
|
alley = 0.5,
|
||||||
|
},
|
||||||
|
|
||||||
bicycle_speeds = {
|
bicycle_speeds = {
|
||||||
cycleway = default_speed,
|
cycleway = default_speed,
|
||||||
primary = default_speed,
|
primary = default_speed,
|
||||||
@@ -480,29 +484,29 @@ function way_function (way, result)
|
|||||||
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
|
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
|
||||||
|
|
||||||
-- convert duration into cyclability
|
-- convert duration into cyclability
|
||||||
local is_unsafe = profile.safety_penalty < 1 and profile.unsafe_highway_list[data.highway]
|
if properties.weight_name == 'cyclability' then
|
||||||
if result.forward_speed > 0 then
|
local is_unsafe = profile.safety_penalty < 1 and profile.unsafe_highway_list[data.highway]
|
||||||
-- convert from km/h to m/s
|
local is_undesireable = data.highway == "service" and profile.service_penalties[service]
|
||||||
result.forward_rate = result.forward_speed / 3.6;
|
local penalty = 1.0
|
||||||
if is_unsafe then
|
if is_unsafe then
|
||||||
result.forward_rate = result.forward_rate * profile.safety_penalty
|
penalty = math.min(penalty, profile.safety_penalty)
|
||||||
end
|
end
|
||||||
end
|
if is_undesireable then
|
||||||
if result.backward_speed > 0 then
|
penalty = math.min(penalty, profile.service_penalties[service])
|
||||||
-- convert from km/h to m/s
|
end
|
||||||
result.backward_rate = result.backward_speed / 3.6;
|
|
||||||
if is_unsafe then
|
|
||||||
result.backward_rate = result.backward_rate * profile.safety_penalty
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if result.duration > 0 then
|
|
||||||
result.weight = result.duration;
|
|
||||||
if is_unsafe then
|
|
||||||
result.weight = result.weight * (1+profile.safety_penalty)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
if result.forward_speed > 0 then
|
||||||
|
-- convert from km/h to m/s
|
||||||
|
result.forward_rate = result.forward_speed / 3.6 * penalty
|
||||||
|
end
|
||||||
|
if result.backward_speed > 0 then
|
||||||
|
-- convert from km/h to m/s
|
||||||
|
result.backward_rate = result.backward_speed / 3.6 * penalty
|
||||||
|
end
|
||||||
|
if result.duration > 0 then
|
||||||
|
result.weight = result.duration / penalty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local handlers = Sequence {
|
local handlers = Sequence {
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
@@ -540,6 +544,7 @@ function turn_function(turn)
|
|||||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
turn.duration = turn.duration + profile.traffic_light_penalty
|
||||||
end
|
end
|
||||||
if properties.weight_name == 'cyclability' then
|
if properties.weight_name == 'cyclability' then
|
||||||
|
turn.weight = turn.duration
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = turn.weight + 3000
|
turn.weight = turn.weight + 3000
|
||||||
|
|||||||
+7
-10
@@ -34,9 +34,6 @@ local profile = {
|
|||||||
speed_reduction = 0.8,
|
speed_reduction = 0.8,
|
||||||
traffic_light_penalty = 2,
|
traffic_light_penalty = 2,
|
||||||
u_turn_penalty = 20,
|
u_turn_penalty = 20,
|
||||||
restricted_penalty = 3000,
|
|
||||||
-- Note^: abstract value but in seconds correlates approximately to 50 min
|
|
||||||
-- meaning that a route through a local access way is > 50 min faster than around
|
|
||||||
|
|
||||||
-- Note: this biases right-side driving.
|
-- Note: this biases right-side driving.
|
||||||
-- Should be inverted for left-driving countries.
|
-- Should be inverted for left-driving countries.
|
||||||
@@ -392,21 +389,21 @@ function turn_function (turn)
|
|||||||
local turn_penalty = profile.turn_penalty
|
local turn_penalty = profile.turn_penalty
|
||||||
local turn_bias = profile.turn_bias
|
local turn_bias = profile.turn_bias
|
||||||
|
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = profile.traffic_light_penalty
|
||||||
|
end
|
||||||
|
|
||||||
if turn.turn_type ~= turn_type.no_turn then
|
if turn.turn_type ~= turn_type.no_turn then
|
||||||
if turn.angle >= 0 then
|
if turn.angle >= 0 then
|
||||||
turn.duration = turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
||||||
else
|
else
|
||||||
turn.duration = turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.direction_modifier == direction_modifier.u_turn then
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
turn.duration = turn.duration + profile.u_turn_penalty
|
turn.duration = turn.duration + profile.u_turn_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
|
||||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
|
||||||
end
|
|
||||||
|
|
||||||
-- for distance based routing we don't want to have penalties based on turn angle
|
-- for distance based routing we don't want to have penalties based on turn angle
|
||||||
if properties.weight_name == 'distance' then
|
if properties.weight_name == 'distance' then
|
||||||
turn.weight = 0
|
turn.weight = 0
|
||||||
@@ -417,7 +414,7 @@ function turn_function (turn)
|
|||||||
if properties.weight_name == 'routability' then
|
if properties.weight_name == 'routability' then
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = turn.weight + profile.restricted_penalty
|
turn.weight = properties.max_turn_weight;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ end
|
|||||||
|
|
||||||
function Handlers.handle_weights(way,result,data,profile)
|
function Handlers.handle_weights(way,result,data,profile)
|
||||||
if properties.weight_name == 'distance' then
|
if properties.weight_name == 'distance' then
|
||||||
result.weight = 0
|
result.weight = -1
|
||||||
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
||||||
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
||||||
result.forward_rate = 1
|
result.forward_rate = 1
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ babel -V >/dev/null 2>&1 || { echo >&2 "Can't find babel. Add node_modules/.bin
|
|||||||
browserify --help >/dev/null 2>&1 || { echo >&2 "Can't find browserify. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
browserify --help >/dev/null 2>&1 || { echo >&2 "Can't find browserify. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
||||||
uglifyjs -V >/dev/null 2>&1 || { echo >&2 "Can't find uglifyjs. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
uglifyjs -V >/dev/null 2>&1 || { echo >&2 "Can't find uglifyjs. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
||||||
|
|
||||||
#documentation build src/nodejs/node_osrm.cpp --polyglot -f md -o docs/nodejs/api.md
|
documentation build src/nodejs/node_osrm.cpp --polyglot --markdown-toc=false -f md -o docs/nodejs/api.md
|
||||||
|
|
||||||
# Clean up previous version
|
# Clean up previous version
|
||||||
rm -rf build/docs
|
rm -rf build/docs
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
NODE_HOME=$HOME/node
|
|
||||||
export NODE_HOME
|
|
||||||
mkdir ${NODE_HOME}
|
|
||||||
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
|
|
||||||
curl https://s3.amazonaws.com/mapbox/apps/install-node/v2.0.0/run | NV=4.4.2 NP=darwin-x64 OD=${NODE_HOME} sh
|
|
||||||
else
|
|
||||||
curl https://s3.amazonaws.com/mapbox/apps/install-node/v2.0.0/run | NV=4.4.2 NP=linux-x64 OD=${NODE_HOME} sh
|
|
||||||
fi
|
|
||||||
|
|
||||||
PATH="${NODE_HOME}/bin:$PATH"
|
|
||||||
export PATH
|
|
||||||
node --version
|
|
||||||
npm --version
|
|
||||||
which node
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CMAKE_OPTIONS=${CMAKE_OPTIONS:-"-DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On"}
|
||||||
|
|
||||||
|
if [[ ! -f $(which cmake) ]]; then
|
||||||
|
echo "Needs cmake to build from source"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -d build ]]; then
|
||||||
|
echo "Detected existing build directory, skipping compiling."
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
mkdir -p build
|
||||||
|
pushd build
|
||||||
|
cmake .. $CMAKE_OPTIONS
|
||||||
|
cmake --build .
|
||||||
|
popd
|
||||||
|
fi
|
||||||
Executable
+16
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var exec = require('child_process').exec;
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var name = process.argv[2];
|
||||||
|
var cmd = process.argv.slice(3).join(' ');
|
||||||
|
var start = Date.now();
|
||||||
|
exec(cmd, (err) => {
|
||||||
|
if (err) return console.log(err);
|
||||||
|
var stop = +new Date();
|
||||||
|
var time = (stop - start) / 1000.;
|
||||||
|
fs.appendFileSync('/tmp/osrm.timings', `${name}\t${time}`, 'utf-8');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
TIMINGS_FILE=/tmp/osrm.timings
|
|
||||||
NAME=$1
|
|
||||||
CMD=${@:2}
|
|
||||||
START=$(date "+%s.%N")
|
|
||||||
/bin/bash -c "$CMD"
|
|
||||||
END=$(date "+%s.%N")
|
|
||||||
TIME="$(echo "$END - $START" | bc)s"
|
|
||||||
NEW_ENTRY="$NAME\t$TIME"
|
|
||||||
|
|
||||||
echo -e "$NEW_ENTRY" >> $TIMINGS_FILE
|
|
||||||
@@ -3,15 +3,19 @@
|
|||||||
set -eu
|
set -eu
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
|
echo "node version is:"
|
||||||
|
which node
|
||||||
|
node -v
|
||||||
|
|
||||||
if [[ ${PUBLISH} == 'On' ]]; then
|
if [[ ${PUBLISH} == 'On' ]]; then
|
||||||
echo "PUBLISH is set to '${PUBLISH}', publishing!"
|
echo "PUBLISH is set to '${PUBLISH}', publishing!"
|
||||||
|
NPM_FLAGS=''
|
||||||
echo "node version is:"
|
if [[ ${BUILD_TYPE} == "Debug" ]]; then
|
||||||
which node
|
NPM_FLAGS='--debug'
|
||||||
node -v
|
fi
|
||||||
|
|
||||||
echo "dumping binary meta..."
|
echo "dumping binary meta..."
|
||||||
./node_modules/.bin/node-pre-gyp reveal
|
./node_modules/.bin/node-pre-gyp reveal $NPM_FLAGS
|
||||||
|
|
||||||
# enforce that binary has proper ORIGIN flags so that
|
# enforce that binary has proper ORIGIN flags so that
|
||||||
# it can portably find libtbb.so in the same directory
|
# it can portably find libtbb.so in the same directory
|
||||||
@@ -27,7 +31,7 @@ if [[ ${PUBLISH} == 'On' ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
./node_modules/.bin/node-pre-gyp package publish info
|
./node_modules/.bin/node-pre-gyp package publish info $NPM_FLAGS
|
||||||
else
|
else
|
||||||
echo "PUBLISH is set to '${PUBLISH}', skipping."
|
echo "PUBLISH is set to '${PUBLISH}', skipping."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -74,9 +74,6 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
|
|||||||
if (entry_step.distance < MAX_COLLAPSE_DISTANCE)
|
if (entry_step.distance < MAX_COLLAPSE_DISTANCE)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (entry_step.distance > 2 * MAX_COLLAPSE_DISTANCE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// both go roughly in the same direction
|
// both go roughly in the same direction
|
||||||
if ((entry_angle <= 185 && exit_angle <= 185) || (entry_angle >= 175 && exit_angle >= 175))
|
if ((entry_angle <= 185 && exit_angle <= 185) || (entry_angle >= 175 && exit_angle >= 175))
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -118,12 +118,14 @@ bool setUpRoundabout(RouteStep &step)
|
|||||||
|
|
||||||
void closeOffRoundabout(const bool on_roundabout,
|
void closeOffRoundabout(const bool on_roundabout,
|
||||||
std::vector<RouteStep> &steps,
|
std::vector<RouteStep> &steps,
|
||||||
const std::size_t step_index)
|
std::size_t step_index)
|
||||||
{
|
{
|
||||||
auto &step = steps[step_index];
|
auto &step = steps[step_index];
|
||||||
step.maneuver.exit += 1;
|
step.maneuver.exit += 1;
|
||||||
if (!on_roundabout)
|
if (!on_roundabout)
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(steps.size() >= 2);
|
||||||
|
|
||||||
// We reached a special case that requires the addition of a special route step in the
|
// We reached a special case that requires the addition of a special route step in the
|
||||||
// beginning. We started in a roundabout, so to announce the exit, we move use the exit
|
// beginning. We started in a roundabout, so to announce the exit, we move use the exit
|
||||||
// instruction and move it right to the beginning to make sure to immediately announce the
|
// instruction and move it right to the beginning to make sure to immediately announce the
|
||||||
@@ -160,6 +162,23 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (step_index > 1)
|
||||||
|
{
|
||||||
|
auto &exit_step = steps[step_index];
|
||||||
|
auto &prev_step = steps[step_index - 1];
|
||||||
|
// In case the step with the roundabout exit instruction cannot be merged with the
|
||||||
|
// previous step we change the instruction to a normal turn
|
||||||
|
if (!guidance::haveSameMode(exit_step, prev_step))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(leavesRoundabout(exit_step.maneuver.instruction));
|
||||||
|
prev_step.maneuver.instruction = exit_step.maneuver.instruction;
|
||||||
|
if (!entersRoundabout(prev_step.maneuver.instruction))
|
||||||
|
prev_step.maneuver.exit = exit_step.maneuver.exit;
|
||||||
|
exit_step.maneuver.instruction.type = TurnType::Notification;
|
||||||
|
step_index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Normal exit from the roundabout, or exit from a previously fixed roundabout. Propagate the
|
// Normal exit from the roundabout, or exit from a previously fixed roundabout. Propagate the
|
||||||
// index back to the entering location and prepare the current silent set of instructions for
|
// index back to the entering location and prepare the current silent set of instructions for
|
||||||
// removal.
|
// removal.
|
||||||
@@ -170,6 +189,7 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
const auto exit_intersection = steps[step_index].intersections.front();
|
const auto exit_intersection = steps[step_index].intersections.front();
|
||||||
const auto exit_bearing = exit_intersection.bearings[exit_intersection.out];
|
const auto exit_bearing = exit_intersection.bearings[exit_intersection.out];
|
||||||
const auto destination_copy = step;
|
const auto destination_copy = step;
|
||||||
|
|
||||||
if (step_index > 1)
|
if (step_index > 1)
|
||||||
{
|
{
|
||||||
// The very first route-step is head, so we cannot iterate past that one
|
// The very first route-step is head, so we cannot iterate past that one
|
||||||
@@ -177,8 +197,11 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
--propagation_index)
|
--propagation_index)
|
||||||
{
|
{
|
||||||
auto &propagation_step = steps[propagation_index];
|
auto &propagation_step = steps[propagation_index];
|
||||||
propagation_step.ElongateBy(steps[propagation_index + 1]);
|
auto &next_step = steps[propagation_index + 1];
|
||||||
propagation_step.maneuver.exit = steps[propagation_index + 1].maneuver.exit;
|
propagation_step.ElongateBy(next_step);
|
||||||
|
propagation_step.maneuver.exit = next_step.maneuver.exit;
|
||||||
|
next_step.Invalidate();
|
||||||
|
|
||||||
if (entersRoundabout(propagation_step.maneuver.instruction))
|
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||||
{
|
{
|
||||||
const auto entry_intersection = propagation_step.intersections.front();
|
const auto entry_intersection = propagation_step.intersections.front();
|
||||||
@@ -206,13 +229,8 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
}
|
}
|
||||||
|
|
||||||
propagation_step.AdaptStepSignage(destination_copy);
|
propagation_step.AdaptStepSignage(destination_copy);
|
||||||
steps[propagation_index + 1].Invalidate();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
steps[propagation_index + 1].Invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// remove exit
|
// remove exit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,17 @@ Status TablePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
|||||||
return Error("TooBig", "Too many table coordinates", result);
|
return Error("TooBig", "Too many table coordinates", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto snapped_phantoms = SnapPhantomNodes(GetPhantomNodes(facade, params));
|
auto phantom_nodes = GetPhantomNodes(facade, params);
|
||||||
|
|
||||||
|
if (phantom_nodes.size() != params.coordinates.size())
|
||||||
|
{
|
||||||
|
return Error("NoSegment",
|
||||||
|
std::string("Could not find a matching segment for coordinate ") +
|
||||||
|
std::to_string(phantom_nodes.size()),
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto snapped_phantoms = SnapPhantomNodes(phantom_nodes);
|
||||||
auto result_table =
|
auto result_table =
|
||||||
algorithms.ManyToManySearch(snapped_phantoms, params.sources, params.destinations);
|
algorithms.ManyToManySearch(snapped_phantoms, params.sources, params.destinations);
|
||||||
|
|
||||||
|
|||||||
@@ -77,27 +77,10 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca
|
|||||||
|
|
||||||
auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);
|
auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);
|
||||||
|
|
||||||
const bool continue_straight_at_waypoint = route_parameters.continue_straight
|
|
||||||
? *route_parameters.continue_straight
|
|
||||||
: facade.GetContinueStraightDefault();
|
|
||||||
|
|
||||||
std::vector<PhantomNodes> start_end_nodes;
|
std::vector<PhantomNodes> start_end_nodes;
|
||||||
auto build_phantom_pairs = [&start_end_nodes, continue_straight_at_waypoint](
|
auto build_phantom_pairs = [&start_end_nodes](const PhantomNode &first_node,
|
||||||
const PhantomNode &first_node, const PhantomNode &second_node) {
|
const PhantomNode &second_node) {
|
||||||
start_end_nodes.push_back(PhantomNodes{first_node, second_node});
|
start_end_nodes.push_back(PhantomNodes{first_node, second_node});
|
||||||
auto &last_inserted = start_end_nodes.back();
|
|
||||||
// enable forward direction if possible
|
|
||||||
if (last_inserted.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID)
|
|
||||||
{
|
|
||||||
last_inserted.source_phantom.forward_segment_id.enabled |=
|
|
||||||
!continue_straight_at_waypoint;
|
|
||||||
}
|
|
||||||
// enable reverse direction if possible
|
|
||||||
if (last_inserted.source_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
|
||||||
{
|
|
||||||
last_inserted.source_phantom.reverse_segment_id.enabled |=
|
|
||||||
!continue_straight_at_waypoint;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
util::for_each_pair(snapped_phantoms, build_phantom_pairs);
|
util::for_each_pair(snapped_phantoms, build_phantom_pairs);
|
||||||
|
|
||||||
|
|||||||
@@ -62,25 +62,19 @@ InternalRouteResult directShortestPathSearchImpl(
|
|||||||
const PhantomNodes &phantom_nodes)
|
const PhantomNodes &phantom_nodes)
|
||||||
{
|
{
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
|
||||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||||
auto &forward_core_heap = *engine_working_data.forward_heap_2;
|
|
||||||
auto &reverse_core_heap = *engine_working_data.reverse_heap_2;
|
|
||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
forward_core_heap.Clear();
|
|
||||||
reverse_core_heap.Clear();
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_leg;
|
std::vector<NodeID> packed_leg;
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||||
|
|
||||||
search(facade,
|
search(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
weight,
|
weight,
|
||||||
packed_leg,
|
packed_leg,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
@@ -107,7 +101,6 @@ InternalRouteResult directShortestPathSearchImpl(
|
|||||||
|
|
||||||
} // namespace ch
|
} // namespace ch
|
||||||
|
|
||||||
template <>
|
|
||||||
InternalRouteResult directShortestPathSearch(
|
InternalRouteResult directShortestPathSearch(
|
||||||
SearchEngineData<corech::Algorithm> &engine_working_data,
|
SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||||
@@ -116,7 +109,6 @@ InternalRouteResult directShortestPathSearch(
|
|||||||
return detail::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
|
return detail::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
InternalRouteResult directShortestPathSearch(
|
InternalRouteResult directShortestPathSearch(
|
||||||
SearchEngineData<ch::Algorithm> &engine_working_data,
|
SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||||
@@ -137,11 +129,17 @@ InternalRouteResult directShortestPathSearch(
|
|||||||
|
|
||||||
// TODO: when structured bindings will be allowed change to
|
// TODO: when structured bindings will be allowed change to
|
||||||
// auto [weight, source_node, target_node, unpacked_edges] = ...
|
// auto [weight, source_node, target_node, unpacked_edges] = ...
|
||||||
EdgeWeight weight;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
NodeID source_node, target_node;
|
NodeID source_node, target_node;
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(
|
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
||||||
facade, forward_heap, reverse_heap, DO_NOT_FORCE_LOOPS, DO_NOT_FORCE_LOOPS, phantom_nodes);
|
facade,
|
||||||
|
forward_heap,
|
||||||
|
reverse_heap,
|
||||||
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
INVALID_EDGE_WEIGHT,
|
||||||
|
phantom_nodes);
|
||||||
|
|
||||||
return extractRoute(facade, weight, source_node, target_node, unpacked_edges, phantom_nodes);
|
return extractRoute(facade, weight, source_node, target_node, unpacked_edges, phantom_nodes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto search_target_phantom = [&](const PhantomNode &phantom) {
|
const auto search_target_phantom = [&](const PhantomNode &phantom) {
|
||||||
// clear heap and insert target nodes
|
// clear heap and insert target nodes
|
||||||
query_heap.Clear();
|
query_heap.Clear();
|
||||||
insertNodesInHeap<REVERSE_DIRECTION>(query_heap, phantom);
|
insertTargetInHeap(query_heap, phantom);
|
||||||
|
|
||||||
// explore search space
|
// explore search space
|
||||||
while (!query_heap.Empty())
|
while (!query_heap.Empty())
|
||||||
@@ -191,7 +191,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto search_source_phantom = [&](const PhantomNode &phantom) {
|
const auto search_source_phantom = [&](const PhantomNode &phantom) {
|
||||||
// clear heap and insert source nodes
|
// clear heap and insert source nodes
|
||||||
query_heap.Clear();
|
query_heap.Clear();
|
||||||
insertNodesInHeap<FORWARD_DIRECTION>(query_heap, phantom);
|
insertSourceInHeap(query_heap, phantom);
|
||||||
|
|
||||||
// explore search space
|
// explore search space
|
||||||
while (!query_heap.Empty())
|
while (!query_heap.Empty())
|
||||||
|
|||||||
@@ -143,12 +143,9 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
const auto nodes_number = facade.GetNumberOfNodes();
|
const auto nodes_number = facade.GetNumberOfNodes();
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number);
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number);
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(nodes_number);
|
|
||||||
|
|
||||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||||
auto &forward_core_heap = *engine_working_data.forward_heap_2;
|
|
||||||
auto &reverse_core_heap = *engine_working_data.reverse_heap_2;
|
|
||||||
|
|
||||||
std::size_t breakage_begin = map_matching::INVALID_STATE;
|
std::size_t breakage_begin = map_matching::INVALID_STATE;
|
||||||
std::vector<std::size_t> split_points;
|
std::vector<std::size_t> split_points;
|
||||||
@@ -198,9 +195,9 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
const auto haversine_distance = util::coordinate_calculation::haversineDistance(
|
const auto haversine_distance = util::coordinate_calculation::haversineDistance(
|
||||||
prev_coordinate, current_coordinate);
|
prev_coordinate, current_coordinate);
|
||||||
// assumes minumum of 0.1 m/s
|
// assumes minumum of 4 m/s
|
||||||
const int duration_upper_bound =
|
const EdgeWeight weight_upper_bound =
|
||||||
((haversine_distance + max_distance_delta) * 0.25) * 10;
|
((haversine_distance + max_distance_delta) / 4.) * facade.GetWeightMultiplier();
|
||||||
|
|
||||||
// compute d_t for this timestamp and the next one
|
// compute d_t for this timestamp and the next one
|
||||||
for (const auto s : util::irange<std::size_t>(0UL, prev_viterbi.size()))
|
for (const auto s : util::irange<std::size_t>(0UL, prev_viterbi.size()))
|
||||||
@@ -220,14 +217,13 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
double network_distance =
|
double network_distance =
|
||||||
getNetworkDistance(facade,
|
getNetworkDistance(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
prev_unbroken_timestamps_list[s].phantom_node,
|
prev_unbroken_timestamps_list[s].phantom_node,
|
||||||
current_timestamps_list[s_prime].phantom_node,
|
current_timestamps_list[s_prime].phantom_node,
|
||||||
duration_upper_bound);
|
weight_upper_bound);
|
||||||
|
|
||||||
// get distance diff between loc1/2 and locs/s_prime
|
// get distance diff between loc1/2 and locs/s_prime
|
||||||
const auto d_t = std::abs(network_distance - haversine_distance);
|
const auto d_t = std::abs(network_distance - haversine_distance);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace routing_algorithms
|
|||||||
|
|
||||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
{
|
{
|
||||||
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
return source_phantom.IsValidForwardSource() && target_phantom.IsValidForwardTarget() &&
|
||||||
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
||||||
source_phantom.GetForwardWeightPlusOffset() >
|
source_phantom.GetForwardWeightPlusOffset() >
|
||||||
target_phantom.GetForwardWeightPlusOffset();
|
target_phantom.GetForwardWeightPlusOffset();
|
||||||
@@ -17,12 +17,46 @@ bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &targ
|
|||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
{
|
{
|
||||||
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
return source_phantom.IsValidReverseSource() && target_phantom.IsValidReverseTarget() &&
|
||||||
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
||||||
source_phantom.GetReverseWeightPlusOffset() >
|
source_phantom.GetReverseWeightPlusOffset() >
|
||||||
target_phantom.GetReverseWeightPlusOffset();
|
target_phantom.GetReverseWeightPlusOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -71,15 +71,23 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHe
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
|
const PhantomNodes & /*phantom_nodes*/,
|
||||||
const EdgeWeight weight_upper_bound)
|
const EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
|
if (forward_heap.Empty() || reverse_heap.Empty())
|
||||||
|
{
|
||||||
|
weight = INVALID_EDGE_WEIGHT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
weight = weight_upper_bound;
|
weight = weight_upper_bound;
|
||||||
|
|
||||||
@@ -142,7 +150,8 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
@@ -152,41 +161,19 @@ double getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<A
|
|||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
|
|
||||||
if (source_phantom.forward_segment_id.enabled)
|
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
|
||||||
{
|
|
||||||
forward_heap.Insert(source_phantom.forward_segment_id.id,
|
|
||||||
-source_phantom.GetForwardWeightPlusOffset(),
|
|
||||||
source_phantom.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
if (source_phantom.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
forward_heap.Insert(source_phantom.reverse_segment_id.id,
|
|
||||||
-source_phantom.GetReverseWeightPlusOffset(),
|
|
||||||
source_phantom.reverse_segment_id.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target_phantom.forward_segment_id.enabled)
|
|
||||||
{
|
|
||||||
reverse_heap.Insert(target_phantom.forward_segment_id.id,
|
|
||||||
target_phantom.GetForwardWeightPlusOffset(),
|
|
||||||
target_phantom.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
if (target_phantom.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
|
|
||||||
target_phantom.GetReverseWeightPlusOffset(),
|
|
||||||
target_phantom.reverse_segment_id.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
search(facade,
|
search(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
weight,
|
weight,
|
||||||
packed_path,
|
packed_path,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
{source_phantom, target_phantom},
|
||||||
weight_upper_bound);
|
weight_upper_bound);
|
||||||
|
|
||||||
if (weight == INVALID_EDGE_WEIGHT)
|
if (weight == INVALID_EDGE_WEIGHT)
|
||||||
@@ -216,11 +203,10 @@ namespace corech
|
|||||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||||
// requires
|
// requires
|
||||||
// a force loop, if the heaps have been initialized with positive offsets.
|
// a force loop, if the heaps have been initialized with positive offsets.
|
||||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_core_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_core_heap,
|
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
@@ -285,8 +271,7 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto insertInCoreHeap = [](const CoreEntryPoint &p,
|
const auto insertInCoreHeap = [](const CoreEntryPoint &p, auto &core_heap) {
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &core_heap) {
|
|
||||||
NodeID id;
|
NodeID id;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
@@ -295,13 +280,16 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
core_heap.Insert(id, weight, parent);
|
core_heap.Insert(id, weight, parent);
|
||||||
};
|
};
|
||||||
|
|
||||||
forward_core_heap.Clear();
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
|
||||||
|
auto &forward_core_heap = *engine_working_data.forward_heap_2;
|
||||||
|
auto &reverse_core_heap = *engine_working_data.reverse_heap_2;
|
||||||
|
|
||||||
for (const auto &p : forward_entry_points)
|
for (const auto &p : forward_entry_points)
|
||||||
{
|
{
|
||||||
insertInCoreHeap(p, forward_core_heap);
|
insertInCoreHeap(p, forward_core_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
reverse_core_heap.Clear();
|
|
||||||
for (const auto &p : reverse_entry_points)
|
for (const auto &p : reverse_entry_points)
|
||||||
{
|
{
|
||||||
insertInCoreHeap(p, reverse_core_heap);
|
insertInCoreHeap(p, reverse_core_heap);
|
||||||
@@ -395,29 +383,25 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
// Requires the heaps for be empty
|
// Requires the heaps for be empty
|
||||||
// If heaps should be adjusted to be initialized outside of this function,
|
// If heaps should be adjusted to be initialized outside of this function,
|
||||||
// the addition of force_loop parameters might be required
|
// the addition of force_loop parameters might be required
|
||||||
double getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_core_heap,
|
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_core_heap,
|
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
EdgeWeight weight_upper_bound)
|
EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
forward_core_heap.Clear();
|
|
||||||
reverse_core_heap.Clear();
|
|
||||||
|
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
|
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
search(facade,
|
search(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
weight,
|
weight,
|
||||||
packed_path,
|
packed_path,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
|
|||||||
@@ -21,11 +21,10 @@ const static constexpr bool DO_NOT_FORCE_LOOP = false;
|
|||||||
// allows a uturn at the target_phantom
|
// allows a uturn at the target_phantom
|
||||||
// searches source forward/reverse -> target forward/reverse
|
// searches source forward/reverse -> target forward/reverse
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_core_heap,
|
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_core_heap,
|
|
||||||
const bool search_from_forward_node,
|
const bool search_from_forward_node,
|
||||||
const bool search_from_reverse_node,
|
const bool search_from_reverse_node,
|
||||||
const bool search_to_forward_node,
|
const bool search_to_forward_node,
|
||||||
@@ -64,9 +63,6 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algori
|
|||||||
target_phantom.reverse_segment_id.id);
|
target_phantom.reverse_segment_id.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(forward_heap.Size() > 0);
|
|
||||||
BOOST_ASSERT(reverse_heap.Size() > 0);
|
|
||||||
|
|
||||||
// this is only relevent if source and target are on the same compressed edge
|
// this is only relevent if source and target are on the same compressed edge
|
||||||
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
|
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
|
||||||
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
|
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
|
||||||
@@ -75,15 +71,10 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algori
|
|||||||
auto needs_loop_backwards =
|
auto needs_loop_backwards =
|
||||||
is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
|
is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
|
||||||
|
|
||||||
forward_core_heap.Clear();
|
search(engine_working_data,
|
||||||
reverse_core_heap.Clear();
|
facade,
|
||||||
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
|
||||||
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
|
||||||
search(facade,
|
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
new_total_weight,
|
new_total_weight,
|
||||||
leg_packed_path,
|
leg_packed_path,
|
||||||
needs_loop_forwards,
|
needs_loop_forwards,
|
||||||
@@ -101,11 +92,10 @@ void searchWithUTurn(const datafacade::ContiguousInternalMemoryDataFacade<Algori
|
|||||||
// source forward/reverse -> target forward
|
// source forward/reverse -> target forward
|
||||||
// source forward/reverse -> target reverse
|
// source forward/reverse -> target reverse
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_core_heap,
|
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_core_heap,
|
|
||||||
const bool search_from_forward_node,
|
const bool search_from_forward_node,
|
||||||
const bool search_from_reverse_node,
|
const bool search_from_reverse_node,
|
||||||
const bool search_to_forward_node,
|
const bool search_to_forward_node,
|
||||||
@@ -144,15 +134,10 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
BOOST_ASSERT(forward_heap.Size() > 0);
|
BOOST_ASSERT(forward_heap.Size() > 0);
|
||||||
BOOST_ASSERT(reverse_heap.Size() > 0);
|
BOOST_ASSERT(reverse_heap.Size() > 0);
|
||||||
|
|
||||||
forward_core_heap.Clear();
|
search(engine_working_data,
|
||||||
reverse_core_heap.Clear();
|
facade,
|
||||||
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
|
||||||
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
|
||||||
search(facade,
|
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
new_total_weight_to_forward,
|
new_total_weight_to_forward,
|
||||||
leg_packed_path_forward,
|
leg_packed_path_forward,
|
||||||
needsLoopForward(source_phantom, target_phantom),
|
needsLoopForward(source_phantom, target_phantom),
|
||||||
@@ -183,15 +168,10 @@ void search(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &fac
|
|||||||
}
|
}
|
||||||
BOOST_ASSERT(forward_heap.Size() > 0);
|
BOOST_ASSERT(forward_heap.Size() > 0);
|
||||||
BOOST_ASSERT(reverse_heap.Size() > 0);
|
BOOST_ASSERT(reverse_heap.Size() > 0);
|
||||||
forward_core_heap.Clear();
|
search(engine_working_data,
|
||||||
reverse_core_heap.Clear();
|
facade,
|
||||||
BOOST_ASSERT(forward_core_heap.Size() == 0);
|
|
||||||
BOOST_ASSERT(reverse_core_heap.Size() == 0);
|
|
||||||
search(facade,
|
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
new_total_weight_to_reverse,
|
new_total_weight_to_reverse,
|
||||||
leg_packed_path_reverse,
|
leg_packed_path_reverse,
|
||||||
routing_algorithms::DO_NOT_FORCE_LOOP,
|
routing_algorithms::DO_NOT_FORCE_LOOP,
|
||||||
@@ -246,19 +226,16 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
: facade.GetContinueStraightDefault());
|
: facade.GetContinueStraightDefault());
|
||||||
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
|
||||||
|
|
||||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||||
auto &forward_core_heap = *engine_working_data.forward_heap_2;
|
|
||||||
auto &reverse_core_heap = *engine_working_data.reverse_heap_2;
|
|
||||||
|
|
||||||
int total_weight_to_forward = 0;
|
int total_weight_to_forward = 0;
|
||||||
int total_weight_to_reverse = 0;
|
int total_weight_to_reverse = 0;
|
||||||
bool search_from_forward_node =
|
bool search_from_forward_node =
|
||||||
phantom_nodes_vector.front().source_phantom.forward_segment_id.enabled;
|
phantom_nodes_vector.front().source_phantom.IsValidForwardSource();
|
||||||
bool search_from_reverse_node =
|
bool search_from_reverse_node =
|
||||||
phantom_nodes_vector.front().source_phantom.reverse_segment_id.enabled;
|
phantom_nodes_vector.front().source_phantom.IsValidReverseSource();
|
||||||
|
|
||||||
std::vector<NodeID> prev_packed_leg_to_forward;
|
std::vector<NodeID> prev_packed_leg_to_forward;
|
||||||
std::vector<NodeID> prev_packed_leg_to_reverse;
|
std::vector<NodeID> prev_packed_leg_to_reverse;
|
||||||
@@ -282,23 +259,20 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto &source_phantom = phantom_node_pair.source_phantom;
|
const auto &source_phantom = phantom_node_pair.source_phantom;
|
||||||
const auto &target_phantom = phantom_node_pair.target_phantom;
|
const auto &target_phantom = phantom_node_pair.target_phantom;
|
||||||
|
|
||||||
bool search_to_forward_node = target_phantom.forward_segment_id.enabled;
|
bool search_to_forward_node = target_phantom.IsValidForwardTarget();
|
||||||
bool search_to_reverse_node = target_phantom.reverse_segment_id.enabled;
|
bool search_to_reverse_node = target_phantom.IsValidReverseTarget();
|
||||||
|
|
||||||
BOOST_ASSERT(!search_from_forward_node || source_phantom.forward_segment_id.enabled);
|
BOOST_ASSERT(!search_from_forward_node || source_phantom.IsValidForwardSource());
|
||||||
BOOST_ASSERT(!search_from_reverse_node || source_phantom.reverse_segment_id.enabled);
|
BOOST_ASSERT(!search_from_reverse_node || source_phantom.IsValidReverseSource());
|
||||||
|
|
||||||
BOOST_ASSERT(search_from_forward_node || search_from_reverse_node);
|
|
||||||
|
|
||||||
if (search_to_reverse_node || search_to_forward_node)
|
if (search_to_reverse_node || search_to_forward_node)
|
||||||
{
|
{
|
||||||
if (allow_uturn_at_waypoint)
|
if (allow_uturn_at_waypoint)
|
||||||
{
|
{
|
||||||
searchWithUTurn(facade,
|
searchWithUTurn(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
search_from_forward_node,
|
search_from_forward_node,
|
||||||
search_from_reverse_node,
|
search_from_reverse_node,
|
||||||
search_to_forward_node,
|
search_to_forward_node,
|
||||||
@@ -311,9 +285,9 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
packed_leg_to_forward);
|
packed_leg_to_forward);
|
||||||
// if only the reverse node is valid (e.g. when using the match plugin) we
|
// if only the reverse node is valid (e.g. when using the match plugin) we
|
||||||
// actually need to move
|
// actually need to move
|
||||||
if (!target_phantom.forward_segment_id.enabled)
|
if (!target_phantom.IsValidForwardTarget())
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(target_phantom.reverse_segment_id.enabled);
|
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
|
||||||
new_total_weight_to_reverse = new_total_weight_to_forward;
|
new_total_weight_to_reverse = new_total_weight_to_forward;
|
||||||
packed_leg_to_reverse = std::move(packed_leg_to_forward);
|
packed_leg_to_reverse = std::move(packed_leg_to_forward);
|
||||||
new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
|
new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
|
||||||
@@ -323,7 +297,7 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
// Below we have to check if new_total_weight_to_forward is invalid.
|
// Below we have to check if new_total_weight_to_forward is invalid.
|
||||||
// This prevents use-after-move on packed_leg_to_forward.
|
// This prevents use-after-move on packed_leg_to_forward.
|
||||||
}
|
}
|
||||||
else if (target_phantom.reverse_segment_id.enabled)
|
else if (target_phantom.IsValidReverseTarget())
|
||||||
{
|
{
|
||||||
new_total_weight_to_reverse = new_total_weight_to_forward;
|
new_total_weight_to_reverse = new_total_weight_to_forward;
|
||||||
packed_leg_to_reverse = packed_leg_to_forward;
|
packed_leg_to_reverse = packed_leg_to_forward;
|
||||||
@@ -331,11 +305,10 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
search(facade,
|
search(engine_working_data,
|
||||||
|
facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
|
||||||
reverse_core_heap,
|
|
||||||
search_from_forward_node,
|
search_from_forward_node,
|
||||||
search_from_reverse_node,
|
search_from_reverse_node,
|
||||||
search_to_forward_node,
|
search_to_forward_node,
|
||||||
@@ -412,7 +385,7 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
if (new_total_weight_to_forward != INVALID_EDGE_WEIGHT)
|
if (new_total_weight_to_forward != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(target_phantom.forward_segment_id.enabled);
|
BOOST_ASSERT(target_phantom.IsValidForwardTarget());
|
||||||
|
|
||||||
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
|
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
|
||||||
total_packed_path_to_forward.insert(total_packed_path_to_forward.end(),
|
total_packed_path_to_forward.insert(total_packed_path_to_forward.end(),
|
||||||
@@ -429,7 +402,7 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
if (new_total_weight_to_reverse != INVALID_EDGE_WEIGHT)
|
if (new_total_weight_to_reverse != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(target_phantom.reverse_segment_id.enabled);
|
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
|
||||||
|
|
||||||
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
|
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
|
||||||
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),
|
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),
|
||||||
|
|||||||
@@ -7,30 +7,17 @@ namespace osrm
|
|||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename Algorithm>
|
// CH heaps
|
||||||
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
using CH = routing_algorithms::ch::Algorithm;
|
||||||
SearchEngineData<Algorithm>::forward_heap_1;
|
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_1;
|
||||||
template <typename Algorithm>
|
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_1;
|
||||||
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_2;
|
||||||
SearchEngineData<Algorithm>::reverse_heap_1;
|
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_2;
|
||||||
template <typename Algorithm>
|
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_3;
|
||||||
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_3;
|
||||||
SearchEngineData<Algorithm>::forward_heap_2;
|
SearchEngineData<CH>::ManyToManyHeapPtr SearchEngineData<CH>::many_to_many_heap;
|
||||||
template <typename Algorithm>
|
|
||||||
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
|
||||||
SearchEngineData<Algorithm>::reverse_heap_2;
|
|
||||||
template <typename Algorithm>
|
|
||||||
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
|
||||||
SearchEngineData<Algorithm>::forward_heap_3;
|
|
||||||
template <typename Algorithm>
|
|
||||||
typename SearchEngineData<Algorithm>::SearchEngineHeapPtr
|
|
||||||
SearchEngineData<Algorithm>::reverse_heap_3;
|
|
||||||
template <typename Algorithm>
|
|
||||||
typename SearchEngineData<Algorithm>::ManyToManyHeapPtr
|
|
||||||
SearchEngineData<Algorithm>::many_to_many_heap;
|
|
||||||
|
|
||||||
template <typename Algorithm>
|
void SearchEngineData<CH>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
||||||
void SearchEngineData<Algorithm>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
|
||||||
{
|
{
|
||||||
if (forward_heap_1.get())
|
if (forward_heap_1.get())
|
||||||
{
|
{
|
||||||
@@ -51,9 +38,7 @@ void SearchEngineData<Algorithm>::InitializeOrClearFirstThreadLocalStorage(unsig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
void SearchEngineData<CH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes)
|
||||||
void SearchEngineData<Algorithm>::InitializeOrClearSecondThreadLocalStorage(
|
|
||||||
unsigned number_of_nodes)
|
|
||||||
{
|
{
|
||||||
if (forward_heap_2.get())
|
if (forward_heap_2.get())
|
||||||
{
|
{
|
||||||
@@ -74,8 +59,7 @@ void SearchEngineData<Algorithm>::InitializeOrClearSecondThreadLocalStorage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
void SearchEngineData<CH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes)
|
||||||
void SearchEngineData<Algorithm>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes)
|
|
||||||
{
|
{
|
||||||
if (forward_heap_3.get())
|
if (forward_heap_3.get())
|
||||||
{
|
{
|
||||||
@@ -96,9 +80,7 @@ void SearchEngineData<Algorithm>::InitializeOrClearThirdThreadLocalStorage(unsig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
void SearchEngineData<CH>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes)
|
||||||
void SearchEngineData<Algorithm>::InitializeOrClearManyToManyThreadLocalStorage(
|
|
||||||
unsigned number_of_nodes)
|
|
||||||
{
|
{
|
||||||
if (many_to_many_heap.get())
|
if (many_to_many_heap.get())
|
||||||
{
|
{
|
||||||
@@ -110,57 +92,10 @@ void SearchEngineData<Algorithm>::InitializeOrClearManyToManyThreadLocalStorage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CH
|
|
||||||
using CH = routing_algorithms::ch::Algorithm;
|
|
||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_1;
|
|
||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_1;
|
|
||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_2;
|
|
||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_2;
|
|
||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::forward_heap_3;
|
|
||||||
template SearchEngineData<CH>::SearchEngineHeapPtr SearchEngineData<CH>::reverse_heap_3;
|
|
||||||
template SearchEngineData<CH>::ManyToManyHeapPtr SearchEngineData<CH>::many_to_many_heap;
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<routing_algorithms::ch::Algorithm>::InitializeOrClearFirstThreadLocalStorage(
|
|
||||||
unsigned number_of_nodes);
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CH>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
// CoreCH
|
|
||||||
using CoreCH = routing_algorithms::corech::Algorithm;
|
|
||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::forward_heap_1;
|
|
||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::reverse_heap_1;
|
|
||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::forward_heap_2;
|
|
||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::reverse_heap_2;
|
|
||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::forward_heap_3;
|
|
||||||
template SearchEngineData<CoreCH>::SearchEngineHeapPtr SearchEngineData<CoreCH>::reverse_heap_3;
|
|
||||||
template SearchEngineData<CoreCH>::ManyToManyHeapPtr SearchEngineData<CoreCH>::many_to_many_heap;
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CoreCH>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CoreCH>::InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CoreCH>::InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
template void
|
|
||||||
SearchEngineData<CoreCH>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
|
||||||
|
|
||||||
// MLD
|
// MLD
|
||||||
using MLD = routing_algorithms::mld::Algorithm;
|
using MLD = routing_algorithms::mld::Algorithm;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_1;
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_1;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_2;
|
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_2;
|
|
||||||
|
|
||||||
void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
||||||
{
|
{
|
||||||
@@ -182,26 +117,5 @@ void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned nu
|
|||||||
reverse_heap_1.reset(new QueryHeap(number_of_nodes));
|
reverse_heap_1.reset(new QueryHeap(number_of_nodes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData<MLD>::InitializeOrClearSecondThreadLocalStorage(unsigned)
|
|
||||||
{
|
|
||||||
if (forward_heap_2.get())
|
|
||||||
{
|
|
||||||
forward_heap_2->Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
forward_heap_2.reset(new QueryHeap(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reverse_heap_2.get())
|
|
||||||
{
|
|
||||||
reverse_heap_2->Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reverse_heap_2.reset(new QueryHeap(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -309,8 +309,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
storage::io::FileWriter turn_penalties_index_file(turn_penalties_index_filename,
|
storage::io::FileWriter turn_penalties_index_file(turn_penalties_index_filename,
|
||||||
storage::io::FileWriter::HasNoFingerprint);
|
storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
|
||||||
// TODO investigate increased peak memory consumption by keeping this in memory now
|
TurnDataExternalContainer turn_data_container;
|
||||||
TurnDataContainer turn_data_container;
|
|
||||||
|
|
||||||
// Loop over all turns and generate new set of edges.
|
// Loop over all turns and generate new set of edges.
|
||||||
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "extractor/geojson_debug_policies.hpp"
|
#include "extractor/geojson_debug_policies.hpp"
|
||||||
#include "util/geojson_debug_logger.hpp"
|
#include "util/geojson_debug_logger.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
@@ -278,7 +279,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// due to merging of roads, the u-turn might actually not be part of the intersection anymore
|
// due to merging of roads, the u-turn might actually not be part of the intersection anymore
|
||||||
const auto uturn_bearing = [&]() {
|
// uturn is a pair of {edge id, bearing}
|
||||||
|
const auto uturn = [&]() {
|
||||||
const auto merge_entry = std::find_if(
|
const auto merge_entry = std::find_if(
|
||||||
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
||||||
return entry.merged_eid == uturn_edge_itr->eid;
|
return entry.merged_eid == uturn_edge_itr->eid;
|
||||||
@@ -291,7 +293,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
normalized_intersection.end(),
|
normalized_intersection.end(),
|
||||||
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
||||||
BOOST_ASSERT(merged_u_turn != normalized_intersection.end());
|
BOOST_ASSERT(merged_u_turn != normalized_intersection.end());
|
||||||
return util::bearing::reverse(merged_u_turn->bearing);
|
return std::make_pair(merged_u_turn->eid,
|
||||||
|
util::bearing::reverse(merged_u_turn->bearing));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -301,7 +304,9 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
connect_to_previous_node);
|
connect_to_previous_node);
|
||||||
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
||||||
normalized_intersection.end());
|
normalized_intersection.end());
|
||||||
return util::bearing::reverse(uturn_edge_at_normalized_intersection_itr->bearing);
|
return std::make_pair(
|
||||||
|
uturn_edge_at_normalized_intersection_itr->eid,
|
||||||
|
util::bearing::reverse(uturn_edge_at_normalized_intersection_itr->bearing));
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
@@ -314,7 +319,7 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
return IntersectionViewData(
|
return IntersectionViewData(
|
||||||
road,
|
road,
|
||||||
is_allowed_turn(road),
|
is_allowed_turn(road),
|
||||||
util::bearing::angleBetween(uturn_bearing, road.bearing));
|
util::bearing::angleBetween(uturn.second, road.bearing));
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto uturn_edge_at_intersection_view_itr =
|
const auto uturn_edge_at_intersection_view_itr =
|
||||||
@@ -369,8 +374,22 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
std::end(intersection_view),
|
std::end(intersection_view),
|
||||||
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
||||||
|
|
||||||
BOOST_ASSERT(intersection_view[0].angle >= 0. &&
|
// Move entering_via_edge to intersection front and place all roads prior entering_via_edge
|
||||||
intersection_view[0].angle < std::numeric_limits<double>::epsilon());
|
// at the end of the intersection view with 360° angle
|
||||||
|
auto entering_via_it = std::find_if(intersection_view.begin(),
|
||||||
|
intersection_view.end(),
|
||||||
|
[&uturn](auto &road) { return road.eid == uturn.first; });
|
||||||
|
|
||||||
|
OSRM_ASSERT(entering_via_it != intersection_view.end() && entering_via_it->angle >= 0. &&
|
||||||
|
entering_via_it->angle < std::numeric_limits<double>::epsilon(),
|
||||||
|
coordinates[node_at_intersection]);
|
||||||
|
|
||||||
|
if (entering_via_it != intersection_view.begin() && entering_via_it != intersection_view.end())
|
||||||
|
{
|
||||||
|
std::for_each(
|
||||||
|
intersection_view.begin(), entering_via_it, [](auto &road) { road.angle = 360.; });
|
||||||
|
std::rotate(intersection_view.begin(), entering_via_it, intersection_view.end());
|
||||||
|
}
|
||||||
|
|
||||||
return intersection_view;
|
return intersection_view;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "extractor/guidance/roundabout_handler.hpp"
|
#include "extractor/guidance/roundabout_handler.hpp"
|
||||||
#include "extractor/guidance/constants.hpp"
|
#include "extractor/guidance/constants.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/guidance/name_announcements.hpp"
|
#include "util/guidance/name_announcements.hpp"
|
||||||
@@ -111,32 +112,65 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
|||||||
if (in_edge_data.roundabout || in_edge_data.circular)
|
if (in_edge_data.roundabout || in_edge_data.circular)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool past_roundabout_angle = false;
|
// Find range in which exits that must be invalidated (shaded areas):
|
||||||
const bool lhs = profile_properties.left_hand_driving;
|
// exit..end exit..end begin..exit for ↺ roundabouts
|
||||||
const int step = lhs ? -1 : 1;
|
// *************************************
|
||||||
for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size();
|
// * <--. ^ <--. / <--. *
|
||||||
++cnt, idx += step)
|
// * | / | /░ | *
|
||||||
|
// * |/ |v░░ -->| *
|
||||||
|
// * |^ |\ ░ ░░░|\ *
|
||||||
|
// * |░\ |░\░ ░░░| \ *
|
||||||
|
// * --'░░░\ --'░░░v --' v *
|
||||||
|
// *************************************
|
||||||
|
//
|
||||||
|
// begin..exit begin..exit exit..end for ↻ roundabouts
|
||||||
|
// *************************************
|
||||||
|
// * --.░░░^ --.░░░/ --. ^ *
|
||||||
|
// * |░/░ |░/ ░░░| / *
|
||||||
|
// * |/░░ |v ░░░|/ *
|
||||||
|
// * |^░░ |\ -->| *
|
||||||
|
// * | \░ | \ | *
|
||||||
|
// * <--' \ <--' v <--' *
|
||||||
|
// *************************************
|
||||||
|
bool roundabout_entry_first = false;
|
||||||
|
auto invalidate_from = intersection.end(), invalidate_to = intersection.end();
|
||||||
|
for (auto road = intersection.begin(); road != intersection.end(); ++road)
|
||||||
{
|
{
|
||||||
auto &road = intersection[idx];
|
const auto &edge_data = node_based_graph.GetEdgeData(road->eid);
|
||||||
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
|
if (edge_data.roundabout || edge_data.circular)
|
||||||
// only check actual outgoing edges
|
|
||||||
if (edge_data.reversed)
|
|
||||||
{
|
{
|
||||||
// remember whether we have seen the roundabout in-part
|
if (edge_data.reversed)
|
||||||
if (edge_data.roundabout || edge_data.circular)
|
{
|
||||||
past_roundabout_angle = true;
|
if (roundabout_entry_first)
|
||||||
|
{ // invalidate turns in range exit..end
|
||||||
continue;
|
invalidate_from = road + 1;
|
||||||
|
invalidate_to = intersection.end();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // invalidate turns in range begin..exit
|
||||||
|
invalidate_from = intersection.begin() + 1;
|
||||||
|
invalidate_to = road;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roundabout_entry_first = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
OSRM_ASSERT(invalidate_from <= invalidate_to, coordinates[from_nid]);
|
||||||
// This workaround handles cases in which an exit precedes and entry. The resulting
|
|
||||||
// u-turn against the roundabout direction is invalidated.
|
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
||||||
// The sorting of the angles represents a problem for left-sided driving, though.
|
// This workaround handles cases in which an exit precedes and entry. The resulting
|
||||||
|
// u-turn against the roundabout direction is invalidated.
|
||||||
|
for (; invalidate_from != invalidate_to; ++invalidate_from)
|
||||||
|
{
|
||||||
|
const auto &edge_data = node_based_graph.GetEdgeData(invalidate_from->eid);
|
||||||
if (!edge_data.roundabout && !edge_data.circular &&
|
if (!edge_data.roundabout && !edge_data.circular &&
|
||||||
node_based_graph.GetTarget(road.eid) != from_nid && past_roundabout_angle)
|
node_based_graph.GetTarget(invalidate_from->eid) != from_nid)
|
||||||
{
|
{
|
||||||
road.entry_allowed = false;
|
invalidate_from->entry_allowed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-37
@@ -50,43 +50,31 @@ NAN_MODULE_INIT(Engine::Init)
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* The `OSRM` method is the main constructor for creating an OSRM instance.
|
* The `OSRM` method is the main constructor for creating an OSRM instance.
|
||||||
* An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
* An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
||||||
* The documentation on `osrm-extract` and `osrm-contract` for more information.
|
* You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
|
||||||
* Once you have a complete `network.osrm` file, you can calculate routes in javascript with this library using the methods below.
|
* profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
|
||||||
* To create an OSRM instance with your network you need to construct an instance like this:
|
*
|
||||||
|
* node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
|
||||||
|
* node_modules/osrm/lib/binding/osrm-contract data.osrm
|
||||||
|
*
|
||||||
|
* Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
|
||||||
|
*
|
||||||
|
* Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* var osrm = new OSRM('network.osrm');
|
* var osrm = new OSRM('network.osrm');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### Methods
|
* @param {Object|String} [options={shared_memory: true}] Options for creating an OSRM object or string to the `.osrm` file.
|
||||||
*
|
* @param {String} [options.algorithm] The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
|
||||||
* | Service | Description |
|
* Make sure you prepared the dataset with the correct toolchain.
|
||||||
* |-----------------------------|-----------------------------------------------------------|
|
* @param {Boolean} [options.shared_memory] Connects to the persistent shared memory datastore.
|
||||||
* | [`osrm.route`](#route) | shortest path between given coordinates |
|
* This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
||||||
* | [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
|
* @param {String} [options.path] The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
|
||||||
* | [`osrm.table`](#table) | computes distance tables for given coordinates |
|
|
||||||
* | [`osrm.match`](#match) | matches given coordinates to the road network |
|
|
||||||
* | [`osrm.trip`](#trip) | computes the shortest trip between given coordinates |
|
|
||||||
* | [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
|
|
||||||
*
|
|
||||||
* #### General Options
|
|
||||||
*
|
|
||||||
* Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options,
|
|
||||||
* outlined below.
|
|
||||||
*
|
|
||||||
* | Option | Values | Description | Format |
|
|
||||||
* | ----------- | -----------------| ------------ | -------|
|
|
||||||
* | coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
|
|
||||||
* | bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
|
|
||||||
* | radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
|
|
||||||
* | hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
|
|
||||||
*
|
*
|
||||||
* @class OSRM
|
* @class OSRM
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
// clang-format on
|
// clang-format on
|
||||||
NAN_METHOD(Engine::New)
|
NAN_METHOD(Engine::New)
|
||||||
@@ -192,11 +180,15 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
|||||||
* @name route
|
* @name route
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options Object literal containing parameters for the route query.
|
* @param {Object} options Object literal containing parameters for the route query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Boolean} [options.alternatives=false] Search for alternative routes and return as well.
|
* @param {Boolean} [options.alternatives=false] Search for alternative routes and return as well.
|
||||||
* *Please note that even if an alternative route is requested, a result cannot be guaranteed.*
|
* *Please note that even if an alternative route is requested, a result cannot be guaranteed.*
|
||||||
* @param {Boolean} [options.steps=false] Return route steps for each route leg.
|
* @param {Boolean} [options.steps=false] Return route steps for each route leg.
|
||||||
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
|
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
|
||||||
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
|
|
||||||
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
||||||
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
||||||
* @param {Boolean} [options.continue_straight] 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.
|
* @param {Boolean} [options.continue_straight] 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.
|
||||||
@@ -228,6 +220,11 @@ NAN_METHOD(Engine::route) //
|
|||||||
* @name nearest
|
* @name nearest
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the nearest query.
|
* @param {Object} options - Object literal containing parameters for the nearest query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Number} [options.number=1] Number of nearest segments that should be returned.
|
* @param {Number} [options.number=1] Number of nearest segments that should be returned.
|
||||||
* Must be an integer greater than or equal to `1`.
|
* Must be an integer greater than or equal to `1`.
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
@@ -261,6 +258,11 @@ NAN_METHOD(Engine::nearest) //
|
|||||||
* @name table
|
* @name table
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the table query.
|
* @param {Object} options - Object literal containing parameters for the table query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Array} [options.sources] An array of `index` elements (`0 <= integer < #coordinates`) to
|
* @param {Array} [options.sources] An array of `index` elements (`0 <= integer < #coordinates`) to
|
||||||
* use
|
* use
|
||||||
* location with given index as source. Default is to use all.
|
* location with given index as source. Default is to use all.
|
||||||
@@ -337,13 +339,16 @@ NAN_METHOD(Engine::tile)
|
|||||||
* @name match
|
* @name match
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the match query.
|
* @param {Object} options - Object literal containing parameters for the match query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
||||||
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
|
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
|
||||||
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
|
|
||||||
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
||||||
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
||||||
* @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like timestamp).
|
* @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like timestamp).
|
||||||
* @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy (`double >= 0`, default `5m`).
|
* @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*
|
*
|
||||||
* @returns {Object} containing `tracepoints` and `matchings`.
|
* @returns {Object} containing `tracepoints` and `matchings`.
|
||||||
@@ -380,14 +385,32 @@ NAN_METHOD(Engine::match) //
|
|||||||
* (farthest-insertion algorithm) for 10 or * more waypoints and uses brute force for less than 10
|
* (farthest-insertion algorithm) for 10 or * more waypoints and uses brute force for less than 10
|
||||||
* waypoints. The returned path does not have to be the shortest path, * as TSP is NP-hard it is
|
* waypoints. The returned path does not have to be the shortest path, * as TSP is NP-hard it is
|
||||||
* only an approximation.
|
* only an approximation.
|
||||||
|
*
|
||||||
* Note that all input coordinates have to be connected for the trip service to work.
|
* Note that all input coordinates have to be connected for the trip service to work.
|
||||||
|
* Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
|
||||||
|
* Right now, the following combinations are possible:
|
||||||
|
*
|
||||||
|
* | roundtrip | source | destination | supported |
|
||||||
|
* | :-- | :-- | :-- | :-- |
|
||||||
|
* | true | first | last | **yes** |
|
||||||
|
* | true | first | any | **yes** |
|
||||||
|
* | true | any | last | **yes** |
|
||||||
|
* | true | any | any | **yes** |
|
||||||
|
* | false | first | last | **yes** |
|
||||||
|
* | false | first | any | no |
|
||||||
|
* | false | any | last | no |
|
||||||
|
* | false | any | any | no |
|
||||||
*
|
*
|
||||||
* @name trip
|
* @name trip
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the trip query.
|
* @param {Object} options - Object literal containing parameters for the trip query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
||||||
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg. Can be `false`,
|
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
|
||||||
* `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
|
|
||||||
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
||||||
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
|
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
@@ -398,8 +421,8 @@ NAN_METHOD(Engine::match) //
|
|||||||
* @returns {Object} containing `waypoints` and `trips`.
|
* @returns {Object} containing `waypoints` and `trips`.
|
||||||
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
|
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
|
||||||
* Each Waypoint object has the following additional properties,
|
* Each Waypoint object has the following additional properties,
|
||||||
* 1) `trips_index`: index to trips of the sub-trip the point was matched to,
|
* 1) `trips_index`: index to trips of the sub-trip the point was matched to, and
|
||||||
* and 2) `waypoint_index`: index of the point in the trip.
|
* 2) `waypoint_index`: index of the point in the trip.
|
||||||
* **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
* **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -408,7 +431,10 @@ NAN_METHOD(Engine::match) //
|
|||||||
* coordinates: [
|
* coordinates: [
|
||||||
* [13.36761474609375, 52.51663871100423],
|
* [13.36761474609375, 52.51663871100423],
|
||||||
* [13.374481201171875, 52.506191342034576]
|
* [13.374481201171875, 52.506191342034576]
|
||||||
* ]
|
* ],
|
||||||
|
* source: "first",
|
||||||
|
* destination: "last",
|
||||||
|
* roundtrip: false
|
||||||
* }
|
* }
|
||||||
* osrm.trip(options, function(err, response) {
|
* osrm.trip(options, function(err, response) {
|
||||||
* if (err) throw err;
|
* if (err) throw err;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ BOOST_FUSION_ADAPT_STRUCT(osrm::updater::Segment,
|
|||||||
(decltype(osrm::updater::Segment::to), to))
|
(decltype(osrm::updater::Segment::to), to))
|
||||||
BOOST_FUSION_ADAPT_STRUCT(osrm::updater::SpeedSource,
|
BOOST_FUSION_ADAPT_STRUCT(osrm::updater::SpeedSource,
|
||||||
(decltype(osrm::updater::SpeedSource::speed), speed)
|
(decltype(osrm::updater::SpeedSource::speed), speed)
|
||||||
(decltype(osrm::updater::SpeedSource::weight), weight))
|
(decltype(osrm::updater::SpeedSource::rate), rate))
|
||||||
BOOST_FUSION_ADAPT_STRUCT(osrm::updater::Turn,
|
BOOST_FUSION_ADAPT_STRUCT(osrm::updater::Turn,
|
||||||
(decltype(osrm::updater::Turn::from), from)
|
(decltype(osrm::updater::Turn::from), from)
|
||||||
(decltype(osrm::updater::Turn::via), via)
|
(decltype(osrm::updater::Turn::via), via)
|
||||||
|
|||||||
+36
-22
@@ -34,6 +34,7 @@
|
|||||||
#include <tbb/parallel_invoke.h>
|
#include <tbb/parallel_invoke.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -62,18 +63,9 @@ inline EdgeWeight convertToDuration(double speed_in_kmh, double distance_in_mete
|
|||||||
if (speed_in_kmh <= 0.)
|
if (speed_in_kmh <= 0.)
|
||||||
return MAXIMAL_EDGE_DURATION;
|
return MAXIMAL_EDGE_DURATION;
|
||||||
|
|
||||||
const double speed_in_ms = speed_in_kmh / 3.6;
|
const auto speed_in_ms = speed_in_kmh / 3.6;
|
||||||
const double duration = distance_in_meters / speed_in_ms;
|
const auto duration = distance_in_meters / speed_in_ms;
|
||||||
return std::max<EdgeWeight>(1, static_cast<EdgeWeight>(std::round(duration * 10.)));
|
return std::max(1, boost::numeric_cast<EdgeWeight>(std::round(duration * 10.)));
|
||||||
}
|
|
||||||
|
|
||||||
inline EdgeWeight convertToWeight(double weight, double weight_multiplier, EdgeWeight duration)
|
|
||||||
{
|
|
||||||
if (std::isfinite(weight))
|
|
||||||
return std::round(weight * weight_multiplier);
|
|
||||||
|
|
||||||
return duration == MAXIMAL_EDGE_DURATION ? INVALID_EDGE_WEIGHT
|
|
||||||
: duration * weight_multiplier / 10.;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
@@ -140,8 +132,6 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
const SegmentLookupTable &segment_speed_lookup,
|
const SegmentLookupTable &segment_speed_lookup,
|
||||||
extractor::SegmentDataContainer &segment_data)
|
extractor::SegmentDataContainer &segment_data)
|
||||||
{
|
{
|
||||||
auto weight_multiplier = profile_properties.GetWeightMultiplier();
|
|
||||||
|
|
||||||
std::vector<util::Coordinate> coordinates;
|
std::vector<util::Coordinate> coordinates;
|
||||||
util::PackedVector<OSMNodeID> osm_node_ids;
|
util::PackedVector<OSMNodeID> osm_node_ids;
|
||||||
extractor::files::readNodes(config.node_based_graph_path, coordinates, osm_node_ids);
|
extractor::files::readNodes(config.node_based_graph_path, coordinates, osm_node_ids);
|
||||||
@@ -154,6 +144,25 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
counters_type(num_counters, 0));
|
counters_type(num_counters, 0));
|
||||||
const constexpr auto LUA_SOURCE = 0;
|
const constexpr auto LUA_SOURCE = 0;
|
||||||
|
|
||||||
|
// closure to convert SpeedSource value to weight and count fallbacks to durations
|
||||||
|
std::atomic<std::uint32_t> fallbacks_to_duration{0};
|
||||||
|
auto convertToWeight = [&profile_properties, &fallbacks_to_duration](
|
||||||
|
const SpeedSource &value, double distance_in_meters) {
|
||||||
|
double rate = value.rate;
|
||||||
|
if (!std::isfinite(rate))
|
||||||
|
{ // use speed value in meters per second as the rate
|
||||||
|
++fallbacks_to_duration;
|
||||||
|
rate = value.speed / 3.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rate <= 0.)
|
||||||
|
return INVALID_EDGE_WEIGHT;
|
||||||
|
|
||||||
|
const auto weight_multiplier = profile_properties.GetWeightMultiplier();
|
||||||
|
const auto weight = distance_in_meters / rate;
|
||||||
|
return std::max(1, boost::numeric_cast<EdgeWeight>(std::round(weight * weight_multiplier)));
|
||||||
|
};
|
||||||
|
|
||||||
// The check here is enabled by the `--edge-weight-updates-over-factor` flag it logs a
|
// The check here is enabled by the `--edge-weight-updates-over-factor` flag it logs a
|
||||||
// warning if the new duration exceeds a heuristic of what a reasonable duration update is
|
// warning if the new duration exceeds a heuristic of what a reasonable duration update is
|
||||||
std::unique_ptr<extractor::SegmentDataContainer> segment_data_backup;
|
std::unique_ptr<extractor::SegmentDataContainer> segment_data_backup;
|
||||||
@@ -191,10 +200,9 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
auto v = osm_node_ids[nodes_range[segment_offset + 1]];
|
auto v = osm_node_ids[nodes_range[segment_offset + 1]];
|
||||||
if (auto value = segment_speed_lookup({u, v}))
|
if (auto value = segment_speed_lookup({u, v}))
|
||||||
{
|
{
|
||||||
auto new_duration =
|
auto segment_length = segment_lengths[segment_offset];
|
||||||
convertToDuration(value->speed, segment_lengths[segment_offset]);
|
auto new_duration = convertToDuration(value->speed, segment_length);
|
||||||
auto new_weight =
|
auto new_weight = convertToWeight(*value, segment_length);
|
||||||
convertToWeight(value->weight, weight_multiplier, new_duration);
|
|
||||||
fwd_was_updated = true;
|
fwd_was_updated = true;
|
||||||
|
|
||||||
fwd_weights_range[segment_offset] = new_weight;
|
fwd_weights_range[segment_offset] = new_weight;
|
||||||
@@ -225,10 +233,9 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
auto v = osm_node_ids[nodes_range[segment_offset + 1]];
|
auto v = osm_node_ids[nodes_range[segment_offset + 1]];
|
||||||
if (auto value = segment_speed_lookup({v, u}))
|
if (auto value = segment_speed_lookup({v, u}))
|
||||||
{
|
{
|
||||||
auto new_duration =
|
auto segment_length = segment_lengths[segment_offset];
|
||||||
convertToDuration(value->speed, segment_lengths[segment_offset]);
|
auto new_duration = convertToDuration(value->speed, segment_length);
|
||||||
auto new_weight =
|
auto new_weight = convertToWeight(*value, segment_length);
|
||||||
convertToWeight(value->weight, weight_multiplier, new_duration);
|
|
||||||
rev_was_updated = true;
|
rev_was_updated = true;
|
||||||
|
|
||||||
rev_weights_range[segment_offset] = new_weight;
|
rev_weights_range[segment_offset] = new_weight;
|
||||||
@@ -271,6 +278,13 @@ updateSegmentData(const UpdaterConfig &config,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!profile_properties.fallback_to_duration && fallbacks_to_duration > 0)
|
||||||
|
{
|
||||||
|
util::Log(logWARNING) << "Speed values were used to update " << fallbacks_to_duration
|
||||||
|
<< " segments for '" << profile_properties.GetWeightName()
|
||||||
|
<< "' profile";
|
||||||
|
}
|
||||||
|
|
||||||
if (config.log_edge_updates_factor > 0)
|
if (config.log_edge_updates_factor > 0)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(segment_data_backup);
|
BOOST_ASSERT(segment_data_backup);
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ OSRM_CUSTOMIZE:=$(OSRM_BUILD_DIR)/osrm-customize
|
|||||||
OSRM_ROUTED:=$(OSRM_BUILD_DIR)/osrm-routed
|
OSRM_ROUTED:=$(OSRM_BUILD_DIR)/osrm-routed
|
||||||
POLY2REQ:=$(SCRIPT_ROOT)/poly2req.js
|
POLY2REQ:=$(SCRIPT_ROOT)/poly2req.js
|
||||||
MD5SUM:=$(SCRIPT_ROOT)/md5sum.js
|
MD5SUM:=$(SCRIPT_ROOT)/md5sum.js
|
||||||
TIMER:=$(SCRIPT_ROOT)/timer.sh
|
TIMER:=$(SCRIPT_ROOT)/timer.js
|
||||||
PROFILE:=$(PROFILE_ROOT)/car.lua
|
PROFILE:=$(PROFILE_ROOT)/car.lua
|
||||||
|
|
||||||
all: data
|
all: data
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ BOOST_AUTO_TEST_CASE(two_item_trace_needs_tidiying_test)
|
|||||||
auto result = tidy::tidy(params, thresholds);
|
auto result = tidy::tidy(params, thresholds);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 1);
|
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[1], true);
|
BOOST_CHECK_EQUAL(result.can_be_removed[1], false);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,16 +87,18 @@ BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_test)
|
|||||||
auto result = tidy::tidy(params, thresholds);
|
auto result = tidy::tidy(params, thresholds);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 3);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||||
|
BOOST_CHECK_EQUAL(result.tidied_to_original[2], 5);
|
||||||
|
|
||||||
const auto redundant = result.can_be_removed.count();
|
const auto redundant = result.can_be_removed.count();
|
||||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 3);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||||
|
BOOST_CHECK_EQUAL(result.can_be_removed[5], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
||||||
@@ -118,15 +120,17 @@ BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
|||||||
auto result = tidy::tidy(params, thresholds);
|
auto result = tidy::tidy(params, thresholds);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 3);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||||
|
BOOST_CHECK_EQUAL(result.tidied_to_original[2], 5);
|
||||||
|
|
||||||
const auto redundant = result.can_be_removed.count();
|
const auto redundant = result.can_be_removed.count();
|
||||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 3);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||||
|
BOOST_CHECK_EQUAL(result.can_be_removed[5], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
@@ -151,4 +151,27 @@ BOOST_AUTO_TEST_CASE(test_table_three_coordinates_matrix)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://github.com/Project-OSRM/osrm-backend/pull/3992
|
||||||
|
BOOST_AUTO_TEST_CASE(test_table_no_segment_for_some_coordinates)
|
||||||
|
{
|
||||||
|
using namespace osrm;
|
||||||
|
|
||||||
|
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
|
||||||
|
|
||||||
|
TableParameters params;
|
||||||
|
params.coordinates.push_back(get_dummy_location());
|
||||||
|
params.coordinates.push_back(get_dummy_location());
|
||||||
|
// resembles query option: `&radiuses=0;`
|
||||||
|
params.radiuses.push_back(boost::make_optional(0.));
|
||||||
|
params.radiuses.push_back(boost::none);
|
||||||
|
|
||||||
|
json::Object result;
|
||||||
|
|
||||||
|
const auto rc = osrm.Table(params, result);
|
||||||
|
|
||||||
|
BOOST_CHECK(rc == Status::Error);
|
||||||
|
const auto code = result.values.at("code").get<json::String>().value;
|
||||||
|
BOOST_CHECK_EQUAL(code, "NoSegment");
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
Reference in New Issue
Block a user