Compare commits
137 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 | |||
| 56bcb491d3 | |||
| f4e2bd848d | |||
| 0cf96314a3 | |||
| 91e24cab9e | |||
| 288155ead0 | |||
| 85454857d3 | |||
| fe50f6590a | |||
| 2da5da3f16 | |||
| 446c865415 | |||
| 0072bf0c59 | |||
| 4ec7ca29f1 | |||
| d94017dfae | |||
| dce0ce0e17 | |||
| d61102e255 | |||
| 7f6e0c478b | |||
| 786a3d8919 | |||
| ef3fcdc6e6 | |||
| 90c194fc81 | |||
| 5ed686a17b | |||
| 4e3009260c | |||
| c87ce2dede | |||
| 99a87b4c83 | |||
| 3f5fc1e897 | |||
| 97d1de1beb | |||
| d7e1c9c09c | |||
| 865111bca9 | |||
| 08d62cd5e3 | |||
| 603e2ee7de | |||
| 98948989d0 | |||
| 1aa8cc3b65 | |||
| c487d1307e | |||
| 604f4957f7 | |||
| 7726576bb7 | |||
| cf17a3a4c3 | |||
| 0972ec9115 | |||
| f660ae30dc | |||
| 2766c24b42 | |||
| cab83555e1 | |||
| 48a098a9c7 | |||
| a1fa1c610c | |||
| 905ca69301 | |||
| d66cc125aa | |||
| 3fc0fc65f9 | |||
| 8c64b01d67 | |||
| 2566f64c34 |
@@ -7,6 +7,8 @@
|
||||
#############################
|
||||
osrm-deps
|
||||
|
||||
.ycm_extra_conf.py
|
||||
|
||||
# Compiled source #
|
||||
###################
|
||||
*.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
|
||||
dist: trusty
|
||||
|
||||
nodejs:
|
||||
node_js:
|
||||
- "4"
|
||||
- "6"
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -16,6 +17,7 @@ notifications:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- "5.7"
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
@@ -36,6 +38,8 @@ env:
|
||||
- CCACHE_VERSION=3.3.1
|
||||
- CMAKE_VERSION=3.7.2
|
||||
- MASON="$(pwd)/scripts/mason.sh"
|
||||
- ENABLE_NODE_BINDINGS=On
|
||||
- NODE="4"
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
@@ -45,12 +49,14 @@ matrix:
|
||||
|
||||
# Debug Builds
|
||||
- os: linux
|
||||
compiler: "gcc-6-debug"
|
||||
compiler: "gcc-6-debug-cov-asan"
|
||||
addons: &gcc6
|
||||
apt:
|
||||
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']
|
||||
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
|
||||
compiler: "clang-4.0-debug"
|
||||
@@ -61,12 +67,12 @@ matrix:
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
||||
|
||||
- os: linux
|
||||
compiler: "mason-linux-debug-santize"
|
||||
compiler: "mason-linux-debug-asan"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
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
|
||||
- os: linux
|
||||
@@ -75,7 +81,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
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
|
||||
compiler: "gcc-6-release"
|
||||
@@ -104,6 +110,8 @@ matrix:
|
||||
compiler: "mason-osx-release"
|
||||
# we use the xcode provides clang and don't install our own
|
||||
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
# Disabled because of CI slowness
|
||||
#- 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']
|
||||
#- 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:
|
||||
- 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 [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
export JOBS=$((`nproc` + 1))
|
||||
if [[ -z $JOBS ]]; then
|
||||
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
|
||||
- |
|
||||
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
||||
@@ -144,8 +253,10 @@ before_install:
|
||||
fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
||||
sudo mdutil -i off /
|
||||
fi
|
||||
- |
|
||||
if [[ ! -f $(which yarn) ]]; then
|
||||
npm install -g yarn
|
||||
fi
|
||||
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
||||
@@ -173,15 +284,17 @@ before_install:
|
||||
fi
|
||||
fi
|
||||
- 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:
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
fi
|
||||
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
|
||||
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
|
||||
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
@@ -191,7 +304,8 @@ install:
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
||||
-DBUILD_TOOLS=ON \
|
||||
-DENABLE_CCACHE=ON
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
- echo "travis_fold:start:MAKE"
|
||||
- make --jobs=${JOBS}
|
||||
- make tests --jobs=${JOBS}
|
||||
@@ -201,10 +315,11 @@ install:
|
||||
- sudo make install
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
sudo ldconfig
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${OSRM_INSTALL_DIR}/lib
|
||||
fi
|
||||
- popd
|
||||
- mkdir example/build && pushd example/build
|
||||
- export PKG_CONFIG_PATH=${OSRM_INSTALL_DIR}/lib/pkgconfig
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
@@ -224,19 +339,9 @@ script:
|
||||
- ./unit_tests/server-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
|
||||
fi
|
||||
- popd
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- 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
|
||||
- .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-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
|
||||
- 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
|
||||
- Changes from 5.6.0
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ endif()
|
||||
project(OSRM C CXX)
|
||||
set(OSRM_VERSION_MAJOR 5)
|
||||
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}")
|
||||
|
||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
@@ -37,27 +37,35 @@ Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
|
||||
|
||||
## Quick Start
|
||||
|
||||
The easiest and quickest way to setup your own routing engine backend is to use Docker images we provide.
|
||||
The easiest and quickest way to setup your own routing engine is to use Docker images we provide.
|
||||
|
||||
### Using Docker
|
||||
|
||||
We base [our Docker images](https://hub.docker.com/r/osrm/osrm-backend/) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
|
||||
```
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
|
||||
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
|
||||
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
|
||||
|
||||
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
|
||||
```
|
||||
Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000
|
||||
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
|
||||
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
|
||||
|
||||
Make requests against the HTTP server
|
||||
|
||||
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
|
||||
|
||||
Optionally start a user-friendly frontend on port 9966, and open it up in your browser
|
||||
|
||||
docker run -p 9966:9966 osrm/osrm-frontend
|
||||
xdg-open 'http://127.0.0.1:9966'
|
||||
|
||||
In case Docker complains about not being able to connect to the Docker daemon make sure you are in the `docker` group.
|
||||
|
||||
```
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
|
||||
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
# Vendored NodeJs.cmake to bootstrap our C++ build without
|
||||
# having the user to install Node modules via `npm install`.
|
||||
#
|
||||
# Update via: ../node_modules/.bin/ncmake update
|
||||
|
||||
|
||||
# Defaults for standard Node.js builds
|
||||
set(NODEJS_DEFAULT_URL https://nodejs.org/download/release)
|
||||
set(NODEJS_DEFAULT_VERSION installed)
|
||||
set(NODEJS_VERSION_FALLBACK latest)
|
||||
set(NODEJS_DEFAULT_NAME node)
|
||||
set(NODEJS_DEFAULT_CHECKSUM SHASUMS256.txt)
|
||||
set(NODEJS_DEFAULT_CHECKTYPE SHA256)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Find a path by walking upward from a base directory until the path is
|
||||
# found. Sets the variable ${PATH} to False if the path can't
|
||||
# be determined
|
||||
function(find_path_parent NAME BASE PATH)
|
||||
set(ROOT ${BASE})
|
||||
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
|
||||
set(DRIVE "^[A-Za-z]?:?/$")
|
||||
while(NOT ROOT MATCHES ${DRIVE} AND NOT EXISTS ${ROOT}/${NAME})
|
||||
get_filename_component(ROOT ${ROOT} DIRECTORY)
|
||||
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
|
||||
endwhile()
|
||||
if(ROOT MATCHES ${DRIVE})
|
||||
set(${PATH} False PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Shortcut for finding standard node module locations
|
||||
macro(find_nodejs_module NAME BASE PATH)
|
||||
find_path_parent(node_modules/${NAME} ${BASE} ${PATH})
|
||||
endmacro()
|
||||
|
||||
# Download with a bit of nice output (without spewing progress)
|
||||
function(download_file URL)
|
||||
message(STATUS "Downloading: ${URL}")
|
||||
file(DOWNLOAD
|
||||
${URL}
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Embedded win_delay_load_hook file so that this file can be copied
|
||||
# into projects directly (recommended practice)
|
||||
function(nodejs_generate_delayload_hook OUTPUT)
|
||||
file(WRITE ${OUTPUT} "")
|
||||
file(APPEND ${OUTPUT} "/*\n")
|
||||
file(APPEND ${OUTPUT} " * When this file is linked to a DLL, it sets up a delay-load hook that\n")
|
||||
file(APPEND ${OUTPUT} " * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe'\n")
|
||||
file(APPEND ${OUTPUT} " * dynamically. Instead of trying to locate the .exe file it'll just return\n")
|
||||
file(APPEND ${OUTPUT} " * a handle to the process image.\n")
|
||||
file(APPEND ${OUTPUT} " *\n")
|
||||
file(APPEND ${OUTPUT} " * This allows compiled addons to work when node.exe or iojs.exe is renamed.\n")
|
||||
file(APPEND ${OUTPUT} " */\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifdef _MSC_VER\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifndef DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
|
||||
file(APPEND ${OUTPUT} "#define DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifndef WIN32_LEAN_AND_MEAN\n")
|
||||
file(APPEND ${OUTPUT} "#define WIN32_LEAN_AND_MEAN\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#include <windows.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <Shlwapi.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <delayimp.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <string.h>\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) {\n")
|
||||
file(APPEND ${OUTPUT} " if (event != dliNotePreLoadLibrary) return NULL;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " if (_stricmp(info->szDll, \"iojs.exe\") != 0 &&\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.exe\") != 0 &&\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.dll\") != 0)\n")
|
||||
file(APPEND ${OUTPUT} " return NULL;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get a handle to the current process executable.\n")
|
||||
file(APPEND ${OUTPUT} " HMODULE processModule = GetModuleHandle(NULL);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get the path to the executable.\n")
|
||||
file(APPEND ${OUTPUT} " TCHAR processPath[_MAX_PATH];\n")
|
||||
file(APPEND ${OUTPUT} " GetModuleFileName(processModule, processPath, _MAX_PATH);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get the name of the current executable.\n")
|
||||
file(APPEND ${OUTPUT} " LPSTR processName = PathFindFileName(processPath);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // If the current process is node or iojs, then just return the proccess \n")
|
||||
file(APPEND ${OUTPUT} " // module.\n")
|
||||
file(APPEND ${OUTPUT} " if (_stricmp(processName, \"node.exe\") == 0 ||\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(processName, \"iojs.exe\") == 0) {\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
|
||||
file(APPEND ${OUTPUT} " }\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // If it is another process, attempt to load 'node.dll' from the same \n")
|
||||
file(APPEND ${OUTPUT} " // directory.\n")
|
||||
file(APPEND ${OUTPUT} " PathRemoveFileSpec(processPath);\n")
|
||||
file(APPEND ${OUTPUT} " PathAppend(processPath, \"node.dll\");\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " HMODULE nodeDllModule = GetModuleHandle(processPath);\n")
|
||||
file(APPEND ${OUTPUT} " if(nodeDllModule != NULL) {\n")
|
||||
file(APPEND ${OUTPUT} " // This application has a node.dll in the same directory as the executable,\n")
|
||||
file(APPEND ${OUTPUT} " // use that.\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) nodeDllModule;\n")
|
||||
file(APPEND ${OUTPUT} " }\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Fallback to the current executable, which must statically link to \n")
|
||||
file(APPEND ${OUTPUT} " // node.lib\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
|
||||
file(APPEND ${OUTPUT} "}\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "PfnDliHook __pfnDliNotifyHook2 = load_exe_hook;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
endfunction()
|
||||
|
||||
# Sets up a project to build Node.js native modules
|
||||
# - Downloads required dependencies and unpacks them to the build directory.
|
||||
# Internet access is required the first invocation but not after (
|
||||
# provided the download is successful)
|
||||
# - Sets up several variables for building against the downloaded
|
||||
# dependencies
|
||||
# - Guarded to prevent multiple executions, so a single project hierarchy
|
||||
# will only call this once
|
||||
function(nodejs_init)
|
||||
# Prevents this function from executing more than once
|
||||
if(NODEJS_INIT)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Regex patterns used by the init function for component extraction
|
||||
set(HEADERS_MATCH "^([A-Fa-f0-9]+)[ \t]+([^-]+)-(headers|v?[0-9.]+)-(headers|v?[0-9.]+)([.]tar[.]gz)$")
|
||||
set(LIB32_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-x86)?(/)?([^/]*)(.lib)$")
|
||||
set(LIB64_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-)?(x64/)(.*)(.lib)$")
|
||||
|
||||
# Parse function arguments
|
||||
cmake_parse_arguments(nodejs_init
|
||||
"" "URL;NAME;VERSION;CHECKSUM;CHECKTYPE" "" ${ARGN}
|
||||
)
|
||||
|
||||
# Allow the download URL to be overridden by command line argument
|
||||
# NODEJS_URL
|
||||
if(NODEJS_URL)
|
||||
set(URL ${NODEJS_URL})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(URL ${NODEJS_DEFAULT_URL})
|
||||
if(nodejs_init_URL)
|
||||
set(URL ${nodejs_init_URL})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow name to be overridden by command line argument NODEJS_NAME
|
||||
if(NODEJS_NAME)
|
||||
set(NAME ${NODEJS_NAME})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(NAME ${NODEJS_DEFAULT_NAME})
|
||||
if(nodejs_init_NAME)
|
||||
set(NAME ${nodejs_init_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the checksum file to be overridden by command line argument
|
||||
# NODEJS_CHECKSUM
|
||||
if(NODEJS_CHECKSUM)
|
||||
set(CHECKSUM ${NODEJS_CHECKSUM})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(CHECKSUM ${NODEJS_DEFAULT_CHECKSUM})
|
||||
if(nodejs_init_CHECKSUM)
|
||||
set(CHECKSUM ${nodejs_init_CHECKSUM})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the checksum type to be overriden by the command line argument
|
||||
# NODEJS_CHECKTYPE
|
||||
if(NODEJS_CHECKTYPE)
|
||||
set(CHECKTYPE ${NODEJS_CHECKTYPE})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(CHECKTYPE ${NODEJS_DEFAULT_CHECKTYPE})
|
||||
if(nodejs_init_CHECKTYPE)
|
||||
set(CHECKTYPE ${nodejs_init_CHECKTYPE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the version to be overridden by the command line argument
|
||||
# NODEJS_VERSION
|
||||
if(NODEJS_VERSION)
|
||||
set(VERSION ${NODEJS_VERSION})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(VERSION ${NODEJS_DEFAULT_VERSION})
|
||||
if(nodejs_init_VERSION)
|
||||
set(VERSION ${nodejs_init_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# "installed" is a special version that tries to use the currently
|
||||
# installed version (determined by running node)
|
||||
set(NODEJS_INSTALLED False CACHE BOOL "Node.js install status" FORCE)
|
||||
if(VERSION STREQUAL "installed")
|
||||
if(NOT NAME STREQUAL ${NODEJS_DEFAULT_NAME})
|
||||
message(FATAL_ERROR
|
||||
"'Installed' version identifier can only be used with"
|
||||
"the core Node.js library"
|
||||
)
|
||||
endif()
|
||||
# Fall back to the "latest" version if node isn't installed
|
||||
set(VERSION ${NODEJS_VERSION_FALLBACK})
|
||||
find_program(NODEJS_BINARY NAMES node nodejs)
|
||||
if(NODEJS_BINARY)
|
||||
execute_process(
|
||||
COMMAND ${NODEJS_BINARY} --version
|
||||
RESULT_VARIABLE INSTALLED_VERSION_RESULT
|
||||
OUTPUT_VARIABLE INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(INSTALLED_VERSION_RESULT STREQUAL "0")
|
||||
set(NODEJS_INSTALLED True CACHE BOOL
|
||||
"Node.js install status" FORCE
|
||||
)
|
||||
set(VERSION ${INSTALLED_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create a temporary download directory
|
||||
set(TEMP ${CMAKE_CURRENT_BINARY_DIR}/temp)
|
||||
if(EXISTS ${TEMP})
|
||||
file(REMOVE_RECURSE ${TEMP})
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${TEMP})
|
||||
|
||||
# Unless the target is special version "latest", the parameters
|
||||
# necessary to construct the root path are known
|
||||
if(NOT VERSION STREQUAL "latest")
|
||||
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
|
||||
# Extract checksums from the existing checksum file
|
||||
set(CHECKSUM_TARGET ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# If we're trying to determine the version or we haven't saved the
|
||||
# checksum file for this version, download it from the specified server
|
||||
if(VERSION STREQUAL "latest" OR
|
||||
(DEFINED ROOT AND NOT EXISTS ${ROOT}/CHECKSUM))
|
||||
if(DEFINED ROOT)
|
||||
# Clear away the old checksum in case the new one is different
|
||||
# and/or it fails to download
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
download_file(
|
||||
${URL}/${VERSION}/${CHECKSUM}
|
||||
${TEMP}/CHECKSUM
|
||||
INACTIVITY_TIMEOUT 10
|
||||
STATUS CHECKSUM_STATUS
|
||||
)
|
||||
list(GET CHECKSUM_STATUS 0 CHECKSUM_STATUS)
|
||||
if(CHECKSUM_STATUS GREATER 0)
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download checksum file"
|
||||
)
|
||||
endif()
|
||||
# Extract checksums from the temporary file
|
||||
set(CHECKSUM_TARGET ${TEMP}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# Extract the version, name, header archive and archive checksum
|
||||
# from the file. This first extract is what defines / specifies the
|
||||
# actual version number and name.
|
||||
file(STRINGS
|
||||
${CHECKSUM_TARGET} HEADERS_CHECKSUM
|
||||
REGEX ${HEADERS_MATCH}
|
||||
LIMIT_COUNT 1
|
||||
)
|
||||
if(NOT HEADERS_CHECKSUM)
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
if(DEFINED ROOT)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
message(FATAL_ERROR "Unable to extract header archive checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${HEADERS_MATCH} HEADERS_CHECKSUM ${HEADERS_CHECKSUM})
|
||||
set(HEADERS_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(NAME ${CMAKE_MATCH_2})
|
||||
if(CMAKE_MATCH_3 STREQUAL "headers")
|
||||
set(VERSION ${CMAKE_MATCH_4})
|
||||
else()
|
||||
set(VERSION ${CMAKE_MATCH_3})
|
||||
endif()
|
||||
set(HEADERS_ARCHIVE
|
||||
${CMAKE_MATCH_2}-${CMAKE_MATCH_3}-${CMAKE_MATCH_4}${CMAKE_MATCH_5}
|
||||
)
|
||||
# Make sure that the root directory exists, and that the checksum
|
||||
# file has been moved over from temp
|
||||
if(DEFINED ROOT)
|
||||
set(OLD_ROOT ${ROOT})
|
||||
endif()
|
||||
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
|
||||
if(DEFINED OLD_ROOT AND NOT ROOT STREQUAL "${OLD_ROOT}")
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
message(FATAL_ERROR "Version/Name mismatch")
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${ROOT})
|
||||
if(EXISTS ${TEMP}/CHECKSUM)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
file(RENAME ${TEMP}/CHECKSUM ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# Now that its fully resolved, report the name and version of Node.js being
|
||||
# used
|
||||
message(STATUS "NodeJS: Using ${NAME}, version ${VERSION}")
|
||||
|
||||
# Download the headers for the version being used
|
||||
# Theoretically, these could be found by searching the installed
|
||||
# system, but in practice, this can be error prone. They're provided
|
||||
# on the download servers, so just use the ones there.
|
||||
if(NOT EXISTS ${ROOT}/include)
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${HEADERS_ARCHIVE}
|
||||
${TEMP}/${HEADERS_ARCHIVE}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${HEADERS_CHECKSUM}
|
||||
STATUS HEADERS_STATUS
|
||||
)
|
||||
list(GET HEADERS_STATUS 0 HEADERS_STATUS)
|
||||
if(HEADER_STATUS GREATER 0)
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
message(FATAL_ERROR "Unable to download Node.js headers")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xfz ${TEMP}/${HEADERS_ARCHIVE}
|
||||
WORKING_DIRECTORY ${TEMP}
|
||||
)
|
||||
|
||||
# This adapts the header extraction to support a number of different
|
||||
# header archive contents in addition to the one used by the
|
||||
# default Node.js library
|
||||
unset(NODEJS_HEADERS_PATH CACHE)
|
||||
find_path(NODEJS_HEADERS_PATH
|
||||
NAMES src include
|
||||
PATHS
|
||||
${TEMP}/${NAME}-${VERSION}-headers
|
||||
${TEMP}/${NAME}-${VERSION}
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}-headers
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}
|
||||
${TEMP}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(NOT NODEJS_HEADERS_PATH)
|
||||
message(FATAL_ERROR "Unable to find extracted headers folder")
|
||||
endif()
|
||||
|
||||
# Move the headers into a standard location with a standard layout
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
if(EXISTS ${NODEJS_HEADERS_PATH}/include/node)
|
||||
file(RENAME ${NODEJS_HEADERS_PATH}/include/node ${ROOT}/include)
|
||||
elseif(EXISTS ${NODEJS_HEADERS_PATH}/src)
|
||||
file(MAKE_DIRECTORY ${ROOT}/include)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/src)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find core headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/src/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/uv/include)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find libuv headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/uv/include/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/v8/include)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find v8 headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/v8/include/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/zlib)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find zlib headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/zlib/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${NODEJS_HEADERS_PATH})
|
||||
unset(NODEJS_HEADERS_PATH CACHE)
|
||||
endif()
|
||||
|
||||
# Only download the libraries on windows, since its the only place
|
||||
# its necessary. Note, this requires rerunning CMake if moving
|
||||
# a module from one platform to another (should happen automatically
|
||||
# with most generators)
|
||||
if(WIN32)
|
||||
# Download the win32 library for linking
|
||||
file(STRINGS
|
||||
${ROOT}/CHECKSUM LIB32_CHECKSUM
|
||||
LIMIT_COUNT 1
|
||||
REGEX ${LIB32_MATCH}
|
||||
)
|
||||
if(NOT LIB32_CHECKSUM)
|
||||
message(FATAL_ERROR "Unable to extract x86 library checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${LIB32_MATCH} LIB32_CHECKSUM ${LIB32_CHECKSUM})
|
||||
set(LIB32_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(LIB32_PATH win-x86)
|
||||
set(LIB32_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
|
||||
set(LIB32_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB32_NAME})
|
||||
if(NOT EXISTS ${ROOT}/${LIB32_PATH})
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${LIB32_TARGET}
|
||||
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${LIB32_CHECKSUM}
|
||||
STATUS LIB32_STATUS
|
||||
)
|
||||
list(GET LIB32_STATUS 0 LIB32_STATUS)
|
||||
if(LIB32_STATUS GREATER 0)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download Node.js windows library (32-bit)"
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${ROOT}/${LIB32_PATH})
|
||||
file(MAKE_DIRECTORY ${ROOT}/${LIB32_PATH})
|
||||
file(RENAME
|
||||
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
|
||||
${ROOT}/${LIB32_PATH}/${LIB32_NAME}
|
||||
)
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
|
||||
endif()
|
||||
|
||||
# Download the win64 library for linking
|
||||
file(STRINGS
|
||||
${ROOT}/CHECKSUM LIB64_CHECKSUM
|
||||
LIMIT_COUNT 1
|
||||
REGEX ${LIB64_MATCH}
|
||||
)
|
||||
if(NOT LIB64_CHECKSUM)
|
||||
message(FATAL_ERROR "Unable to extract x64 library checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${LIB64_MATCH} LIB64_CHECKSUM ${LIB64_CHECKSUM})
|
||||
set(LIB64_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(LIB64_PATH win-x64)
|
||||
set(LIB64_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
|
||||
set(LIB64_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB64_NAME})
|
||||
if(NOT EXISTS ${ROOT}/${LIB64_PATH})
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${LIB64_TARGET}
|
||||
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${LIB64_CHECKSUM}
|
||||
STATUS LIB64_STATUS
|
||||
)
|
||||
list(GET LIB64_STATUS 0 LIB64_STATUS)
|
||||
if(LIB64_STATUS GREATER 0)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download Node.js windows library (64-bit)"
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${ROOT}/${LIB64_PATH})
|
||||
file(MAKE_DIRECTORY ${ROOT}/${LIB64_PATH})
|
||||
file(RENAME
|
||||
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
|
||||
${ROOT}/${LIB64_PATH}/${LIB64_NAME}
|
||||
)
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The downloaded headers should always be set for inclusion
|
||||
list(APPEND INCLUDE_DIRS ${ROOT}/include)
|
||||
|
||||
# Look for the NAN module, and add it to the includes
|
||||
find_nodejs_module(
|
||||
nan
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
NODEJS_NAN_DIR
|
||||
)
|
||||
if(NODEJS_NAN_DIR)
|
||||
list(APPEND INCLUDE_DIRS ${NODEJS_NAN_DIR})
|
||||
endif()
|
||||
|
||||
# Under windows, we need a bunch of libraries (due to the way
|
||||
# dynamic linking works)
|
||||
if(WIN32)
|
||||
# Generate and use a delay load hook to allow the node binary
|
||||
# name to be changed while still loading native modules
|
||||
set(DELAY_LOAD_HOOK ${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c)
|
||||
nodejs_generate_delayload_hook(${DELAY_LOAD_HOOK})
|
||||
set(SOURCES ${DELAY_LOAD_HOOK})
|
||||
|
||||
# Necessary flags to get delayload working correctly
|
||||
list(APPEND LINK_FLAGS
|
||||
"-IGNORE:4199"
|
||||
"-DELAYLOAD:iojs.exe"
|
||||
"-DELAYLOAD:node.exe"
|
||||
"-DELAYLOAD:node.dll"
|
||||
)
|
||||
|
||||
# Core system libraries used by node
|
||||
list(APPEND LIBRARIES
|
||||
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
|
||||
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
|
||||
odbc32.lib Shlwapi.lib DelayImp.lib
|
||||
)
|
||||
|
||||
# Also link to the node stub itself (downloaded above)
|
||||
if(CMAKE_CL_64)
|
||||
list(APPEND LIBRARIES ${ROOT}/${LIB64_PATH}/${LIB64_NAME})
|
||||
else()
|
||||
list(APPEND LIBRARIES ${ROOT}/${LIB32_PATH}/${LIB32_NAME})
|
||||
endif()
|
||||
else()
|
||||
# Non-windows platforms should use these flags
|
||||
list(APPEND DEFINITIONS _LARGEFILE_SOURCE _FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
||||
# Special handling for OSX / clang to allow undefined symbols
|
||||
# Define is required by node on OSX
|
||||
if(APPLE)
|
||||
list(APPEND LINK_FLAGS "-undefined dynamic_lookup")
|
||||
list(APPEND DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
|
||||
endif()
|
||||
|
||||
# Export all settings for use as arguments in the rest of the build
|
||||
set(NODEJS_VERSION ${VERSION} PARENT_SCOPE)
|
||||
set(NODEJS_SOURCES ${SOURCES} PARENT_SCOPE)
|
||||
set(NODEJS_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
|
||||
set(NODEJS_LIBRARIES ${LIBRARIES} PARENT_SCOPE)
|
||||
set(NODEJS_LINK_FLAGS ${LINK_FLAGS} PARENT_SCOPE)
|
||||
set(NODEJS_DEFINITIONS ${DEFINITIONS} PARENT_SCOPE)
|
||||
|
||||
# Prevents this function from executing more than once
|
||||
set(NODEJS_INIT TRUE PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Helper function for defining a node module
|
||||
# After nodejs_init, all of the settings and dependencies necessary to do
|
||||
# this yourself are defined, but this helps make sure everything is configured
|
||||
# correctly. Feel free to use it as a model to do this by hand (or to
|
||||
# tweak this configuration if you need something custom).
|
||||
function(add_nodejs_module NAME)
|
||||
# Validate name parameter (must be a valid C identifier)
|
||||
string(MAKE_C_IDENTIFIER ${NAME} ${NAME}_SYMBOL_CHECK)
|
||||
if(NOT "${NAME}" STREQUAL "${${NAME}_SYMBOL_CHECK}")
|
||||
message(FATAL_ERROR
|
||||
"Module name must be a valid C identifier. "
|
||||
"Suggested alternative: '${${NAME}_SYMBOL_CHECK}'"
|
||||
)
|
||||
endif()
|
||||
# Make sure node is initialized (variables set) before defining the module
|
||||
if(NOT NODEJS_INIT)
|
||||
message(FATAL_ERROR
|
||||
"Node.js has not been initialized. "
|
||||
"Call nodejs_init before adding any modules"
|
||||
)
|
||||
endif()
|
||||
# In order to match node-gyp, we need to build into type specific folders
|
||||
# ncmake takes care of this, but be sure to set CMAKE_BUILD_TYPE yourself
|
||||
# if invoking CMake directly
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
||||
message(FATAL_ERROR
|
||||
"Configuration type must be specified. "
|
||||
"Set CMAKE_BUILD_TYPE or use a different generator"
|
||||
)
|
||||
endif()
|
||||
|
||||
# A node module is a shared library
|
||||
add_library(${NAME} SHARED ${NODEJS_SOURCES} ${ARGN})
|
||||
# Add compiler defines for the module
|
||||
# Two helpful ones:
|
||||
# MODULE_NAME must match the name of the build library, define that here
|
||||
# ${NAME}_BUILD is for symbol visibility under windows
|
||||
string(TOUPPER "${NAME}_BUILD" ${NAME}_BUILD_DEF)
|
||||
target_compile_definitions(${NAME}
|
||||
PRIVATE MODULE_NAME=${NAME}
|
||||
PRIVATE ${${NAME}_BUILD_DEF}
|
||||
PUBLIC ${NODEJS_DEFINITIONS}
|
||||
)
|
||||
# This properly defines includes for the module
|
||||
target_include_directories(${NAME} PUBLIC ${NODEJS_INCLUDE_DIRS})
|
||||
|
||||
# Add link flags to the module
|
||||
target_link_libraries(${NAME} ${NODEJS_LIBRARIES})
|
||||
|
||||
# Set required properties for the module to build properly
|
||||
# Correct naming, symbol visiblity and C++ standard
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
OUTPUT_NAME ${NAME}
|
||||
PREFIX ""
|
||||
SUFFIX ".node"
|
||||
MACOSX_RPATH ON
|
||||
C_VISIBILITY_PRESET hidden
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
CMAKE_CXX_STANDARD_REQUIRED TRUE
|
||||
CXX_STANDARD 11
|
||||
LINK_FLAGS "${NODEJS_LINK_FLAGS}"
|
||||
)
|
||||
|
||||
# Make sure we're buiilding in a build specific output directory
|
||||
# Only necessary on single-target generators (Make, Ninja)
|
||||
# Multi-target generators do this automatically
|
||||
# This (luckily) mirrors node-gyp conventions
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(TARGET ${NAME} PROPERTY
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,587 +0,0 @@
|
||||
# Copyright (c) 2015, Colin Taylor
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# FindNodeJS.cmake CMake module vendored from the node-cmake project (v1.2).
|
||||
|
||||
# This script uses CMake 3.1+ features
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0)
|
||||
message(FATAL_ERROR "FindNodeJS.cmake uses CMake 3.1+ features")
|
||||
endif()
|
||||
|
||||
# Force a build type to be set (ignored on config based generators)
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
|
||||
endif()
|
||||
|
||||
# Capture module information
|
||||
set(NodeJS_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
get_filename_component(NodeJS_MODULE_NAME ${NodeJS_MODULE_PATH} NAME)
|
||||
|
||||
# Allow users to specify the installed location of the Node.js package
|
||||
set(NodeJS_ROOT_DIR "" CACHE PATH
|
||||
"The root directory of the node.js installed package")
|
||||
|
||||
# Allow users to specify that downloaded sources should be used
|
||||
option(NodeJS_DOWNLOAD "Download the required source files" Off)
|
||||
|
||||
# Allow users to force downloading of node packages
|
||||
option(NodeJS_FORCE_DOWNLOAD "Download the source files every time" Off)
|
||||
|
||||
# Allow users to force archive extraction
|
||||
option(NodeJS_FORCE_EXTRACT "Extract the archive every time" Off)
|
||||
|
||||
# Make libc++ the default when compiling with clang
|
||||
option(NodeJS_USE_CLANG_STDLIB "Use libc++ when compiling with clang" On)
|
||||
if(APPLE)
|
||||
set(NodeJS_USE_CLANG_STDLIB On CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# Allow users to specify that the executable should be downloaded
|
||||
option(NodeJS_DOWNLOAD_EXECUTABLE
|
||||
"Download matching executable if available" Off
|
||||
)
|
||||
endif()
|
||||
|
||||
# Try to find the node.js executable
|
||||
# The node executable under linux may not be the correct program
|
||||
find_program(NodeJS_EXECUTABLE
|
||||
NAMES node
|
||||
PATHS ${NodeJS_ROOT_DIR}
|
||||
PATH_SUFFIXES nodejs node
|
||||
)
|
||||
set(NodeJS_VALIDATE_EXECUTABLE 1)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} --version
|
||||
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} -p "process.platform"
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_PLATFORM
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} -p "process.arch"
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_ARCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
# If node isn't the node.js binary, try the nodejs binary
|
||||
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
|
||||
find_program(NodeJS_EXECUTABLE
|
||||
NAMES nodejs
|
||||
PATHS ${NodeJS_ROOT_DIR}
|
||||
PATH_SUFFIXES nodejs node
|
||||
)
|
||||
set(NodeJS_VALIDATE_EXECUTABLE 1)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} --version
|
||||
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
|
||||
message(WARNING "Node.js executable could not be found. \
|
||||
Set NodeJS_ROOT_DIR to the installed location of the executable or \
|
||||
install Node.js to its default location.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Determine if a variant is set in the components
|
||||
list(APPEND NodeJS_OTHER_COMPONENTS
|
||||
X64 IA32 ARM WIN32 LINUX DARWIN
|
||||
)
|
||||
set(NodeJS_COMPONENTS_CONTAINS_VARIANT False)
|
||||
foreach(NodeJS_COMPONENT ${NodeJS_FIND_COMPONENTS})
|
||||
list(FIND NodeJS_OTHER_COMPONENTS ${NodeJS_COMPONENT} NodeJS_OTHER_INDEX)
|
||||
if(NodeJS_OTHER_INDEX EQUAL -1)
|
||||
set(NodeJS_COMPONENTS_CONTAINS_VARIANT True)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Get the targeted version of Node.js (or one of its derivatives)
|
||||
if(NOT NodeJS_VERSION)
|
||||
if(NodeJS_FIND_VERSION)
|
||||
set(NodeJS_VERSION ${NodeJS_FIND_VERSION})
|
||||
elseif(NodeJS_INSTALLED_VERSION AND NOT NodeJS_COMPONENTS_CONTAINS_VARIANT)
|
||||
string(SUBSTRING ${NodeJS_INSTALLED_VERSION} 1 -1 NodeJS_VERSION)
|
||||
else()
|
||||
message(FATAL_ERROR "Node.js version is not set. Set the VERSION \
|
||||
property of the find_package command to the required version of the \
|
||||
Node.js sources")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Determine the target platform for the compiled module
|
||||
# Uses several mechanisms in order:
|
||||
#
|
||||
# 1. CMake cache (allows overriding on the command line)
|
||||
# 2. Node architecture when binary is available
|
||||
# 3. CMake architecture
|
||||
#
|
||||
set(NodeJS_PLATFORM "" CACHE STRING "Target node.js platform for module")
|
||||
if(NOT NodeJS_PLATFORM)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
set(NodeJS_PLATFORM ${NodeJS_INSTALLED_PLATFORM})
|
||||
elseif(WIN32)
|
||||
set(NodeJS_PLATFORM "win32")
|
||||
elseif(UNIX)
|
||||
if(APPLE)
|
||||
set(NodeJS_PLATFORM "darwin")
|
||||
else()
|
||||
set(NodeJS_PLATFORM "linux")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Node.js platform is not set. Add the platform \
|
||||
to the find_package components section or set NodeJS_PLATFORM in the \
|
||||
cache.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Convenience variables for the platform type
|
||||
if(NodeJS_PLATFORM STREQUAL "win32")
|
||||
set(NodeJS_PLATFORM_WIN32 True)
|
||||
set(NodeJS_PLATFORM_LINUX False)
|
||||
set(NodeJS_PLATFORM_DARWIN False)
|
||||
elseif(NodeJS_PLATFORM STREQUAL "linux")
|
||||
set(NodeJS_PLATFORM_WIN32 False)
|
||||
set(NodeJS_PLATFORM_LINUX True)
|
||||
set(NodeJS_PLATFORM_DARWIN False)
|
||||
elseif(NodeJS_PLATFORM STREQUAL "darwin")
|
||||
set(NodeJS_PLATFORM_WIN32 False)
|
||||
set(NodeJS_PLATFORM_LINUX False)
|
||||
set(NodeJS_PLATFORM_DARWIN True)
|
||||
endif()
|
||||
|
||||
# Determine the target architecture for the compiled module
|
||||
# Uses several mechanisms in order:
|
||||
#
|
||||
# 1. CMake cache (allows overriding on the command line)
|
||||
# 2. Node architecture when binary is available
|
||||
# 3. Compiler architecture under MSVC
|
||||
#
|
||||
set(NodeJS_ARCH "" CACHE STRING "Target node.js architecture for module")
|
||||
if(NOT NodeJS_ARCH)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
set(NodeJS_ARCH ${NodeJS_INSTALLED_ARCH})
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(NodeJS_ARCH "x64")
|
||||
else()
|
||||
set(NodeJS_ARCH "ia32")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Node.js architecture is not set. Add the \
|
||||
architecture to the find_package components section or set NodeJS_ARCH \
|
||||
in the cache.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Convenience variables for the architecture
|
||||
if(NodeJS_ARCH STREQUAL "x64")
|
||||
set(NodeJS_ARCH_X64 True)
|
||||
set(NodeJS_ARCH_IA32 False)
|
||||
set(NodeJS_ARCH_ARM False)
|
||||
elseif(NodeJS_ARCH STREQUAL "ia32")
|
||||
set(NodeJS_ARCH_X64 False)
|
||||
set(NodeJS_ARCH_IA32 True)
|
||||
set(NodeJS_ARCH_ARM False)
|
||||
elseif(NodeJS_ARCH STREQUAL "arm")
|
||||
set(NodeJS_ARCH_X64 False)
|
||||
set(NodeJS_ARCH_IA32 False)
|
||||
set(NodeJS_ARCH_ARM True)
|
||||
endif()
|
||||
|
||||
# Include helper functions
|
||||
include(util/NodeJSUtil)
|
||||
|
||||
# Default variant name
|
||||
# Used by the installed header comparison below
|
||||
set(NodeJS_DEFAULT_VARIANT_NAME "node.js")
|
||||
|
||||
# Variables for Node.js artifacts across variants
|
||||
# Specify all of these variables for each new variant
|
||||
set(NodeJS_VARIANT_NAME "") # The printable name of the variant
|
||||
set(NodeJS_VARIANT_BASE "") # A file name safe version of the variant
|
||||
set(NodeJS_URL "") # The URL for the artifacts
|
||||
set(NodeJS_SOURCE_PATH "") # The URL path of the source archive
|
||||
set(NodeJS_CHECKSUM_PATH "") # The URL path of the checksum file
|
||||
set(NodeJS_CHECKSUM_TYPE "") # The checksum type (algorithm)
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "") # The URL path of the windows library
|
||||
set(NodeJS_WIN32_BINARY_PATH "") # The URL path of the windows executable
|
||||
set(NodeJS_WIN32_LIBRARY_NAME "") # The name of the windows library
|
||||
set(NodeJS_WIN32_BINARY_NAME "") # The name of the windows executable
|
||||
|
||||
set(NodeJS_DEFAULT_INCLUDE True) # Enable default include behavior
|
||||
set(NodeJS_DEFAULT_LIBS True) # Include the default libraries
|
||||
set(NodeJS_HAS_WIN32_PREFIX True) # Does the variant use library prefixes
|
||||
set(NodeJS_HAS_WIN32_BINARY True) # Does the variant have win32 executables
|
||||
set(NodeJS_HAS_OPENSSL True) # Does the variant include openssl headers
|
||||
set(NodeJS_HEADER_VERSION 0.12.7) # Version after header-only archives start
|
||||
set(NodeJS_SHA256_VERSION 0.7.0) # Version after sha256 checksums start
|
||||
set(NodeJS_PREFIX_VERSION 0.12.7) # Version after windows prefixing starts
|
||||
set(NodeJS_CXX11R_VERSION 0.12.7) # Version after c++11 is required
|
||||
set(NodeJS_SOURCE_INCLUDE True) # Use the include paths from a source archive
|
||||
set(NodeJS_HEADER_INCLUDE False) # Use the include paths from a header archive
|
||||
set(NodeJS_INCLUDE_PATHS "") # Set of header dirs inside the source archive
|
||||
set(NodeJS_LIBRARIES "") # The set of libraries to link with addon
|
||||
set(NodeJS_WIN32_DELAYLOAD "") # Set of executables to delayload on windows
|
||||
|
||||
# NodeJS variants
|
||||
# Selects download target based on configured component
|
||||
# Include NodeJS last to provide default configurations when omitted
|
||||
file(
|
||||
GLOB NodeJS_SUPPORTED_VARIANTS
|
||||
RELATIVE ${CMAKE_CURRENT_LIST_DIR}/variants
|
||||
${CMAKE_CURRENT_LIST_DIR}/variants/*
|
||||
)
|
||||
foreach(NodeJS_SUPPORTED_VARIANT ${NodeJS_SUPPORTED_VARIANTS})
|
||||
get_filename_component(NodeJS_SUPPORTED_VARIANT_NAME
|
||||
${NodeJS_SUPPORTED_VARIANT} NAME_WE
|
||||
)
|
||||
if(NOT NodeJS_SUPPORTED_VARIANT_NAME STREQUAL "NodeJS")
|
||||
include(variants/${NodeJS_SUPPORTED_VARIANT_NAME})
|
||||
endif()
|
||||
endforeach()
|
||||
include(variants/NodeJS)
|
||||
|
||||
# Populate version variables, including version components
|
||||
set(NodeJS_VERSION_STRING "v${NodeJS_VERSION}")
|
||||
|
||||
# Populate the remaining version variables
|
||||
string(REPLACE "." ";" NodeJS_VERSION_PARTS ${NodeJS_VERSION})
|
||||
list(GET NodeJS_VERSION_PARTS 0 NodeJS_VERSION_MAJOR)
|
||||
list(GET NodeJS_VERSION_PARTS 1 NodeJS_VERSION_MINOR)
|
||||
list(GET NodeJS_VERSION_PARTS 2 NodeJS_VERSION_PATCH)
|
||||
|
||||
# If the version we're looking for is the version that is installed,
|
||||
# try finding the required headers. Don't do this under windows (where
|
||||
# headers are not part of the installed content), when the user has
|
||||
# specified that headers should be downloaded or when using a variant other
|
||||
# than the default
|
||||
if((NOT NodeJS_PLATFORM_WIN32) AND (NOT NodeJS_DOWNLOAD) AND
|
||||
NodeJS_VARIANT_NAME STREQUAL NodeJS_DEFAULT_VARIANT_NAME AND
|
||||
NodeJS_INSTALLED_VERSION STREQUAL NodeJS_VERSION_STRING AND
|
||||
NodeJS_INSTALLED_PLATFORM STREQUAL NodeJS_PLATFORM AND
|
||||
NodeJS_INSTALLED_ARCH STREQUAL NodeJS_ARCH)
|
||||
# node.h is really generic and too easy for cmake to find the wrong
|
||||
# file, so use the directory as a guard, and then just tack it on to
|
||||
# the actual path
|
||||
#
|
||||
# Specifically ran into this under OSX, where python contains a node.h
|
||||
# that gets found instead
|
||||
find_path(NodeJS_INCLUDE_PARENT node/node.h)
|
||||
set(NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_PARENT}/node)
|
||||
|
||||
# Under all systems that support this, there are no libraries required
|
||||
# for linking (symbols are resolved via the main executable at runtime)
|
||||
set(NodeJS_LIBRARIES "")
|
||||
|
||||
# Otherwise, headers and required libraries must be downloaded to the project
|
||||
# to supplement what is installed
|
||||
else()
|
||||
# Create a folder for downloaded artifacts
|
||||
set(NodeJS_DOWNLOAD_PATH
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${NodeJS_VARIANT_BASE}
|
||||
)
|
||||
set(NodeJS_DOWNLOAD_PATH ${NodeJS_DOWNLOAD_PATH}-${NodeJS_VERSION_STRING})
|
||||
file(MAKE_DIRECTORY ${NodeJS_DOWNLOAD_PATH})
|
||||
|
||||
# Download the checksum file for validating all other downloads
|
||||
# Conveniently, if this doesn't download correctly, the setup fails
|
||||
# due to checksum failures
|
||||
set(NodeJS_CHECKSUM_FILE ${NodeJS_DOWNLOAD_PATH}/CHECKSUM)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_CHECKSUM_PATH}
|
||||
${NodeJS_CHECKSUM_FILE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
file(READ ${NodeJS_CHECKSUM_FILE} NodeJS_CHECKSUM_DATA)
|
||||
|
||||
# Download and extract the main source archive
|
||||
set(NodeJS_SOURCE_FILE ${NodeJS_DOWNLOAD_PATH}/headers.tar.gz)
|
||||
nodejs_checksum(
|
||||
${NodeJS_CHECKSUM_DATA} ${NodeJS_SOURCE_PATH} NodeJS_SOURCE_CHECKSUM
|
||||
)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_SOURCE_PATH}
|
||||
${NodeJS_SOURCE_FILE}
|
||||
${NodeJS_SOURCE_CHECKSUM}
|
||||
${NodeJS_CHECKSUM_TYPE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
set(NodeJS_HEADER_PATH ${NodeJS_DOWNLOAD_PATH}/src)
|
||||
nodejs_extract(
|
||||
${NodeJS_SOURCE_FILE}
|
||||
${NodeJS_HEADER_PATH}
|
||||
${NodeJS_FORCE_EXTRACT}
|
||||
)
|
||||
|
||||
# Populate include directories from the extracted source archive
|
||||
foreach(NodeJS_HEADER_BASE ${NodeJS_INCLUDE_PATHS})
|
||||
set(NodeJS_INCLUDE_DIR ${NodeJS_HEADER_PATH}/${NodeJS_HEADER_BASE})
|
||||
if(NOT EXISTS ${NodeJS_INCLUDE_DIR})
|
||||
message(FATAL_ERROR "Include does not exist: ${NodeJS_INCLUDE_DIR}")
|
||||
endif()
|
||||
list(APPEND NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_DIR})
|
||||
endforeach()
|
||||
|
||||
# Download required library files when targeting windows
|
||||
if(NodeJS_PLATFORM_WIN32)
|
||||
# Download the windows library
|
||||
set(NodeJS_WIN32_LIBRARY_FILE
|
||||
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
|
||||
)
|
||||
set(NodeJS_WIN32_LIBRARY_FILE
|
||||
${NodeJS_WIN32_LIBRARY_FILE}/${NodeJS_WIN32_LIBRARY_NAME}
|
||||
)
|
||||
nodejs_checksum(
|
||||
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_LIBRARY_PATH}
|
||||
NodeJS_WIN32_LIBRARY_CHECKSUM
|
||||
)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_WIN32_LIBRARY_PATH}
|
||||
${NodeJS_WIN32_LIBRARY_FILE}
|
||||
${NodeJS_WIN32_LIBRARY_CHECKSUM}
|
||||
${NodeJS_CHECKSUM_TYPE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
list(APPEND NodeJS_LIBRARIES ${NodeJS_WIN32_LIBRARY_FILE})
|
||||
|
||||
# If provided, download the windows executable
|
||||
if(NodeJS_WIN32_BINARY_PATH AND
|
||||
NodeJS_DOWNLOAD_EXECUTABLE)
|
||||
set(NodeJS_WIN32_BINARY_FILE
|
||||
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
|
||||
)
|
||||
set(NodeJS_WIN32_BINARY_FILE
|
||||
${NodeJS_WIN32_BINARY_FILE}/${NodeJS_WIN32_BINARY_NAME}
|
||||
)
|
||||
nodejs_checksum(
|
||||
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_BINARY_PATH}
|
||||
NodeJS_WIN32_BINARY_CHECKSUM
|
||||
)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_WIN32_BINARY_PATH}
|
||||
${NodeJS_WIN32_BINARY_FILE}
|
||||
${NodeJS_WIN32_BINARY_CHECKSUM}
|
||||
${NodeJS_CHECKSUM_TYPE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Support windows delay loading
|
||||
if(NodeJS_PLATFORM_WIN32)
|
||||
list(APPEND NodeJS_LINK_FLAGS /IGNORE:4199)
|
||||
set(NodeJS_WIN32_DELAYLOAD_CONDITION "")
|
||||
foreach(NodeJS_WIN32_DELAYLOAD_BINARY ${NodeJS_WIN32_DELAYLOAD})
|
||||
list(APPEND NodeJS_LINK_FLAGS
|
||||
/DELAYLOAD:${NodeJS_WIN32_DELAYLOAD_BINARY}
|
||||
)
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD_CONDITION
|
||||
"_stricmp(info->szDll, \"${NodeJS_WIN32_DELAYLOAD_BINARY}\") != 0"
|
||||
)
|
||||
endforeach()
|
||||
string(REPLACE ";" " &&\n "
|
||||
NodeJS_WIN32_DELAYLOAD_CONDITION
|
||||
"${NodeJS_WIN32_DELAYLOAD_CONDITION}"
|
||||
)
|
||||
configure_file(
|
||||
${NodeJS_MODULE_PATH}/src/win_delay_load_hook.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c @ONLY
|
||||
)
|
||||
list(APPEND NodeJS_ADDITIONAL_SOURCES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# Allow undefined symbols on OSX
|
||||
if(NodeJS_PLATFORM_DARWIN)
|
||||
list(APPEND NodeJS_LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif()
|
||||
|
||||
# Use libc++ when clang is the compiler by default
|
||||
if(NodeJS_USE_CLANG_STDLIB AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*")
|
||||
list(APPEND NodeJS_COMPILE_OPTIONS -stdlib=libc++)
|
||||
endif()
|
||||
|
||||
# Require c++11 support after a specific point, but only if the user hasn't
|
||||
# specified an override
|
||||
if(NOT NodeJS_CXX_STANDARD)
|
||||
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION)
|
||||
set(NodeJS_CXX_STANDARD 11)
|
||||
else()
|
||||
set(NodeJS_CXX_STANDARD 98)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set required definitions
|
||||
list(APPEND NodeJS_DEFINITIONS BUILDING_NODE_EXTENSION)
|
||||
if(NodeJS_PLATFORM_DARWIN)
|
||||
list(APPEND NodeJS_DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
|
||||
endif()
|
||||
if(NOT NodeJS_PLATFORM_WIN32)
|
||||
list(APPEND NodeJS_DEFINITIONS
|
||||
_LARGEFILE_SOURCE
|
||||
_FILE_OFFSET_BITS=64
|
||||
)
|
||||
endif()
|
||||
|
||||
function(add_nodejs_module NAME)
|
||||
# Build a shared library for the module
|
||||
add_library(${NAME} SHARED ${ARGN} ${NodeJS_ADDITIONAL_SOURCES})
|
||||
|
||||
# Include required headers
|
||||
# Find and include Nan as well (always available as its a
|
||||
# dependency of this module)
|
||||
nodejs_find_module_fallback(nan ${CMAKE_CURRENT_SOURCE_DIR} NAN_PATH)
|
||||
target_include_directories(${NAME}
|
||||
PUBLIC ${NodeJS_INCLUDE_DIRS}
|
||||
PUBLIC ${NAN_PATH}
|
||||
)
|
||||
|
||||
# Set module properties
|
||||
# This ensures proper naming of the module library across all platforms
|
||||
get_target_property(COMPILE_OPTIONS ${NAME} COMPILE_OPTIONS)
|
||||
if(NOT COMPILE_OPTIONS)
|
||||
set(COMPILE_OPTIONS "")
|
||||
endif()
|
||||
set(COMPILE_OPTIONS ${COMPILE_OPTIONS} ${NodeJS_COMPILE_OPTIONS})
|
||||
get_target_property(LINK_FLAGS ${NAME} LINK_FLAGS)
|
||||
if(NOT LINK_FLAGS)
|
||||
set(LINK_FLAGS "")
|
||||
endif()
|
||||
foreach(NodeJS_LINK_FLAG ${NodeJS_LINK_FLAGS})
|
||||
set(LINK_FLAGS "${LINK_FLAGS} ${NodeJS_LINK_FLAG}")
|
||||
endforeach()
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
PREFIX ""
|
||||
SUFFIX ".node"
|
||||
MACOSX_RPATH ON
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
COMPILE_OPTIONS "${COMPILE_OPTIONS}"
|
||||
LINK_FLAGS "${LINK_FLAGS}"
|
||||
CXX_STANDARD_REQUIRED TRUE
|
||||
CXX_STANDARD ${NodeJS_CXX_STANDARD}
|
||||
)
|
||||
|
||||
# Output the module in a per build type directory
|
||||
# This makes builds consistent with visual studio and other generators
|
||||
# that build by configuration
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(TARGET ${NAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY
|
||||
${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set any required complier flags
|
||||
# Mostly used under windows
|
||||
target_compile_definitions(${NAME} PRIVATE ${NodeJS_DEFINITIONS})
|
||||
|
||||
# Link against required NodeJS libraries
|
||||
target_link_libraries(${NAME} ${NodeJS_LIBRARIES})
|
||||
endfunction()
|
||||
|
||||
# Write out the configuration for node scripts
|
||||
configure_file(
|
||||
${NodeJS_MODULE_PATH}/build.json.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/build.json @ONLY
|
||||
)
|
||||
|
||||
# Make sure we haven't violated the version-to-standard mapping
|
||||
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION AND
|
||||
NodeJS_CXX_STANDARD EQUAL 98)
|
||||
message(FATAL_ERROR "${NodeJS_VARIANT_NAME} ${NodeJS_VERSION} \
|
||||
requires C++11 or newer to build")
|
||||
endif()
|
||||
|
||||
# This is a find_package file, handle the standard invocation
|
||||
include(FindPackageHandleStandardArgs)
|
||||
set(NodeJS_TARGET "${NodeJS_VARIANT_NAME} ${NodeJS_PLATFORM}/${NodeJS_ARCH}")
|
||||
find_package_handle_standard_args(NodeJS
|
||||
FOUND_VAR NodeJS_FOUND
|
||||
REQUIRED_VARS NodeJS_TARGET NodeJS_INCLUDE_DIRS
|
||||
VERSION_VAR NodeJS_VERSION
|
||||
)
|
||||
|
||||
# Mark variables that users shouldn't modify
|
||||
mark_as_advanced(
|
||||
NodeJS_VALIDATE_EXECUTABLE
|
||||
NodeJS_OTHER_COMPONENTS
|
||||
NodeJS_COMPONENTS_CONTAINS_VARIANT
|
||||
NodeJS_COMPONENT
|
||||
NodeJS_OTHER_INDEX
|
||||
NodeJS_VERSION_STRING
|
||||
NodeJS_VERSION_MAJOR
|
||||
NodeJS_VERSION_MINOR
|
||||
NodeJS_VERSION_PATCH
|
||||
NodeJS_VERSION_TWEAK
|
||||
NodeJS_PLATFORM
|
||||
NodeJS_PLATFORM_WIN32
|
||||
NodeJS_PLATFORM_LINUX
|
||||
NodeJS_PLATFORM_DARWIN
|
||||
NodeJS_ARCH
|
||||
NodeJS_ARCH_X64
|
||||
NodeJS_ARCH_IA32
|
||||
NodeJS_ARCH_ARM
|
||||
NodeJS_DEFAULT_VARIANT_NAME
|
||||
NodeJS_VARIANT_BASE
|
||||
NodeJS_VARIANT_NAME
|
||||
NodeJS_URL
|
||||
NodeJS_SOURCE_PATH
|
||||
NodeJS_CHECKSUM_PATH
|
||||
NodeJS_CHECKSUM_TYPE
|
||||
NodeJS_WIN32_LIBRARY_PATH
|
||||
NodeJS_WIN32_BINARY_PATH
|
||||
NodeJS_WIN32_LIBRARY_NAME
|
||||
NodeJS_WIN32_BINARY_NAME
|
||||
NodeJS_DEFAULT_INCLUDE
|
||||
NodeJS_DEFAULT_LIBS
|
||||
NodeJS_HAS_WIN32_BINARY
|
||||
NodeJS_HEADER_VERSION
|
||||
NodeJS_SHA256_VERISON
|
||||
NodeJS_PREFIX_VERSION
|
||||
NodeJS_SOURCE_INCLUDE
|
||||
NodeJS_HEADER_INCLUDE
|
||||
NodeJS_INCLUDE_PATHS
|
||||
NodeJS_WIN32_DELAYLOAD
|
||||
NodeJS_DOWNLOAD_PATH
|
||||
NodeJS_CHECKSUM_FILE
|
||||
NodeJS_CHECKSUM_DATA
|
||||
NodeJS_SOURCE_FILE
|
||||
NodeJS_SOURCE_CHECKSUM
|
||||
NodeJS_HEADER_PATH
|
||||
NodeJS_HEADER_BASE
|
||||
NodeJS_INCLUDE_DIR
|
||||
NodeJS_WIN32_LIBRARY_FILE
|
||||
NodeJS_WIN32_LIBRARY_CHECKSUM
|
||||
NodeJS_WIN32_BINARY_FILE
|
||||
NodeJS_WIN32_BINARY_CHECKSUM
|
||||
NodeJS_NAN_PATH
|
||||
NodeJS_LINK_FLAGS
|
||||
NodeJS_COMPILE_OPTIONS
|
||||
NodeJS_ADDITIONAL_SOURCES
|
||||
NodeJS_WIN32_DELAYLOAD_CONDITION
|
||||
NodeJS_WIN32_DELAYLOAD_BINARY
|
||||
NodeJS_TARGET
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"build_type": "@CMAKE_BUILD_TYPE@",
|
||||
"generator": "@CMAKE_GENERATOR@",
|
||||
"toolset": "@CMAKE_GENERATOR_TOOLSET@",
|
||||
"platform": "@CMAKE_GENERATOR_PLATFORM@",
|
||||
"variant": "@NodeJS_VARIANT_BASE@",
|
||||
"version": "@NodeJS_VERSION@",
|
||||
"download": "@NodeJS_DOWNLOAD@",
|
||||
"standard": "@NodeJS_CXX_STANDARD@"
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
set(GITHUB_API_TOKEN $ENV{GITHUB_API_TOKEN})
|
||||
|
||||
set(GITHUB_AUTH "")
|
||||
if(GITHUB_API_TOKEN)
|
||||
set(GITHUB_AUTH "?access_token=${GITHUB_API_TOKEN}")
|
||||
endif()
|
||||
|
||||
set(GITHUB_API_URL "https://api.github.com")
|
||||
|
||||
function(github_get_rate_limit VAR)
|
||||
set(RATE_LIMIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/GITHUBRATE)
|
||||
set(RATE_LIMIT_URL ${GITHUB_API_URL}/rate_limit${GITHUB_AUTH})
|
||||
nodejs_download(
|
||||
${RATE_LIMIT_URL}
|
||||
${RATE_LIMIT_FILE}
|
||||
ON
|
||||
)
|
||||
file(READ ${RATE_LIMIT_FILE} RATE_LIMIT_DATA)
|
||||
string(REGEX MATCH "\"remaining\": ([0-9]+),"
|
||||
RATE_LIMIT_MATCH ${RATE_LIMIT_DATA})
|
||||
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
mark_as_advanced(
|
||||
GITHUB_AUTH
|
||||
GITHUB_API_TOKEN
|
||||
GITHUB_API_URL
|
||||
)
|
||||
@@ -1,166 +0,0 @@
|
||||
function(nodejs_check_file FILE)
|
||||
set(MESSAGE "File ${FILE} does not exist or is empty")
|
||||
if(ARGC GREATER 1)
|
||||
set(MESSAGE ${ARGV1})
|
||||
endif()
|
||||
|
||||
# Make sure the file has contents
|
||||
file(READ ${FILE} FILE_CONTENT LIMIT 1 HEX)
|
||||
if(NOT FILE_CONTENT)
|
||||
file(REMOVE ${FILE})
|
||||
message(FATAL_ERROR ${MESSAGE})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(nodejs_download URL FILE)
|
||||
# Function optionally takes a checksum and a checksum type, and
|
||||
# a force value
|
||||
# Either can be specified without the other, but checksum must come first
|
||||
if(ARGC GREATER 2)
|
||||
set(CHECKSUM ${ARGV2})
|
||||
if(CHECKSUM STREQUAL "On" OR CHECKSUM STREQUAL "ON" OR
|
||||
CHECKSUM STREQUAL "True" OR CHECKSUM STREQUAL "TRUE" OR
|
||||
CHECKSUM STREQUAL "Off" OR CHECKSUM STREQUAL "OFF" OR
|
||||
CHECKSUM STREQUAL "False" OR CHECKSUM STREQUAL "FALSE")
|
||||
set(FORCE ${CHECKSUM})
|
||||
unset(CHECKSUM)
|
||||
elseif(ARGC GREATER 3)
|
||||
set(TYPE ${ARGV3})
|
||||
else()
|
||||
message(FATAL_ERROR "Checksum type must be specified")
|
||||
endif()
|
||||
elseif(ARGC GREATER 4)
|
||||
set(CHECKSUM ${ARGV2})
|
||||
set(TYPE ${ARGV3})
|
||||
set(FORCE ${ARGV4})
|
||||
endif()
|
||||
|
||||
# If the file exists, no need to download it again unless its being forced
|
||||
if(NOT FORCE AND EXISTS ${FILE})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Download the file
|
||||
message(STATUS "Downloading: ${URL}")
|
||||
file(DOWNLOAD
|
||||
${URL}
|
||||
${FILE}
|
||||
SHOW_PROGRESS
|
||||
)
|
||||
|
||||
# Make sure the file has contents
|
||||
nodejs_check_file(${FILE} "Unable to download ${URL}")
|
||||
|
||||
# If a checksum is provided, validate the downloaded file
|
||||
if(CHECKSUM)
|
||||
message(STATUS "Validating: ${FILE}")
|
||||
file(${TYPE} ${FILE} DOWNLOAD_CHECKSUM)
|
||||
message(STATUS "Checksum: ${CHECKSUM}")
|
||||
message(STATUS "Download: ${DOWNLOAD_CHECKSUM}")
|
||||
if(NOT CHECKSUM STREQUAL DOWNLOAD_CHECKSUM)
|
||||
file(REMOVE ${FILE})
|
||||
message(FATAL_ERROR "Validation failure: ${FILE}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(nodejs_checksum DATA FILE VAR)
|
||||
string(REGEX MATCH "([A-Fa-f0-9]+)[\t ]+${FILE}" CHECKSUM_MATCH ${DATA})
|
||||
if(CMAKE_MATCH_1)
|
||||
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to extract file checksum")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(nodejs_extract FILE DIR)
|
||||
# Function optionally takes a force value
|
||||
if(ARGC GREATER 2)
|
||||
set(FORCE ${ARGV2})
|
||||
endif()
|
||||
|
||||
# If the archvie has been extracted, no need to extract again unless it
|
||||
# is being forced
|
||||
if(NOT FORCE AND EXISTS ${DIR})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Make a temporary directory for extracting the output
|
||||
set(EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/extract)
|
||||
if(EXISTS ${EXTRACT_DIR})
|
||||
file(REMOVE_RECURSE ${EXTRACT_DIR})
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${EXTRACT_DIR})
|
||||
|
||||
# Extract the archive
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xfz ${FILE}
|
||||
WORKING_DIRECTORY ${EXTRACT_DIR}
|
||||
)
|
||||
|
||||
# If only one element is extracted, the archive contained a nested
|
||||
# folder; use the inner folder as the extracted folder
|
||||
file(GLOB EXTRACT_CHILDREN ${EXTRACT_DIR}/*)
|
||||
list(LENGTH EXTRACT_CHILDREN NUM_CHILDREN)
|
||||
set(TARGET_DIR ${EXTRACT_DIR})
|
||||
if(NUM_CHILDREN EQUAL 1)
|
||||
list(GET EXTRACT_CHILDREN 0 TARGET_DIR)
|
||||
endif()
|
||||
|
||||
# Move the folder to the target path
|
||||
if(EXISTS ${DIR})
|
||||
file(REMOVE_RECURSE ${DIR})
|
||||
endif()
|
||||
file(RENAME ${TARGET_DIR} ${DIR})
|
||||
|
||||
# Make sure to clean up the extraction folder when the inner folder
|
||||
# is used
|
||||
file(REMOVE_RECURSE ${EXTRACT_DIR})
|
||||
endfunction()
|
||||
|
||||
function(nodejs_find_module NAME BASE PATH)
|
||||
# Find a node module using the same search path that require uses
|
||||
# without needing a node binary
|
||||
set(ROOT ${BASE})
|
||||
set(DRIVE "^[A-Za-z]?:?/$")
|
||||
|
||||
# Walk up the directory tree until at the root
|
||||
while(NOT ROOT MATCHES ${DRIVE} AND NOT
|
||||
EXISTS ${ROOT}/node_modules/${NAME})
|
||||
get_filename_component(ROOT ${ROOT} DIRECTORY)
|
||||
endwhile()
|
||||
|
||||
# Operate like the CMake find_* functions, returning NOTFOUND if the
|
||||
# module can't be found
|
||||
if(ROOT MATCHES ${DRIVE})
|
||||
set(${PATH} ${NAME}-NOTFOUND PARENT_SCOPE)
|
||||
else()
|
||||
set(${PATH} ${ROOT}/node_modules/${NAME} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
macro(nodejs_find_module_fallback NAME BASE PATH)
|
||||
# Look in the provided path first
|
||||
# If the module isn't found, try searching from the module
|
||||
nodejs_find_module(${NAME} ${BASE} ${PATH})
|
||||
if(NOT ${PATH})
|
||||
nodejs_find_module(${NAME} ${NodeJS_MODULE_PATH} ${PATH})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(nodejs_get_version URL VAR)
|
||||
set(NWJS_LATEST_RELEASE_URL
|
||||
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
|
||||
set(VERSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/VERSION)
|
||||
nodejs_download(
|
||||
${URL}
|
||||
${VERSION_FILE}
|
||||
ON
|
||||
)
|
||||
nodejs_check_file(${VERSION_FILE})
|
||||
file(READ ${VERSION_FILE} VERSION_DATA)
|
||||
string(REGEX MATCH "v([0-9]+\.[0-9]+\.[0-9]+)"
|
||||
VERSION_MATCH ${VERSION_DATA}
|
||||
)
|
||||
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,81 +0,0 @@
|
||||
set(ELECTRON_VARIANT_BASE "electron")
|
||||
set(ELECTRON_WIN32_BINARY_NAME "${ELECTRON_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${ELECTRON_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_FIND_REQUIRED_ELECTRON OR
|
||||
NodeJS_VARIANT STREQUAL ${ELECTRON_VARIANT_BASE})
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
include(util/Github)
|
||||
github_get_rate_limit(GITHUB_RATE_LIMIT)
|
||||
|
||||
# Handle determining the latest release
|
||||
# Very complicated, due to electron not following the "latest"
|
||||
# convention of other variants
|
||||
set(ELECTRON_LATEST_RELEASE_FILE ${CMAKE_CURRENT_BINARY_DIR}/ELECTRON)
|
||||
set(ELECTRON_LATEST_RELEASE_URL
|
||||
${GITHUB_API_URL}/repos/atom/electron/releases/latest${GITHUB_AUTH}
|
||||
)
|
||||
if(GITHUB_RATE_LIMIT GREATER 0)
|
||||
nodejs_download(
|
||||
${ELECTRON_LATEST_RELEASE_URL}
|
||||
${ELECTRON_LATEST_RELEASE_FILE}
|
||||
ON
|
||||
)
|
||||
endif()
|
||||
nodejs_check_file(
|
||||
${ELECTRON_LATEST_RELEASE_FILE}
|
||||
"Releases file could not be downloaded, likely \
|
||||
because github rate limit was exceeded. Wait until the limit \
|
||||
passes or set GITHUB_API_TOKEN in your environment to a valid \
|
||||
github developer token."
|
||||
)
|
||||
file(READ ${ELECTRON_LATEST_RELEASE_FILE} ELECTRON_LATEST_RELEASE_DATA)
|
||||
string(REGEX MATCH "\"tag_name\"\: \"v([0-9]+\.[0-9]+\.[0-9]+)\""
|
||||
ELECTRON_LATEST_RELEASE_MATCH ${ELECTRON_LATEST_RELEASE_DATA})
|
||||
set(NodeJS_VERSION ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
set(NodeJS_VARIANT_NAME "Electron.js")
|
||||
|
||||
# SHASUMS of any kind is inaccessible prior to 0.16.0
|
||||
if(NodeJS_VERSION VERSION_LESS 0.16.0)
|
||||
message(FATAL_ERROR "Electron is only supported for versions >= 0.16.0")
|
||||
endif()
|
||||
|
||||
# Electron switched to IOJS after 0.25.0
|
||||
# Probably needs to be bounded on the upper side if/when they switch
|
||||
# back to node mainline due to iojs-node merge
|
||||
set(NodeJS_VARIANT_BASE "node")
|
||||
if(NodeJS_VERSION VERSION_GREATER 0.25.0)
|
||||
set(NodeJS_VARIANT_BASE "iojs")
|
||||
endif()
|
||||
|
||||
# Url is hard to get, because it will immediately resolve to a CDN
|
||||
# Extracted from the electron website
|
||||
set(NodeJS_URL
|
||||
"https://atom.io/download/atom-shell/v${NodeJS_VERSION}"
|
||||
)
|
||||
|
||||
# Headers become available for IOJS base ONLY!
|
||||
# Variant base switch above handles this
|
||||
set(NodeJS_HEADER_VERSION 0.30.1)
|
||||
|
||||
# Header only archive uses source style paths
|
||||
set(NodeJS_DEFAULT_INCLUDE False)
|
||||
|
||||
# Hard to determine, but versions seem to start at 16, and SHA256 is
|
||||
# available
|
||||
set(NodeJS_SHA256_VERSION 0.15.9)
|
||||
|
||||
# C++11 and Prefixing start after the IOJS switch
|
||||
# Will carry forward after node mainline so no need for upper bound (whew)
|
||||
set(NodeJS_PREFIX_VERSION 0.25.0)
|
||||
set(NodeJS_CXX11R_VERSION 0.25.0)
|
||||
|
||||
# The executable is not provided on the CDN
|
||||
# In theory, I could support a BINARY_URL to get this from github
|
||||
set(NodeJS_HAS_WIN32_BINARY False)
|
||||
|
||||
# OpenSSL isn't included in the headers
|
||||
set(NodeJS_HAS_OPENSSL False)
|
||||
endif()
|
||||
@@ -1,25 +0,0 @@
|
||||
set(IOJS_URL_BASE "https://iojs.org/dist")
|
||||
set(IOJS_VARIANT_BASE "iojs")
|
||||
set(IOJS_WIN32_BINARY_NAME "${IOJS_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${IOJS_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_FIND_REQUIRED_IOJS OR NodeJS_VARIANT STREQUAL ${IOJS_VARIANT_BASE})
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
set(IOJS_LATEST_RELEASE_URL
|
||||
"${IOJS_URL_BASE}/latest/SHASUMS256.txt")
|
||||
nodejs_get_version(${IOJS_LATEST_RELEASE_URL} NodeJS_VERSION)
|
||||
endif()
|
||||
|
||||
set(NodeJS_VARIANT_NAME "io.js")
|
||||
set(NodeJS_VARIANT_BASE ${IOJS_VARIANT_BASE})
|
||||
set(NodeJS_URL "${IOJS_URL_BASE}/v${NodeJS_VERSION}")
|
||||
set(NodeJS_HEADER_VERSION 2.3.1)
|
||||
set(NodeJS_WIN32_BINARY_NAME "${IOJS_WIN32_BINARY_NAME}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
IOJS_URL_BASE
|
||||
IOJS_VARIANT_BASE
|
||||
IOJS_WIN32_BINARY_NAME
|
||||
IOJS_LATEST_RELEASE_URL
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
set(NWJS_URL_BASE "http://dl.nwjs.io")
|
||||
set(NWJS_VARIANT_BASE "nw")
|
||||
set(NWJS_WIN32_BINARY_NAME "${NWJS_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${NWJS_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_FIND_REQUIRED_NWJS OR NodeJS_VARIANT STREQUAL ${NWJS_VARIANT_BASE})
|
||||
set(NodeJS_CHECKSUM_PATH "MD5SUMS")
|
||||
set(NodeJS_CHECKSUM_TYPE "MD5")
|
||||
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
set(NWJS_LATEST_RELEASE_URL
|
||||
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
|
||||
nodejs_get_version(${NWJS_LATEST_RELEASE_URL} NodeJS_VERSION)
|
||||
endif()
|
||||
|
||||
set(NodeJS_VARIANT_NAME "nw.js")
|
||||
set(NodeJS_VARIANT_BASE ${NWJS_VARIANT_BASE})
|
||||
set(NodeJS_URL "${NWJS_URL_BASE}/v${NodeJS_VERSION}")
|
||||
set(NodeJS_SOURCE_PATH "nw-headers-v${NodeJS_VERSION}.tar.gz")
|
||||
set(NodeJS_DEFAULT_INCLUDE False)
|
||||
set(NodeJS_HAS_WIN32_PREFIX False)
|
||||
set(NodeJS_HAS_WIN32_BINARY False)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
NWJS_URL_BASE
|
||||
NWJS_VARIANT_BASE
|
||||
NWJS_WIN32_BINARY_NAME
|
||||
NWJS_LATEST_RELEASE_URL
|
||||
)
|
||||
@@ -1,131 +0,0 @@
|
||||
set(NodeJS_URL_BASE http://nodejs.org/dist)
|
||||
set(NodeJS_DEFAULT_VARIANT_BASE "node")
|
||||
set(NodeJS_DEFAULT_WIN32_BINARY_NAME "${NodeJS_DEFAULT_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${NodeJS_DEFAULT_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
set(NodeJS_LATEST_RELEASE_URL
|
||||
"${NodeJS_URL_BASE}/latest/SHASUMS256.txt")
|
||||
nodejs_get_version(${NodeJS_LATEST_RELEASE_URL} NodeJS_VERSION)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_VARIANT_NAME)
|
||||
set(NodeJS_VARIANT_NAME ${NodeJS_DEFAULT_VARIANT_NAME})
|
||||
endif()
|
||||
if(NOT NodeJS_VARIANT_BASE)
|
||||
set(NodeJS_VARIANT_BASE ${NodeJS_DEFAULT_VARIANT_BASE})
|
||||
endif()
|
||||
if(NOT NodeJS_URL)
|
||||
set(NodeJS_URL "${NodeJS_URL_BASE}/v${NodeJS_VERSION}")
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_SOURCE_PATH)
|
||||
set(NodeJS_SOURCE_PATH "${NodeJS_VARIANT_BASE}-v${NodeJS_VERSION}")
|
||||
# Use the headers archive when its available
|
||||
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
|
||||
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}-headers")
|
||||
endif()
|
||||
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}.tar.gz")
|
||||
endif()
|
||||
|
||||
if(NodeJS_DEFAULT_INCLUDE AND
|
||||
NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
|
||||
set(NodeJS_SOURCE_INCLUDE False)
|
||||
set(NodeJS_HEADER_INCLUDE True)
|
||||
endif()
|
||||
|
||||
if(NodeJS_SOURCE_INCLUDE)
|
||||
list(APPEND NodeJS_INCLUDE_PATHS
|
||||
src
|
||||
deps/uv/include
|
||||
deps/v8/include
|
||||
deps/zlib
|
||||
)
|
||||
# OpenSSL is an optional header
|
||||
if(NodeJS_HAS_OPENSSL)
|
||||
list(APPEND NodeJS_INCLUDE_PATHS
|
||||
deps/openssl/openssl/include
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(NodeJS_HEADER_INCLUDE)
|
||||
set(NodeJS_INCLUDE_PATHS include/node)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_CHECKSUM_TYPE)
|
||||
# Use SHA256 when available
|
||||
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_SHA256_VERSION})
|
||||
set(NodeJS_CHECKSUM_TYPE "SHA256")
|
||||
else()
|
||||
set(NodeJS_CHECKSUM_TYPE "SHA1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_CHECKSUM_PATH)
|
||||
set(NodeJS_CHECKSUM_PATH "SHASUMS")
|
||||
if(NodeJS_CHECKSUM_TYPE STREQUAL "SHA256")
|
||||
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}256")
|
||||
endif()
|
||||
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}.txt")
|
||||
endif()
|
||||
|
||||
# Library and binary are based on variant base
|
||||
if(NOT NodeJS_WIN32_LIBRARY_NAME)
|
||||
set(NodeJS_WIN32_LIBRARY_NAME ${NodeJS_VARIANT_BASE}.lib)
|
||||
endif()
|
||||
if(NOT NodeJS_WIN32_BINARY_NAME)
|
||||
set(NodeJS_WIN32_BINARY_NAME ${NodeJS_VARIANT_BASE}.exe)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_WIN32_LIBRARY_PATH)
|
||||
# The library location is prefixed after a specific version
|
||||
if(NodeJS_HAS_WIN32_PREFIX AND
|
||||
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "win-")
|
||||
if(NodeJS_ARCH_IA32)
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x86/")
|
||||
endif()
|
||||
endif()
|
||||
# 64-bit versions are prefixed
|
||||
if(NodeJS_ARCH_X64)
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x64/")
|
||||
endif()
|
||||
set(NodeJS_WIN32_LIBRARY_PATH
|
||||
"${NodeJS_WIN32_LIBRARY_PATH}${NodeJS_WIN32_LIBRARY_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NodeJS_HAS_WIN32_BINARY AND NOT NodeJS_WIN32_BINARY_PATH)
|
||||
# The executable location is prefixed after a specific version
|
||||
if(NodeJS_HAS_WIN32_PREFIX AND
|
||||
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
|
||||
set(NodeJS_WIN32_BINARY_PATH "win-")
|
||||
if(NodeJS_ARCH_IA32)
|
||||
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x86/")
|
||||
endif()
|
||||
endif()
|
||||
# 64-bit versions are prefixed
|
||||
if(NodeJS_ARCH_X64)
|
||||
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x64/")
|
||||
endif()
|
||||
set(NodeJS_WIN32_BINARY_PATH
|
||||
"${NodeJS_WIN32_BINARY_PATH}${NodeJS_WIN32_BINARY_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Specify windows libraries
|
||||
# XXX: This may need to be version/variant specific in the future
|
||||
if(NodeJS_DEFAULT_LIBS AND NodeJS_PLATFORM_WIN32)
|
||||
list(APPEND NodeJS_LIBRARIES
|
||||
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
|
||||
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
|
||||
odbc32.lib DelayImp.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
NodeJS_URL_BASE
|
||||
NodeJS_DEFAULT_VARIANT_BASE
|
||||
NodeJS_DEFAULT_WIN32_BINARY_NAME
|
||||
NodeJS_LATEST_RELEASE_URL
|
||||
)
|
||||
+1
-1
@@ -3,5 +3,5 @@ module.exports = {
|
||||
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
||||
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||
all: '--strict --require features/support --require features/step_definitions',
|
||||
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@match --tags ~@alternative --tags ~@matrix --tags ~@trip --tags ~@via --require features/support --require features/step_definitions -f progress'
|
||||
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@matrix --tags ~@trip --require features/support --require features/step_definitions -f progress'
|
||||
}
|
||||
|
||||
+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,
|
||||
which is prepared by the OSRM Backend C++ library.
|
||||
## OSRM
|
||||
|
||||
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
|
||||
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-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
|
||||
methods below. To create an OSRM instance with your network you need to construct an instance like this:
|
||||
Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
|
||||
|
||||
```javascript
|
||||
var osrm = new OSRM('network.osrm');
|
||||
```
|
||||
|
||||
#### Methods
|
||||
**Parameters**
|
||||
|
||||
| Service | Description |
|
||||
| -------------------------- | --------------------------------------------------------- |
|
||||
| [`osrm.route`](#route) | shortest path between given coordinates |
|
||||
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
|
||||
| [`osrm.table`](#table) | computes distance tables for given coordinates |
|
||||
| [`osrm.match`](#match) | matches given coordinates to the road network |
|
||||
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
|
||||
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
|
||||
- `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'.
|
||||
Make sure you prepared the dataset with the correct toolchain.
|
||||
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
|
||||
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
||||
- `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.
|
||||
|
||||
#### 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` |
|
||||
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
|
||||
|
||||
## route
|
||||
### route
|
||||
|
||||
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
|
||||
|
||||
**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.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` **\[[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` 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`
|
||||
- `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.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)**
|
||||
|
||||
**Examples**
|
||||
|
||||
```javascript
|
||||
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;
|
||||
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
|
||||
@@ -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.
|
||||
|
||||
## nearest
|
||||
### nearest
|
||||
|
||||
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**
|
||||
|
||||
- `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`)
|
||||
- `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`.
|
||||
**`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
|
||||
input coordinate.
|
||||
Each object has an additional `distance` property, which is the distance in meters to the supplied 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**
|
||||
|
||||
- `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.
|
||||
- `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)**
|
||||
|
||||
**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`.
|
||||
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
|
||||
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
|
||||
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from the i-th waypoint to the j-th waypoint.
|
||||
Values are given in seconds.
|
||||
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources 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
|
||||
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
|
||||
be used to examine the routing graph. The tiles are generated directly from the data in-memory,
|
||||
so are in sync with actual routing results, and let you examine which roads are actually routable,
|
||||
so are in sync with actual routing results, and let you examine which roads are actually
|
||||
routable,
|
||||
and what weights they have applied.
|
||||
|
||||
**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
|
||||
[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/>.
|
||||
[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/).
|
||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||
|
||||
**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.
|
||||
|
||||
## match
|
||||
### match
|
||||
|
||||
Map matching matches given GPS points to the road network in the most plausible way.
|
||||
Please note the request might result multiple sub-traces. Large jumps in the timestamps
|
||||
@@ -175,15 +181,16 @@ if they can not be matched successfully.
|
||||
**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.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`
|
||||
according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||
- `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 (`double >= 0`, default `5m`).
|
||||
- `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.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` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||
- `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)**
|
||||
|
||||
**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`.
|
||||
**`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
|
||||
`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
|
||||
the waypoint inside the matched route.
|
||||
**`matchings`** is an array of [`Route`](#route) objects that
|
||||
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
|
||||
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
|
||||
If the trace point was ommited by map matching because it is an outlier, the entry will be null.
|
||||
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
|
||||
the waypoint inside the matched route.
|
||||
**`matchings`** is an array of [`Route`](#route) objects that assemble the trace. Each `Route` object has an additional `confidence` property,
|
||||
which is the confidence of 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.
|
||||
|
||||
**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.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.
|
||||
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
|
||||
waypoints. The returned path does not have to be the shortest 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.
|
||||
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 |
|
||||
| :-------- | :----- | :---------- | :-------- |
|
||||
| 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 |
|
||||
|
||||
**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**
|
||||
|
||||
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
|
||||
var osrm = new OSRM('network.osrm');
|
||||
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`.
|
||||
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
|
||||
Each Waypoint object has the following additional properties, 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.
|
||||
**`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 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.
|
||||
|
||||
# Responses
|
||||
## Responses
|
||||
|
||||
Responses
|
||||
|
||||
## Route
|
||||
### Route
|
||||
|
||||
Represents a route through (potentially multiple) waypoints.
|
||||
|
||||
**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.
|
||||
|
||||
**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**
|
||||
|
||||
- `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**
|
||||
|
||||
- `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.
|
||||
|
||||
**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 | f | sj,jf,jf | 50s +-1 | 400m +-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 |
|
||||
| mp | primary |
|
||||
And the profile "car"
|
||||
And the extract extra arguments "--generate-edge-lookup"
|
||||
|
||||
Scenario: Weighting not based on turn penalty file
|
||||
When I route I should get
|
||||
|
||||
@@ -51,7 +51,6 @@ Feature: Car - weights
|
||||
| cd | primary | yes |
|
||||
| be | 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 customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
@@ -62,3 +61,28 @@ Feature: Car - weights
|
||||
| from | to | route | speed | weight |
|
||||
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
||||
| 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,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 |
|
||||
|
||||
|
||||
# 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,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
|
||||
Given the node map
|
||||
"""
|
||||
@@ -681,3 +718,105 @@ Feature: Basic Roundabout
|
||||
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
|
||||
| u,s | ug,ds,ds | depart,roundabout-exit-4,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
|
||||
|
||||
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}"
|
||||
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,3"
|
||||
And I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 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]);
|
||||
|
||||
got.code = 'unknown';
|
||||
if (res.body.length) {
|
||||
json = JSON.parse(res.body);
|
||||
got.code = json.code;
|
||||
}
|
||||
|
||||
|
||||
if (headers.has('status')) {
|
||||
got.status = json.status.toString();
|
||||
}
|
||||
@@ -33,7 +36,7 @@ module.exports = function () {
|
||||
got['#'] = row['#'];
|
||||
}
|
||||
|
||||
var subMatchings = [],
|
||||
var subMatchings = [''],
|
||||
turns = '',
|
||||
route = '',
|
||||
duration = '',
|
||||
@@ -175,8 +178,7 @@ module.exports = function () {
|
||||
|
||||
if (headers.has('matchings')) {
|
||||
if (subMatchings.length != row.matchings.split(',').length) {
|
||||
ok = false;
|
||||
cb(new Error('*** table matchings and api response are not the same'));
|
||||
return cb(new Error('*** table matchings and api response are not the same'));
|
||||
}
|
||||
|
||||
row.matchings.split(',').forEach((sub, si) => {
|
||||
|
||||
@@ -126,6 +126,7 @@ module.exports = function () {
|
||||
|
||||
r.query = this.query;
|
||||
r.json = JSON.parse(body);
|
||||
r.code = r.json.code;
|
||||
r.status = res.statusCode === 200 ? 'x' : null;
|
||||
if (r.status) {
|
||||
r.route = this.wayList(r.json.routes[0]);
|
||||
|
||||
@@ -29,8 +29,10 @@ module.exports = function () {
|
||||
}
|
||||
|
||||
var json;
|
||||
got.code = 'unknown';
|
||||
if (res.body.length) {
|
||||
json = JSON.parse(res.body);
|
||||
got.code = json.code;
|
||||
}
|
||||
|
||||
if (headers.has('status')) {
|
||||
@@ -153,11 +155,11 @@ module.exports = function () {
|
||||
|
||||
if (row.source) {
|
||||
params.source = got.source = row.source;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (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
|
||||
params.roundtrip = got.roundtrip = row.roundtrip;
|
||||
|
||||
@@ -39,6 +39,8 @@ module.exports = function () {
|
||||
|
||||
let json = JSON.parse(body);
|
||||
|
||||
got.code = json.code;
|
||||
|
||||
let hasRoute = json.code === 'Ok';
|
||||
|
||||
if (hasRoute) {
|
||||
@@ -79,102 +81,102 @@ module.exports = function () {
|
||||
|
||||
if (headers.has('route')) {
|
||||
got.route = (instructions || '').trim();
|
||||
|
||||
if (headers.has('summary')) {
|
||||
got.summary = (summary || '').trim();
|
||||
}
|
||||
|
||||
if (headers.has('alternative')) {
|
||||
// TODO examine more than first alternative?
|
||||
got.alternative ='';
|
||||
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) {
|
||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||
got[key] = row[key];
|
||||
|
||||
@@ -4,7 +4,6 @@ Feature: Basic Map Matching
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
Given a grid size of 10 meters
|
||||
Given the extract extra arguments "--generate-edge-lookup"
|
||||
Given the query options
|
||||
| geometries | geojson |
|
||||
|
||||
@@ -213,7 +212,7 @@ Feature: Basic Map Matching
|
||||
|
||||
And the speed file
|
||||
"""
|
||||
1,2,36
|
||||
1,2,36,10
|
||||
"""
|
||||
|
||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||
@@ -240,7 +239,7 @@ Feature: Basic Map Matching
|
||||
|
||||
And the speed file
|
||||
"""
|
||||
1,2,36
|
||||
1,2,36,10
|
||||
"""
|
||||
|
||||
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 |
|
||||
| d | b | 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 |
|
||||
| fb | primary |
|
||||
And the profile "testbot"
|
||||
And the extract extra arguments "--generate-edge-lookup"
|
||||
|
||||
|
||||
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 speed file
|
||||
"""
|
||||
1,2,0
|
||||
2,1,0
|
||||
2,3,27
|
||||
3,2,27
|
||||
1,4,27
|
||||
4,1,27
|
||||
1,2,0,0
|
||||
2,1,0,0
|
||||
2,3,27,7.5
|
||||
3,2,27,7.5
|
||||
1,4,27,7.5
|
||||
4,1,27,7.5
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
@@ -56,12 +55,12 @@ Feature: Traffic - speeds
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
"""
|
||||
1,2,1,20020.7
|
||||
2,1,1,20020.7
|
||||
2,3,27,741.5
|
||||
3,2,27,741.5
|
||||
1,4,27,1275.7
|
||||
4,1,27,1275.7
|
||||
1,2,1,0.2777777
|
||||
2,1,1
|
||||
2,3,27
|
||||
3,2,27,7.5
|
||||
1,4,27,7.5
|
||||
4,1,27,7.5
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
@@ -89,26 +88,26 @@ Feature: Traffic - speeds
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
"""
|
||||
1,2,1,20020.789
|
||||
2,1,1,20020.123
|
||||
2,3,27,741.56789
|
||||
3,2,27,741.3
|
||||
1,4,1,34445.12
|
||||
4,1,1,34445.3
|
||||
1,2,1,0.27777777
|
||||
2,1,1,0.27777777
|
||||
2,3,27,7.5
|
||||
3,2,27
|
||||
1,4,1
|
||||
4,1,1
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed | weights | a:datasources |
|
||||
| a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
|
||||
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
|
||||
| b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
|
||||
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
|
||||
| a | b | ab,ab | 1 km/h | 20020.735,0 | 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.509,0 | 1: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 |
|
||||
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
|
||||
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
|
||||
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
|
||||
| g | b | ab,ab | 1 km/h | 10010.365,0 | 1:0 |
|
||||
| a | g | ab,ab | 1 km/h | 10010.37,0 | 1 |
|
||||
| g | a | ab,ab | 1 km/h | 10010.37,0 | 1:1 |
|
||||
|
||||
|
||||
Scenario: Speeds that isolate a single node (a)
|
||||
@@ -121,10 +120,10 @@ Feature: Traffic - speeds
|
||||
"""
|
||||
1,2,0
|
||||
2,1,0
|
||||
2,3,27
|
||||
3,2,27
|
||||
1,4,0
|
||||
4,1,0
|
||||
2,3,27,7.5
|
||||
3,2,27,7.5
|
||||
1,4,0,0
|
||||
4,1,0,0
|
||||
"""
|
||||
And the query options
|
||||
| annotations | true |
|
||||
@@ -154,3 +153,11 @@ Feature: Traffic - speeds
|
||||
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||
And stderr should contain "malformed"
|
||||
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 |
|
||||
And the profile "testbot"
|
||||
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
|
||||
And the extract extra arguments "--generate-edge-lookup"
|
||||
|
||||
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
|
||||
Given the turn penalty file
|
||||
|
||||
@@ -352,3 +352,64 @@ Feature: Via points
|
||||
| waypoints | bearings | route | turns |
|
||||
| 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 |
|
||||
|
||||
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:
|
||||
Given the profile "testbot"
|
||||
Given a grid size of 10 meters
|
||||
Given the extract extra arguments "--generate-edge-lookup"
|
||||
Given the query options
|
||||
| geometries | geojson |
|
||||
|
||||
@@ -284,8 +283,8 @@ Feature: Weight tests
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | distance | weights | times |
|
||||
| a,d | , | 59.9m | 62,0 | 24s,0s |
|
||||
| a,e | ,, | 60.1m | 68.7,10,0 | 38.5s,11s,0s |
|
||||
| a,d | , | 59.9m | 20.5,0 | 24s,0s |
|
||||
| a,e | ,, | 60.1m | 27.2,10,0 | 38.5s,11s,0s |
|
||||
| d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s |
|
||||
|
||||
@traffic @speed
|
||||
@@ -320,6 +319,6 @@ Feature: Weight tests
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | distance | weights | times |
|
||||
| a,d | abcd,abcd | 59.9m | 6.993,0 | 7s,0s |
|
||||
| a,e | abcd,ce,ce | 60.1m | 6.002,2.002,0 | 6s,2s,0s |
|
||||
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
||||
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
||||
| 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 |
|
||||
@@ -68,9 +68,8 @@ class Contractor
|
||||
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
|
||||
void WriteNodeLevels(std::vector<float> &&node_levels) const;
|
||||
void ReadNodeLevels(std::vector<float> &contraction_order) const;
|
||||
std::size_t
|
||||
WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||
const util::DeallocatingVector<QueryEdge> &contracted_edge_list);
|
||||
void WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||
util::DeallocatingVector<QueryEdge> contracted_edge_list);
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<extractor::EdgeBasedEdge> &edges,
|
||||
std::vector<extractor::EdgeBasedNode> &nodes) const;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef OSRM_CONTRACTOR_FILES_HPP
|
||||
#define OSRM_CONTRACTOR_FILES_HPP
|
||||
|
||||
#include "contractor/query_graph.hpp"
|
||||
|
||||
#include "util/serialization.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace contractor
|
||||
{
|
||||
namespace files
|
||||
{
|
||||
|
||||
// reads .osrm.hsgr file
|
||||
template <typename QueryGraphT>
|
||||
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
||||
"graph must be of type QueryGraph<>");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.ReadInto(checksum);
|
||||
util::serialization::read(reader, graph);
|
||||
}
|
||||
|
||||
// writes .osrm.hsgr file
|
||||
template <typename QueryGraphT>
|
||||
inline void
|
||||
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
||||
"graph must be of type QueryGraph<>");
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteOne(checksum);
|
||||
util::serialization::write(writer, graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef OSRM_CONTRACTOR_QUERY_GRAPH_HPP
|
||||
#define OSRM_CONTRACTOR_QUERY_GRAPH_HPP
|
||||
|
||||
#include "contractor/query_edge.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace contractor
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
using QueryGraph = util::StaticGraph<typename QueryEdge::EdgeData, Ownership>;
|
||||
}
|
||||
|
||||
using QueryGraph = detail::QueryGraph<storage::Ownership::Container>;
|
||||
using QueryGraphView = detail::QueryGraph<storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // QUERYEDGE_HPP
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef OSRM_CUSTOMIZER_IO_HPP
|
||||
#define OSRM_CUSTOMIZER_IO_HPP
|
||||
|
||||
#include "customizer/edge_based_graph.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace customizer
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -7,30 +7,36 @@ namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
namespace algorithm
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
// Contraction Hiearchy
|
||||
struct CH final
|
||||
namespace ch
|
||||
{
|
||||
struct Algorithm final
|
||||
{
|
||||
};
|
||||
}
|
||||
// Contraction Hiearchy with core
|
||||
struct CoreCH final
|
||||
namespace corech
|
||||
{
|
||||
struct Algorithm final
|
||||
{
|
||||
};
|
||||
}
|
||||
// Multi-Level Dijkstra
|
||||
struct MLD final
|
||||
namespace mld
|
||||
{
|
||||
struct Algorithm final
|
||||
{
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> const char *name();
|
||||
template <> inline const char *name<CH>() { return "CH"; }
|
||||
template <> inline const char *name<CoreCH>() { return "CoreCH"; }
|
||||
template <> inline const char *name<MLD>() { return "MLD"; }
|
||||
}
|
||||
|
||||
namespace algorithm_trais
|
||||
{
|
||||
// Algorithm names
|
||||
template <typename AlgorithmT> const char *name();
|
||||
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
|
||||
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
|
||||
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
|
||||
|
||||
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
|
||||
{
|
||||
@@ -51,62 +57,49 @@ template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct HasAlternativePathSearch<algorithm::CH> final : std::true_type
|
||||
// Algorithms supported by Contraction Hierarchies
|
||||
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasShortestPathSearch<algorithm::CH> final : std::true_type
|
||||
template <> struct HasShortestPathSearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasDirectShortestPathSearch<algorithm::CH> final : std::true_type
|
||||
template <> struct HasDirectShortestPathSearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasMapMatching<algorithm::CH> final : std::true_type
|
||||
template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasManyToManySearch<algorithm::CH> final : std::true_type
|
||||
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasGetTileTurns<algorithm::CH> final : std::true_type
|
||||
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// disbaled because of perfomance reasons
|
||||
template <> struct HasAlternativePathSearch<algorithm::CoreCH> final : std::false_type
|
||||
// Algorithms supported by Contraction Hierarchies with core
|
||||
// the rest is disabled because of performance reasons
|
||||
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasManyToManySearch<algorithm::CoreCH> final : std::false_type
|
||||
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasShortestPathSearch<algorithm::CoreCH> final : std::true_type
|
||||
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasDirectShortestPathSearch<algorithm::CoreCH> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasMapMatching<algorithm::CoreCH> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasGetTileTurns<algorithm::CoreCH> final : std::true_type
|
||||
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// disbaled because of perfomance reasons
|
||||
template <> struct HasAlternativePathSearch<algorithm::MLD> final : std::false_type
|
||||
// Algorithms supported by Multi-Level Dijkstra
|
||||
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasManyToManySearch<algorithm::MLD> final : std::false_type
|
||||
template <> struct HasShortestPathSearch<mld::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasShortestPathSearch<algorithm::MLD> final : std::false_type
|
||||
{
|
||||
};
|
||||
template <> struct HasDirectShortestPathSearch<algorithm::MLD> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasMapMatching<algorithm::MLD> final : std::false_type
|
||||
{
|
||||
};
|
||||
template <> struct HasGetTileTurns<algorithm::MLD> final : std::false_type
|
||||
template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
@@ -80,22 +80,21 @@ inline Result keep_all(const MatchParameters ¶ms)
|
||||
|
||||
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
{
|
||||
BOOST_ASSERT(!params.coordinates.empty());
|
||||
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
|
||||
result.tidied_to_original.push_back(0);
|
||||
std::size_t last_good = 0;
|
||||
|
||||
const auto uses_timestamps = !params.timestamps.empty();
|
||||
|
||||
Thresholds running{0., 0};
|
||||
|
||||
// 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(
|
||||
params.coordinates[current], params.coordinates[next]);
|
||||
running.distance_in_meters += distance_delta;
|
||||
@@ -109,7 +108,6 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
|
||||
if (over_distance && over_duration)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
@@ -122,7 +120,6 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
{
|
||||
if (over_distance)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
@@ -133,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.
|
||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||
|
||||
@@ -167,8 +167,8 @@ class RouteAPI : public BaseAPI
|
||||
*/
|
||||
|
||||
guidance::trimShortSegments(steps, leg_geometry);
|
||||
leg.steps = guidance::collapseTurnInstructions(std::move(steps));
|
||||
leg.steps = guidance::postProcess(std::move(leg.steps));
|
||||
leg.steps = guidance::postProcess(std::move(steps));
|
||||
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
|
||||
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
||||
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
|
||||
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
||||
|
||||
@@ -17,11 +17,16 @@ namespace engine
|
||||
namespace datafacade
|
||||
{
|
||||
|
||||
// Namespace local aliases for algorithms
|
||||
using CH = routing_algorithms::ch::Algorithm;
|
||||
using CoreCH = routing_algorithms::corech::Algorithm;
|
||||
using MLD = routing_algorithms::mld::Algorithm;
|
||||
|
||||
using EdgeRange = util::range<EdgeID>;
|
||||
|
||||
template <typename AlgorithmT> class AlgorithmDataFacade;
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::CH>
|
||||
template <> class AlgorithmDataFacade<CH>
|
||||
{
|
||||
public:
|
||||
using EdgeData = contractor::QueryEdge::EdgeData;
|
||||
@@ -56,7 +61,7 @@ template <> class AlgorithmDataFacade<algorithm::CH>
|
||||
const std::function<bool(EdgeData)> filter) const = 0;
|
||||
};
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::CoreCH>
|
||||
template <> class AlgorithmDataFacade<CoreCH>
|
||||
{
|
||||
public:
|
||||
using EdgeData = contractor::QueryEdge::EdgeData;
|
||||
@@ -64,7 +69,7 @@ template <> class AlgorithmDataFacade<algorithm::CoreCH>
|
||||
virtual bool IsCoreNode(const NodeID id) const = 0;
|
||||
};
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::MLD>
|
||||
template <> class AlgorithmDataFacade<MLD>
|
||||
{
|
||||
public:
|
||||
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
|
||||
#include "contractor/query_graph.hpp"
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
@@ -58,15 +61,14 @@ namespace datafacade
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryAlgorithmDataFacade;
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::CH>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
|
||||
{
|
||||
private:
|
||||
using QueryGraph = util::StaticGraph<EdgeData, storage::Ownership::View>;
|
||||
using QueryGraph = contractor::QueryGraphView;
|
||||
using GraphNode = QueryGraph::NodeArrayEntry;
|
||||
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
||||
|
||||
std::unique_ptr<QueryGraph> m_query_graph;
|
||||
QueryGraph m_query_graph;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
@@ -83,7 +85,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
|
||||
util::vector_view<GraphEdge> edge_list(
|
||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
|
||||
m_query_graph.reset(new QueryGraph(node_list, edge_list));
|
||||
m_query_graph = QueryGraph(node_list, edge_list);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -100,59 +102,59 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
}
|
||||
|
||||
// search graph access
|
||||
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
|
||||
unsigned GetNumberOfNodes() const override final { return m_query_graph.GetNumberOfNodes(); }
|
||||
|
||||
unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
|
||||
unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); }
|
||||
|
||||
unsigned GetOutDegree(const NodeID n) const override final
|
||||
{
|
||||
return m_query_graph->GetOutDegree(n);
|
||||
return m_query_graph.GetOutDegree(n);
|
||||
}
|
||||
|
||||
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); }
|
||||
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); }
|
||||
|
||||
EdgeData &GetEdgeData(const EdgeID e) const override final
|
||||
const EdgeData &GetEdgeData(const EdgeID e) const override final
|
||||
{
|
||||
return m_query_graph->GetEdgeData(e);
|
||||
return m_query_graph.GetEdgeData(e);
|
||||
}
|
||||
|
||||
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); }
|
||||
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph.BeginEdges(n); }
|
||||
|
||||
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); }
|
||||
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph.EndEdges(n); }
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
||||
{
|
||||
return m_query_graph->GetAdjacentEdgeRange(node);
|
||||
return m_query_graph.GetAdjacentEdgeRange(node);
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeID FindEdge(const NodeID from, const NodeID to) const override final
|
||||
{
|
||||
return m_query_graph->FindEdge(from, to);
|
||||
return m_query_graph.FindEdge(from, to);
|
||||
}
|
||||
|
||||
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final
|
||||
{
|
||||
return m_query_graph->FindEdgeInEitherDirection(from, to);
|
||||
return m_query_graph.FindEdgeInEitherDirection(from, to);
|
||||
}
|
||||
|
||||
EdgeID
|
||||
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final
|
||||
{
|
||||
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
|
||||
return m_query_graph.FindEdgeIndicateIfReverse(from, to, result);
|
||||
}
|
||||
|
||||
EdgeID FindSmallestEdge(const NodeID from,
|
||||
const NodeID to,
|
||||
std::function<bool(EdgeData)> filter) const override final
|
||||
{
|
||||
return m_query_graph->FindSmallestEdge(from, to, filter);
|
||||
return m_query_graph.FindSmallestEdge(from, to, filter);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::CoreCH>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
||||
: public datafacade::AlgorithmDataFacade<CoreCH>
|
||||
{
|
||||
private:
|
||||
util::vector_view<bool> m_is_core_node;
|
||||
@@ -202,8 +204,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
using super = BaseDataFacade;
|
||||
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
|
||||
using RTreeLeaf = super::RTreeLeaf;
|
||||
using SharedRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::vector_view<util::Coordinate>, storage::Ownership::View>;
|
||||
using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>;
|
||||
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
|
||||
using RTreeNode = SharedRTree::TreeNode;
|
||||
|
||||
@@ -213,22 +214,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
unsigned m_check_sum;
|
||||
util::vector_view<util::Coordinate> m_coordinate_list;
|
||||
util::PackedVector<OSMNodeID, storage::Ownership::View> m_osmnodeid_list;
|
||||
util::vector_view<GeometryID> m_via_geometry_list;
|
||||
util::vector_view<NameID> m_name_ID_list;
|
||||
util::vector_view<LaneDataID> m_lane_data_id;
|
||||
util::vector_view<extractor::guidance::TurnInstruction> m_turn_instruction_list;
|
||||
util::vector_view<extractor::TravelMode> m_travel_mode_list;
|
||||
util::vector_view<util::guidance::TurnBearing> m_pre_turn_bearing;
|
||||
util::vector_view<util::guidance::TurnBearing> m_post_turn_bearing;
|
||||
util::PackedVectorView<OSMNodeID> m_osmnodeid_list;
|
||||
util::NameTable m_names_table;
|
||||
util::vector_view<unsigned> m_name_begin_indices;
|
||||
util::vector_view<bool> m_is_core_node;
|
||||
util::vector_view<std::uint32_t> m_lane_description_offsets;
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> m_lane_description_masks;
|
||||
util::vector_view<TurnPenalty> m_turn_weight_penalties;
|
||||
util::vector_view<TurnPenalty> m_turn_duration_penalties;
|
||||
extractor::SegmentDataView segment_data;
|
||||
extractor::TurnDataView turn_data;
|
||||
|
||||
util::vector_view<char> m_datasource_name_data;
|
||||
util::vector_view<std::size_t> m_datasource_name_offsets;
|
||||
@@ -304,8 +297,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
|
||||
}
|
||||
|
||||
void InitializeNodeAndEdgeInformationPointers(storage::DataLayout &data_layout,
|
||||
char *memory_block)
|
||||
void InitializeNodeInformationPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
const auto coordinate_list_ptr = data_layout.GetBlockPtr<util::Coordinate>(
|
||||
memory_block, storage::DataLayout::COORDINATE_LIST);
|
||||
@@ -324,66 +316,59 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
// We (ab)use the number of coordinates here because we know we have the same amount of ids
|
||||
m_osmnodeid_list.set_number_of_entries(
|
||||
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
|
||||
|
||||
const auto travel_mode_list_ptr = data_layout.GetBlockPtr<extractor::TravelMode>(
|
||||
memory_block, storage::DataLayout::TRAVEL_MODE);
|
||||
util::vector_view<extractor::TravelMode> travel_mode_list(
|
||||
travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
|
||||
m_travel_mode_list = std::move(travel_mode_list);
|
||||
|
||||
const auto lane_data_id_ptr =
|
||||
data_layout.GetBlockPtr<LaneDataID>(memory_block, storage::DataLayout::LANE_DATA_ID);
|
||||
util::vector_view<LaneDataID> lane_data_id(
|
||||
lane_data_id_ptr, data_layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
|
||||
m_lane_data_id = std::move(lane_data_id);
|
||||
|
||||
const auto lane_tupel_id_pair_ptr =
|
||||
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
|
||||
memory_block, storage::DataLayout::TURN_LANE_DATA);
|
||||
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
|
||||
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
|
||||
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
|
||||
|
||||
const auto turn_instruction_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
|
||||
memory_block, storage::DataLayout::TURN_INSTRUCTION);
|
||||
util::vector_view<extractor::guidance::TurnInstruction> turn_instruction_list(
|
||||
turn_instruction_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
||||
m_turn_instruction_list = std::move(turn_instruction_list);
|
||||
|
||||
const auto name_id_list_ptr =
|
||||
data_layout.GetBlockPtr<NameID>(memory_block, storage::DataLayout::NAME_ID_LIST);
|
||||
util::vector_view<NameID> name_id_list(
|
||||
name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
|
||||
m_name_ID_list = std::move(name_id_list);
|
||||
|
||||
const auto entry_class_id_list_ptr =
|
||||
data_layout.GetBlockPtr<EntryClassID>(memory_block, storage::DataLayout::ENTRY_CLASSID);
|
||||
typename util::vector_view<EntryClassID> entry_class_id_list(
|
||||
entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||
m_entry_class_id_list = std::move(entry_class_id_list);
|
||||
|
||||
const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_block, storage::DataLayout::PRE_TURN_BEARING);
|
||||
typename util::vector_view<util::guidance::TurnBearing> pre_turn_bearing(
|
||||
pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||
m_pre_turn_bearing = std::move(pre_turn_bearing);
|
||||
|
||||
const auto post_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_block, storage::DataLayout::POST_TURN_BEARING);
|
||||
typename util::vector_view<util::guidance::TurnBearing> post_turn_bearing(
|
||||
post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||
m_post_turn_bearing = std::move(post_turn_bearing);
|
||||
}
|
||||
|
||||
void InitializeViaNodeListPointer(storage::DataLayout &data_layout, char *memory_block)
|
||||
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
||||
{
|
||||
auto via_geometry_list_ptr =
|
||||
data_layout.GetBlockPtr<GeometryID>(memory_block, storage::DataLayout::VIA_NODE_LIST);
|
||||
util::vector_view<GeometryID> via_geometry_list(
|
||||
via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
|
||||
m_via_geometry_list = std::move(via_geometry_list);
|
||||
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::VIA_NODE_LIST);
|
||||
util::vector_view<GeometryID> geometry_ids(
|
||||
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
|
||||
|
||||
const auto travel_mode_list_ptr =
|
||||
layout.GetBlockPtr<extractor::TravelMode>(memory_ptr, storage::DataLayout::TRAVEL_MODE);
|
||||
util::vector_view<extractor::TravelMode> travel_modes(
|
||||
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
|
||||
|
||||
const auto lane_data_id_ptr =
|
||||
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
|
||||
util::vector_view<LaneDataID> lane_data_ids(
|
||||
lane_data_id_ptr, layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
|
||||
|
||||
const auto turn_instruction_list_ptr =
|
||||
layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
|
||||
memory_ptr, storage::DataLayout::TURN_INSTRUCTION);
|
||||
util::vector_view<extractor::guidance::TurnInstruction> turn_instructions(
|
||||
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
||||
|
||||
const auto name_id_list_ptr =
|
||||
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST);
|
||||
util::vector_view<NameID> name_ids(name_id_list_ptr,
|
||||
layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
|
||||
|
||||
const auto entry_class_id_list_ptr =
|
||||
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
|
||||
util::vector_view<EntryClassID> entry_class_ids(
|
||||
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||
|
||||
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
||||
util::vector_view<util::guidance::TurnBearing> pre_turn_bearings(
|
||||
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||
|
||||
const auto post_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
||||
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
|
||||
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||
|
||||
turn_data = extractor::TurnDataView(std::move(geometry_ids),
|
||||
std::move(name_ids),
|
||||
std::move(turn_instructions),
|
||||
std::move(lane_data_ids),
|
||||
std::move(travel_modes),
|
||||
std::move(entry_class_ids),
|
||||
std::move(pre_turn_bearings),
|
||||
std::move(post_turn_bearings));
|
||||
}
|
||||
|
||||
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
@@ -409,6 +394,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> masks(
|
||||
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
|
||||
m_lane_description_masks = std::move(masks);
|
||||
|
||||
const auto lane_tupel_id_pair_ptr =
|
||||
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
|
||||
memory_block, storage::DataLayout::TURN_LANE_DATA);
|
||||
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
|
||||
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
|
||||
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
|
||||
}
|
||||
|
||||
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
|
||||
@@ -515,11 +507,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
InitializeChecksumPointer(data_layout, memory_block);
|
||||
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
|
||||
InitializeNodeInformationPointers(data_layout, memory_block);
|
||||
InitializeEdgeInformationPointers(data_layout, memory_block);
|
||||
InitializeTurnPenalties(data_layout, memory_block);
|
||||
InitializeGeometryPointers(data_layout, memory_block);
|
||||
InitializeTimestampPointer(data_layout, memory_block);
|
||||
InitializeViaNodeListPointer(data_layout, memory_block);
|
||||
InitializeNamePointers(data_layout, memory_block);
|
||||
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
|
||||
InitializeProfilePropertiesPointer(data_layout, memory_block);
|
||||
@@ -608,7 +600,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_via_geometry_list.at(id);
|
||||
return turn_data.GetGeometryID(id);
|
||||
}
|
||||
|
||||
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
|
||||
@@ -626,12 +618,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
extractor::guidance::TurnInstruction
|
||||
GetTurnInstructionForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_turn_instruction_list.at(id);
|
||||
return turn_data.GetTurnInstruction(id);
|
||||
}
|
||||
|
||||
extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_travel_mode_list.at(id);
|
||||
return turn_data.GetTravelMode(id);
|
||||
}
|
||||
|
||||
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
@@ -753,7 +745,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
NameID GetNameIndexFromEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_name_ID_list.at(id);
|
||||
return turn_data.GetNameID(id);
|
||||
}
|
||||
|
||||
StringView GetNameForID(const NameID id) const override final
|
||||
@@ -825,16 +817,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID eid) const override final
|
||||
{
|
||||
return m_entry_class_id_list.at(eid);
|
||||
return turn_data.GetEntryClassID(eid);
|
||||
}
|
||||
|
||||
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
|
||||
{
|
||||
return m_pre_turn_bearing.at(eid);
|
||||
return turn_data.GetPreTurnBearing(eid);
|
||||
}
|
||||
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
|
||||
{
|
||||
return m_post_turn_bearing.at(eid);
|
||||
return turn_data.GetPostTurnBearing(eid);
|
||||
}
|
||||
|
||||
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
|
||||
@@ -842,15 +834,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
return m_entry_class_table.at(entry_class_id);
|
||||
}
|
||||
|
||||
bool hasLaneData(const EdgeID id) const override final
|
||||
{
|
||||
return INVALID_LANE_DATAID != m_lane_data_id.at(id);
|
||||
}
|
||||
bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); }
|
||||
|
||||
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
|
||||
{
|
||||
BOOST_ASSERT(hasLaneData(id));
|
||||
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
|
||||
BOOST_ASSERT(HasLaneData(id));
|
||||
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id));
|
||||
}
|
||||
|
||||
extractor::guidance::TurnLaneDescription
|
||||
@@ -869,36 +858,34 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::CH>
|
||||
class ContiguousInternalMemoryDataFacade<CH>
|
||||
: public ContiguousInternalMemoryDataFacadeBase,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
|
||||
{
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>(allocator)
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::CoreCH> final
|
||||
: public ContiguousInternalMemoryDataFacade<algorithm::CH>,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
class ContiguousInternalMemoryDataFacade<CoreCH> final
|
||||
: public ContiguousInternalMemoryDataFacade<CH>,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
||||
{
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacade<algorithm::CH>(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>(allocator)
|
||||
: ContiguousInternalMemoryDataFacade<CH>(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::MLD>
|
||||
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
|
||||
{
|
||||
// MLD data
|
||||
partition::MultiLevelPartitionView mld_partition;
|
||||
@@ -923,7 +910,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
|
||||
|
||||
auto level_data =
|
||||
*data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
|
||||
data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
|
||||
memory_block, storage::DataLayout::MLD_LEVEL_DATA);
|
||||
|
||||
auto mld_partition_ptr = data_layout.GetBlockPtr<PartitionID>(
|
||||
@@ -1065,15 +1052,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::MLD> final
|
||||
class ContiguousInternalMemoryDataFacade<MLD> final
|
||||
: public ContiguousInternalMemoryDataFacadeBase,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<MLD>
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>(allocator)
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class BaseDataFacade
|
||||
const int bearing,
|
||||
const int bearing_range) const = 0;
|
||||
|
||||
virtual bool hasLaneData(const EdgeID id) const = 0;
|
||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||
virtual extractor::guidance::TurnLaneDescription
|
||||
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
|
||||
|
||||
+18
-17
@@ -49,7 +49,7 @@ class EngineInterface
|
||||
virtual Status Tile(const api::TileParameters ¶meters, std::string &result) const = 0;
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
template <typename Algorithm> class Engine final : public EngineInterface
|
||||
{
|
||||
public:
|
||||
explicit Engine(const EngineConfig &config)
|
||||
@@ -64,15 +64,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
if (config.use_shared_memory)
|
||||
{
|
||||
util::Log(logDEBUG) << "Using shared memory with algorithm "
|
||||
<< algorithm::name<AlgorithmT>();
|
||||
facade_provider = std::make_unique<WatchingProvider<AlgorithmT>>();
|
||||
<< routing_algorithms::name<Algorithm>();
|
||||
facade_provider = std::make_unique<WatchingProvider<Algorithm>>();
|
||||
}
|
||||
else
|
||||
{
|
||||
util::Log(logDEBUG) << "Using internal memory with algorithm "
|
||||
<< algorithm::name<AlgorithmT>();
|
||||
facade_provider =
|
||||
std::make_unique<ImmutableProvider<AlgorithmT>>(config.storage_config);
|
||||
<< routing_algorithms::name<Algorithm>();
|
||||
facade_provider = std::make_unique<ImmutableProvider<Algorithm>>(config.storage_config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return route_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
@@ -95,7 +94,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return table_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
@@ -103,14 +102,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return nearest_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
Status Trip(const api::TripParameters ¶ms, util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return trip_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
@@ -118,22 +117,22 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return match_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
Status Tile(const api::TileParameters ¶ms, std::string &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return tile_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
static bool CheckCompability(const EngineConfig &config);
|
||||
|
||||
private:
|
||||
std::unique_ptr<DataFacadeProvider<AlgorithmT>> facade_provider;
|
||||
mutable SearchEngineData heaps;
|
||||
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
|
||||
mutable SearchEngineData<Algorithm> heaps;
|
||||
|
||||
const plugins::ViaRoutePlugin route_plugin;
|
||||
const plugins::TablePlugin table_plugin;
|
||||
@@ -143,7 +142,8 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
const plugins::TilePlugin tile_plugin;
|
||||
};
|
||||
|
||||
template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &config)
|
||||
template <>
|
||||
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompability(const EngineConfig &config)
|
||||
{
|
||||
if (config.use_shared_memory)
|
||||
{
|
||||
@@ -168,9 +168,10 @@ template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &con
|
||||
}
|
||||
}
|
||||
|
||||
template <> bool Engine<algorithm::CoreCH>::CheckCompability(const EngineConfig &config)
|
||||
template <>
|
||||
bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const EngineConfig &config)
|
||||
{
|
||||
if (!Engine<algorithm::CH>::CheckCompability(config))
|
||||
if (!Engine<routing_algorithms::ch::Algorithm>::CheckCompability(config))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -416,6 +416,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
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,
|
||||
forward_weight,
|
||||
reverse_weight,
|
||||
@@ -425,6 +439,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
reverse_duration,
|
||||
forward_duration_offset,
|
||||
reverse_duration_offset,
|
||||
is_forward_valid_source,
|
||||
is_forward_valid_target,
|
||||
is_reverse_valid_source,
|
||||
is_reverse_valid_target,
|
||||
point_on_segment,
|
||||
input_coordinate},
|
||||
current_perpendicular_distance};
|
||||
|
||||
@@ -170,10 +170,13 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
||||
weight = weight + target_weight;
|
||||
if (route_data.empty())
|
||||
{
|
||||
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
|
||||
: source_node.forward_duration);
|
||||
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;
|
||||
|
||||
@@ -222,10 +222,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
// u-------------v
|
||||
// | |---------| source_weight
|
||||
// | |---| target_weight
|
||||
BOOST_ASSERT(target_weight >= source_weight);
|
||||
const EdgeWeight weight = target_weight - source_weight;
|
||||
const EdgeWeight duration = target_duration - source_duration;
|
||||
BOOST_ASSERT(weight >= 0);
|
||||
BOOST_ASSERT(duration >= 0);
|
||||
|
||||
// use rectified linear unit function to avoid negative duration values
|
||||
// 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,
|
||||
facade.GetNameForID(source_node.name_id).to_string(),
|
||||
|
||||
@@ -46,37 +46,6 @@ namespace engine
|
||||
|
||||
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()
|
||||
: forward_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),
|
||||
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
||||
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 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; }
|
||||
|
||||
template <class OtherT>
|
||||
@@ -146,6 +134,10 @@ struct PhantomNode
|
||||
EdgeWeight reverse_duration,
|
||||
EdgeWeight forward_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 input_location)
|
||||
: forward_segment_id{other.forward_segment_id},
|
||||
@@ -159,7 +151,11 @@ struct PhantomNode
|
||||
component{other.component.id, other.component.is_tiny}, location{location},
|
||||
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
||||
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;
|
||||
// note 4 bits would suffice for each,
|
||||
// but the saved byte would be padding anyway
|
||||
extractor::TravelMode forward_travel_mode;
|
||||
extractor::TravelMode backward_travel_mode;
|
||||
extractor::TravelMode forward_travel_mode : 4;
|
||||
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");
|
||||
|
||||
@@ -54,11 +54,11 @@ class RoutingAlgorithmsInterface
|
||||
};
|
||||
|
||||
// Short-lived object passed to each plugin in request to wrap routing algorithms
|
||||
template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
|
||||
template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
|
||||
{
|
||||
public:
|
||||
RoutingAlgorithms(SearchEngineData &heaps,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade)
|
||||
RoutingAlgorithms(SearchEngineData<Algorithm> &heaps,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade)
|
||||
: heaps(heaps), facade(facade)
|
||||
{
|
||||
}
|
||||
@@ -93,49 +93,50 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
||||
|
||||
bool HasAlternativePathSearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasAlternativePathSearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasAlternativePathSearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasShortestPathSearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasShortestPathSearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasShortestPathSearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasDirectShortestPathSearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasDirectShortestPathSearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasDirectShortestPathSearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasMapMatching() const final override
|
||||
{
|
||||
return algorithm_trais::HasMapMatching<AlgorithmT>::value;
|
||||
return routing_algorithms::HasMapMatching<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasManyToManySearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasManyToManySearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasGetTileTurns() const final override
|
||||
{
|
||||
return algorithm_trais::HasGetTileTurns<AlgorithmT>::value;
|
||||
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
|
||||
}
|
||||
|
||||
private:
|
||||
SearchEngineData &heaps;
|
||||
SearchEngineData<Algorithm> &heaps;
|
||||
|
||||
// Owned by shared-ptr passed to the query
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade;
|
||||
};
|
||||
|
||||
template <typename AlgorithmT>
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<AlgorithmT>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||
{
|
||||
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult RoutingAlgorithms<Algorithm>::ShortestPathSearch(
|
||||
const std::vector<PhantomNodes> &phantom_node_pair,
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const
|
||||
{
|
||||
@@ -143,25 +144,25 @@ InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
|
||||
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<AlgorithmT>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
|
||||
RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
|
||||
{
|
||||
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
std::vector<EdgeWeight> RoutingAlgorithms<AlgorithmT>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const
|
||||
template <typename Algorithm>
|
||||
std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const
|
||||
{
|
||||
return routing_algorithms::manyToManySearch(
|
||||
return routing_algorithms::ch::manyToManySearch(
|
||||
heaps, facade, phantom_nodes, source_indices, target_indices);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMatching(
|
||||
template <typename Algorithm>
|
||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
@@ -177,52 +178,53 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMat
|
||||
allow_splitting);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<AlgorithmT>::GetTileTurns(
|
||||
template <typename Algorithm>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::GetTileTurns(
|
||||
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
const std::vector<std::size_t> &sorted_edge_indexes) const
|
||||
{
|
||||
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
|
||||
}
|
||||
|
||||
// CoreCH overrides
|
||||
template <>
|
||||
InternalRouteResult inline RoutingAlgorithms<
|
||||
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
throw util::exception("ManyToManySearch is disabled due to performance reasons");
|
||||
}
|
||||
|
||||
// MLD overrides for not implemented
|
||||
template <>
|
||||
InternalRouteResult inline RoutingAlgorithms<algorithm::MLD>::AlternativePathSearch(
|
||||
const PhantomNodes &) const
|
||||
InternalRouteResult inline RoutingAlgorithms<
|
||||
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline InternalRouteResult
|
||||
RoutingAlgorithms<algorithm::MLD>::ShortestPathSearch(const std::vector<PhantomNodes> &,
|
||||
const boost::optional<bool>) const
|
||||
{
|
||||
throw util::exception("ShortestPathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<algorithm::MLD>::ManyToManySearch(const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
throw util::exception("ManyToManySearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline routing_algorithms::SubMatchingList
|
||||
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
|
||||
const std::vector<util::Coordinate> &,
|
||||
const std::vector<unsigned> &,
|
||||
const std::vector<boost::optional<double>> &,
|
||||
const bool) const
|
||||
{
|
||||
throw util::exception("MapMatching is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<algorithm::MLD>::GetTileTurns(
|
||||
inline std::vector<routing_algorithms::TurnData>
|
||||
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::GetTileTurns(
|
||||
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
|
||||
@@ -15,12 +15,13 @@ namespace engine
|
||||
{
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
namespace ch
|
||||
{
|
||||
InternalRouteResult
|
||||
alternativePathSearch(SearchEngineData &search_engine_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const PhantomNodes &phantom_node_pair);
|
||||
|
||||
} // namespace ch
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -21,11 +21,20 @@ namespace routing_algorithms
|
||||
/// by the previous route.
|
||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||
/// not fully contracted graphs.
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult
|
||||
directShortestPathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -13,16 +13,18 @@ namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
namespace ch
|
||||
{
|
||||
std::vector<EdgeWeight>
|
||||
manyToManySearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices);
|
||||
} // namespace ch
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -22,25 +22,17 @@ static const constexpr double DEFAULT_GPS_PRECISION = 5;
|
||||
|
||||
//[1] "Hidden Markov Map Matching Through Noise and Sparseness";
|
||||
// P. Newson and J. Krumm; 2009; ACM GIS
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
template <typename Algorithm>
|
||||
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* MAP_MATCHING_HPP */
|
||||
|
||||
@@ -37,53 +37,48 @@ static constexpr bool FORWARD_DIRECTION = true;
|
||||
static constexpr bool REVERSE_DIRECTION = false;
|
||||
static constexpr bool DO_NOT_FORCE_LOOPS = false;
|
||||
|
||||
template <bool DIRECTION, typename Heap>
|
||||
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
||||
{
|
||||
BOOST_ASSERT(phantom_node.IsValid());
|
||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
template <bool DIRECTION>
|
||||
void insertNodesInHeap(SearchEngineData::ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
|
||||
{
|
||||
BOOST_ASSERT(phantom_node.IsValid());
|
||||
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||
const PhantomNode &phantom_node);
|
||||
|
||||
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()});
|
||||
}
|
||||
}
|
||||
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||
const PhantomNode &phantom_node);
|
||||
|
||||
template <typename Heap>
|
||||
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
||||
{
|
||||
insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
|
||||
insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
|
||||
const auto &source = nodes.source_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>
|
||||
@@ -169,7 +164,7 @@ void annotatePath(const FacadeT &facade,
|
||||
util::guidance::TurnBearing(0)});
|
||||
}
|
||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||
if (facade.hasLaneData(turn_id))
|
||||
if (facade.HasLaneData(turn_id))
|
||||
unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
|
||||
|
||||
unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
|
||||
@@ -305,6 +300,57 @@ void annotatePath(const FacadeT &facade,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Algorithm>
|
||||
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PathData> unpacked_path,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom)
|
||||
{
|
||||
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
|
||||
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
||||
|
||||
double distance = 0;
|
||||
double prev_lat = static_cast<double>(toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
double prev_lon = static_cast<double>(toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
double prev_cos = std::cos(prev_lat);
|
||||
for (const auto &p : unpacked_path)
|
||||
{
|
||||
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
||||
|
||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
distance += EARTH_RADIUS * charv;
|
||||
|
||||
prev_lat = current_lat;
|
||||
prev_lon = current_lon;
|
||||
prev_cos = current_cos;
|
||||
}
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
||||
|
||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
distance += EARTH_RADIUS * charv;
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ch
|
||||
|
||||
// Stalling
|
||||
template <bool DIRECTION, typename HeapT>
|
||||
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID node,
|
||||
const EdgeWeight weight,
|
||||
const HeapT &query_heap)
|
||||
@@ -49,10 +49,10 @@ bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
}
|
||||
|
||||
template <bool DIRECTION>
|
||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID node,
|
||||
const EdgeWeight weight,
|
||||
SearchEngineData::QueryHeap &heap)
|
||||
SearchEngineData<Algorithm>::QueryHeap &heap)
|
||||
{
|
||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
@@ -113,9 +113,9 @@ we need to add an offset to the termination criterion.
|
||||
static constexpr bool ENABLE_STALLING = true;
|
||||
static constexpr bool DISABLE_STALLING = false;
|
||||
template <bool DIRECTION, bool STALLING = ENABLE_STALLING>
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
NodeID &middle_node_id,
|
||||
EdgeWeight &upper_bound,
|
||||
EdgeWeight min_edge_offset,
|
||||
@@ -186,9 +186,8 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
}
|
||||
|
||||
template <bool UseDuration>
|
||||
EdgeWeight
|
||||
getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
NodeID node)
|
||||
EdgeWeight getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
NodeID node)
|
||||
{
|
||||
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||
@@ -228,7 +227,7 @@ getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH
|
||||
* original edge found.
|
||||
*/
|
||||
template <typename BidirectionalIterator, typename Callback>
|
||||
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
BidirectionalIterator packed_path_begin,
|
||||
BidirectionalIterator packed_path_end,
|
||||
Callback &&callback)
|
||||
@@ -325,17 +324,17 @@ void unpackPath(const FacadeT &facade,
|
||||
* @param to the node the CH edge finishes at
|
||||
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
|
||||
*/
|
||||
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID from,
|
||||
const NodeID to,
|
||||
std::vector<NodeID> &unpacked_path);
|
||||
|
||||
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
|
||||
const SearchEngineData::QueryHeap &reverse_heap,
|
||||
void retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
const SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID> &packed_path);
|
||||
|
||||
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
|
||||
void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &search_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID> &packed_path);
|
||||
|
||||
@@ -351,37 +350,33 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_
|
||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||
// requires
|
||||
// a force loop, if the heaps have been initialized with positive offsets.
|
||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
std::int32_t &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);
|
||||
|
||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
|
||||
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &,
|
||||
SearchEngineData::QueryHeap &,
|
||||
std::int32_t &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
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
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double
|
||||
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
} // namespace ch
|
||||
|
||||
namespace corech
|
||||
{
|
||||
// assumes that heaps are already setup correctly.
|
||||
// A forced loop might be necessary, if source and target are on the same segment.
|
||||
// If this is the case and the offsets of the respective direction are larger for the source
|
||||
@@ -391,66 +386,41 @@ inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorith
|
||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||
// requires
|
||||
// a force loop, if the heaps have been initialized with positive offsets.
|
||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &forward_core_heap,
|
||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
||||
int &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const std::vector<NodeID> &packed_path,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom);
|
||||
|
||||
// Requires the heaps for be empty
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double
|
||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &forward_core_heap,
|
||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
// Requires the heaps for be empty
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double
|
||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
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<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &,
|
||||
SearchEngineData::QueryHeap &,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
template <typename RandomIter, typename FacadeT>
|
||||
void unpackPath(const FacadeT &facade,
|
||||
RandomIter packed_path_begin,
|
||||
RandomIter packed_path_end,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
std::vector<PathData> &unpacked_path)
|
||||
{
|
||||
return getNetworkDistance(
|
||||
facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
|
||||
return ch::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
|
||||
}
|
||||
|
||||
} // namespace ch
|
||||
} // namespace corech
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace
|
||||
// Unrestricted search (Args is const PhantomNodes &):
|
||||
// * use partition.GetQueryLevel to find the node query level based on source and target phantoms
|
||||
// * allow to traverse all cells
|
||||
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
|
||||
NodeID node,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
inline LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
|
||||
NodeID node,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
{
|
||||
auto level = [&partition, node](const SegmentID &source, const SegmentID &target) {
|
||||
if (source.enabled && target.enabled)
|
||||
@@ -43,25 +43,31 @@ LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
|
||||
phantom_nodes.target_phantom.reverse_segment_id)));
|
||||
}
|
||||
|
||||
bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
|
||||
inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
|
||||
|
||||
// Restricted search (Args is LevelID, CellID):
|
||||
// * use the fixed level for queries
|
||||
// * check if the node cell is the same as the specified parent onr
|
||||
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
|
||||
inline LevelID
|
||||
getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
bool checkParentCellRestriction(CellID cell, LevelID, CellID parent) { return cell == parent; }
|
||||
inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
|
||||
{
|
||||
return cell == parent;
|
||||
}
|
||||
}
|
||||
|
||||
template <bool DIRECTION, typename... Args>
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
NodeID &middle_node,
|
||||
EdgeWeight &path_upper_bound,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
Args... args)
|
||||
{
|
||||
const auto &partition = facade.GetMultiLevelPartition();
|
||||
@@ -79,7 +85,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
{
|
||||
auto reverse_weight = reverse_heap.GetKey(node);
|
||||
auto path_weight = weight + reverse_weight;
|
||||
if (path_weight >= 0 && path_weight < path_upper_bound)
|
||||
|
||||
// if loops are forced, they are so at the source
|
||||
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
|
||||
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
|
||||
(path_weight >= 0) && (path_weight < path_upper_bound))
|
||||
{
|
||||
middle_node = node;
|
||||
path_upper_bound = path_weight;
|
||||
@@ -171,11 +181,20 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
|
||||
template <typename... Args>
|
||||
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
|
||||
search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
|
||||
search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
EdgeWeight weight_upper_bound,
|
||||
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();
|
||||
|
||||
@@ -184,7 +203,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
|
||||
// run two-Target Dijkstra routing step.
|
||||
NodeID middle = SPECIAL_NODEID;
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
EdgeWeight weight = weight_upper_bound;
|
||||
EdgeWeight forward_heap_min = forward_heap.MinKey();
|
||||
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
|
||||
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
||||
@@ -192,22 +211,34 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
{
|
||||
if (!forward_heap.Empty())
|
||||
{
|
||||
routingStep<FORWARD_DIRECTION>(
|
||||
facade, forward_heap, reverse_heap, middle, weight, args...);
|
||||
routingStep<FORWARD_DIRECTION>(facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
middle,
|
||||
weight,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
args...);
|
||||
if (!forward_heap.Empty())
|
||||
forward_heap_min = forward_heap.MinKey();
|
||||
}
|
||||
if (!reverse_heap.Empty())
|
||||
{
|
||||
routingStep<REVERSE_DIRECTION>(
|
||||
facade, reverse_heap, forward_heap, middle, weight, args...);
|
||||
routingStep<REVERSE_DIRECTION>(facade,
|
||||
reverse_heap,
|
||||
forward_heap,
|
||||
middle,
|
||||
weight,
|
||||
force_loop_reverse,
|
||||
force_loop_forward,
|
||||
args...);
|
||||
if (!reverse_heap.Empty())
|
||||
reverse_heap_min = reverse_heap.MinKey();
|
||||
}
|
||||
};
|
||||
|
||||
// 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(
|
||||
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||
@@ -268,7 +299,15 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
NodeID subpath_source, subpath_target;
|
||||
std::vector<EdgeID> subpath;
|
||||
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
||||
search(facade, forward_heap, reverse_heap, sublevel, parent_cell_id);
|
||||
search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!subpath.empty());
|
||||
BOOST_ASSERT(subpath_source == source);
|
||||
BOOST_ASSERT(subpath_target == target);
|
||||
@@ -279,6 +318,105 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
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
|
||||
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
EdgeWeight &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
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,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
|
||||
if (weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
packed_leg.push_back(source_node);
|
||||
std::transform(unpacked_edges.begin(),
|
||||
unpacked_edges.end(),
|
||||
std::back_inserter(packed_leg),
|
||||
[&facade](const auto edge) { return facade.GetTarget(edge); });
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RandomIter, typename FacadeT>
|
||||
void unpackPath(const FacadeT &facade,
|
||||
RandomIter packed_path_begin,
|
||||
RandomIter packed_path_end,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
std::vector<PathData> &unpacked_path)
|
||||
{
|
||||
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
|
||||
BOOST_ASSERT(nodes_number > 0);
|
||||
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
|
||||
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
|
||||
|
||||
if (nodes_number > 1)
|
||||
{
|
||||
target_node = *std::prev(packed_path_end);
|
||||
util::for_each_pair(packed_path_begin,
|
||||
packed_path_end,
|
||||
[&facade, &unpacked_edges](const auto from, const auto to) {
|
||||
unpacked_edges.push_back(facade.FindEdge(from, to));
|
||||
});
|
||||
}
|
||||
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
}
|
||||
|
||||
inline double
|
||||
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
|
||||
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
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,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
return std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
std::vector<PathData> unpacked_path;
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
|
||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
||||
}
|
||||
|
||||
} // namespace mld
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -13,15 +13,10 @@ namespace engine
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ struct TurnData final
|
||||
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
||||
|
||||
std::vector<TurnData>
|
||||
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
const std::vector<RTreeLeaf> &edges,
|
||||
const std::vector<std::size_t> &sorted_edge_indexes);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
#include "engine/algorithm.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -12,6 +12,16 @@ namespace osrm
|
||||
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
|
||||
{
|
||||
NodeID parent;
|
||||
@@ -24,14 +34,7 @@ struct ManyToManyHeapData : HeapData
|
||||
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
|
||||
};
|
||||
|
||||
struct MultiLayerDijkstraHeapData : HeapData
|
||||
{
|
||||
bool from_clique_arc;
|
||||
MultiLayerDijkstraHeapData(NodeID p) : HeapData(p), from_clique_arc(false) {}
|
||||
MultiLayerDijkstraHeapData(NodeID p, bool from) : HeapData(p), from_clique_arc(from) {}
|
||||
};
|
||||
|
||||
struct SearchEngineData
|
||||
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||
{
|
||||
using QueryHeap = util::
|
||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||
@@ -45,14 +48,6 @@ struct SearchEngineData
|
||||
|
||||
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
|
||||
|
||||
using MultiLayerDijkstraHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
MultiLayerDijkstraHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
|
||||
using MultiLayerDijkstraHeapPtr = boost::thread_specific_ptr<MultiLayerDijkstraHeap>;
|
||||
|
||||
static SearchEngineHeapPtr forward_heap_1;
|
||||
static SearchEngineHeapPtr reverse_heap_1;
|
||||
static SearchEngineHeapPtr forward_heap_2;
|
||||
@@ -60,18 +55,44 @@ struct SearchEngineData
|
||||
static SearchEngineHeapPtr forward_heap_3;
|
||||
static SearchEngineHeapPtr reverse_heap_3;
|
||||
static ManyToManyHeapPtr many_to_many_heap;
|
||||
static MultiLayerDijkstraHeapPtr mld_forward_heap;
|
||||
static MultiLayerDijkstraHeapPtr mld_reverse_heap;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearManyToManyThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||
};
|
||||
|
||||
void InitializeOrClearMultiLayerDijkstraThreadLocalStorage(const unsigned number_of_nodes);
|
||||
template <>
|
||||
struct SearchEngineData<routing_algorithms::corech::Algorithm>
|
||||
: public SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||
{
|
||||
};
|
||||
|
||||
struct MultiLayerDijkstraHeapData
|
||||
{
|
||||
NodeID parent;
|
||||
bool from_clique_arc;
|
||||
MultiLayerDijkstraHeapData(NodeID p) : parent(p), from_clique_arc(false) {}
|
||||
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
|
||||
};
|
||||
|
||||
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
||||
{
|
||||
using QueryHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
MultiLayerDijkstraHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
|
||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||
|
||||
static SearchEngineHeapPtr forward_heap_1;
|
||||
static SearchEngineHeapPtr reverse_heap_1;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
@@ -72,7 +73,8 @@ class EdgeBasedGraphFactory
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::PackedVector<OSMNodeID> &osm_node_ids,
|
||||
ProfileProperties profile_properties,
|
||||
const util::NameTable &name_table,
|
||||
std::vector<std::uint32_t> &turn_lane_offsets,
|
||||
@@ -128,7 +130,8 @@ class EdgeBasedGraphFactory
|
||||
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||
EdgeID m_max_edge_id;
|
||||
|
||||
const std::vector<QueryNode> &m_node_info_list;
|
||||
const std::vector<util::Coordinate> &m_coordinates;
|
||||
const util::PackedVector<OSMNodeID> &m_osm_node_ids;
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
|
||||
std::shared_ptr<RestrictionMap const> m_restriction_map;
|
||||
|
||||
@@ -156,9 +159,6 @@ class EdgeBasedGraphFactory
|
||||
|
||||
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 skipped_uturns_counter;
|
||||
std::size_t skipped_barrier_turns_counter;
|
||||
|
||||
@@ -58,7 +58,8 @@ class Extractor
|
||||
|
||||
std::pair<std::size_t, EdgeID>
|
||||
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<QueryNode> &internal_to_external_node_map,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids,
|
||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
@@ -66,18 +67,18 @@ class Extractor
|
||||
const std::string &intersection_class_output_file);
|
||||
void WriteProfileProperties(const std::string &output_path,
|
||||
const ProfileProperties &properties) const;
|
||||
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<EdgeBasedEdge> &edges,
|
||||
std::vector<EdgeBasedNode> &nodes) const;
|
||||
void BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
|
||||
std::vector<bool> node_is_startpoint,
|
||||
const std::vector<QueryNode> &internal_to_external_node_map);
|
||||
const std::vector<util::Coordinate> &coordinates);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph>
|
||||
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||
std::unordered_set<NodeID> &traffic_lights,
|
||||
std::vector<QueryNode> &internal_to_external_node_map);
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids);
|
||||
|
||||
void WriteEdgeBasedGraph(const std::string &output_file_filename,
|
||||
const EdgeID max_edge_id,
|
||||
@@ -94,7 +95,7 @@ class Extractor
|
||||
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
|
||||
static void WriteCompressedNodeBasedGraph(const std::string &path,
|
||||
const util::NodeBasedDynamicGraph &graph,
|
||||
const std::vector<QueryNode> &externals);
|
||||
const std::vector<util::Coordinate> &coordiantes);
|
||||
|
||||
// globals persisting during the extraction process and the graph generation process
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
#ifndef OSRM_EXTRACTOR_FILES_HPP
|
||||
#define OSRM_EXTRACTOR_FILES_HPP
|
||||
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/serialization.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/serialization.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace files
|
||||
{
|
||||
|
||||
// reads .osrm.nodes
|
||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||
inline void readNodes(const boost::filesystem::path &path,
|
||||
CoordinatesT &coordinates,
|
||||
PackedOSMIDsT &osm_node_ids)
|
||||
{
|
||||
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, coordinates);
|
||||
util::serialization::read(reader, osm_node_ids);
|
||||
}
|
||||
|
||||
// writes .osrm.nodes
|
||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||
inline void writeNodes(const boost::filesystem::path &path,
|
||||
const CoordinatesT &coordinates,
|
||||
const PackedOSMIDsT &osm_node_ids)
|
||||
{
|
||||
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, coordinates);
|
||||
util::serialization::write(writer, osm_node_ids);
|
||||
}
|
||||
|
||||
// reads .osrm.cnbg_to_ebg
|
||||
inline void readNBGMapping(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, mapping);
|
||||
}
|
||||
|
||||
// writes .osrm.cnbg_to_ebg
|
||||
inline void writeNBGMapping(const boost::filesystem::path &path,
|
||||
const std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, mapping);
|
||||
}
|
||||
|
||||
// reads .osrm.datasource_names
|
||||
inline void readDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, sources);
|
||||
}
|
||||
|
||||
// writes .osrm.datasource_names
|
||||
inline void writeDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, sources);
|
||||
}
|
||||
|
||||
// reads .osrm.geometry
|
||||
template <typename SegmentDataT>
|
||||
inline void readSegmentData(const boost::filesystem::path &path, SegmentDataT &segment_data)
|
||||
{
|
||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, segment_data);
|
||||
}
|
||||
|
||||
// writes .osrm.geometry
|
||||
template <typename SegmentDataT>
|
||||
inline void writeSegmentData(const boost::filesystem::path &path, const SegmentDataT &segment_data)
|
||||
{
|
||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, segment_data);
|
||||
}
|
||||
|
||||
// reads .osrm.edges
|
||||
template <typename TurnDataT>
|
||||
inline void readTurnData(const boost::filesystem::path &path, TurnDataT &turn_data)
|
||||
{
|
||||
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
||||
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, turn_data);
|
||||
}
|
||||
|
||||
// writes .osrm.edges
|
||||
template <typename TurnDataT>
|
||||
inline void writeTurnData(const boost::filesystem::path &path, const TurnDataT &turn_data)
|
||||
{
|
||||
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
||||
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, turn_data);
|
||||
}
|
||||
|
||||
// reads .osrm.tls
|
||||
template <typename OffsetsT, typename MaskT>
|
||||
inline void readTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
OffsetsT &turn_offsets,
|
||||
MaskT &turn_masks)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<typename MaskT::value_type, extractor::guidance::TurnLaneType::Mask>::value,
|
||||
"");
|
||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, turn_offsets);
|
||||
storage::serialization::read(reader, turn_masks);
|
||||
}
|
||||
|
||||
// writes .osrm.tls
|
||||
template <typename OffsetsT, typename MaskT>
|
||||
inline void writeTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
const OffsetsT &turn_offsets,
|
||||
const MaskT &turn_masks)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<typename MaskT::value_type, extractor::guidance::TurnLaneType::Mask>::value,
|
||||
"");
|
||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, turn_offsets);
|
||||
storage::serialization::write(writer, turn_masks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@ class CoordinateExtractor
|
||||
public:
|
||||
CoordinateExtractor(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const std::vector<extractor::QueryNode> &node_coordinates);
|
||||
const std::vector<util::Coordinate> &node_coordinates);
|
||||
|
||||
/* Find a interpolated coordinate a long the compressed geometries. The desired coordinate
|
||||
* should be in a certain distance. This method is dedicated to find representative coordinates
|
||||
@@ -156,7 +156,7 @@ class CoordinateExtractor
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const std::vector<extractor::QueryNode> &node_coordinates;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
|
||||
double ComputeInterpolationFactor(const double desired_distance,
|
||||
const double distance_to_first,
|
||||
|
||||
@@ -40,7 +40,7 @@ class IntersectionGenerator
|
||||
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container);
|
||||
|
||||
// For a source node `a` and a via edge `ab` creates an intersection at target `b`.
|
||||
@@ -112,7 +112,7 @@ class IntersectionGenerator
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const RestrictionMap &restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const std::vector<QueryNode> &node_info_list;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
|
||||
// own state, used to find the correct coordinates along a road
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
|
||||
@@ -34,7 +34,7 @@ class IntersectionHandler
|
||||
{
|
||||
public:
|
||||
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
@@ -51,7 +51,7 @@ class IntersectionHandler
|
||||
|
||||
protected:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const std::vector<QueryNode> &node_info_list;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
const util::NameTable &name_table;
|
||||
const SuffixTable &street_name_suffix_table;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
|
||||
@@ -43,7 +43,7 @@ class IntersectionNormalizer
|
||||
std::vector<IntersectionNormalizationOperation> performed_merges;
|
||||
};
|
||||
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<extractor::QueryNode> &node_coordinates,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -22,7 +23,6 @@ class NameTable;
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct QueryNode;
|
||||
class SuffixTable;
|
||||
|
||||
namespace guidance
|
||||
@@ -37,7 +37,7 @@ class MergableRoadDetector
|
||||
using MergableRoadData = IntersectionShapeData;
|
||||
|
||||
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_coordinates,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const IntersectionGenerator &intersection_generator,
|
||||
const CoordinateExtractor &coordinate_extractor,
|
||||
const util::NameTable &name_table,
|
||||
@@ -138,7 +138,7 @@ class MergableRoadDetector
|
||||
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
|
||||
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const std::vector<QueryNode> &node_coordinates;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const CoordinateExtractor &coordinate_extractor;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class MotorwayHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
@@ -41,7 +41,7 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
|
||||
@@ -27,7 +27,7 @@ class SliproadHandler final : public IntersectionHandler
|
||||
public:
|
||||
SliproadHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class SuppressModeHandler final : public IntersectionHandler
|
||||
public:
|
||||
SuppressModeHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class TurnAnalysis
|
||||
{
|
||||
public:
|
||||
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
|
||||
@@ -29,7 +29,7 @@ class TurnHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_IO_HPP
|
||||
#define OSRM_EXTRACTOR_IO_HPP
|
||||
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
inline void read(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(mapping);
|
||||
}
|
||||
|
||||
inline void write(const boost::filesystem::path &path, const std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter reader{path, fingerprint};
|
||||
|
||||
reader.SerializeVector(mapping);
|
||||
}
|
||||
|
||||
inline void read(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.ReadInto(sources);
|
||||
}
|
||||
|
||||
inline void write(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteFrom(sources);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void read(const boost::filesystem::path &path, SegmentDataContainer &segment_data)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
auto num_indices = reader.ReadElementCount32();
|
||||
segment_data.index.resize(num_indices);
|
||||
reader.ReadInto(segment_data.index.data(), num_indices);
|
||||
|
||||
auto num_entries = reader.ReadElementCount32();
|
||||
segment_data.nodes.resize(num_entries);
|
||||
segment_data.fwd_weights.resize(num_entries);
|
||||
segment_data.rev_weights.resize(num_entries);
|
||||
segment_data.fwd_durations.resize(num_entries);
|
||||
segment_data.rev_durations.resize(num_entries);
|
||||
segment_data.datasources.resize(num_entries);
|
||||
|
||||
reader.ReadInto(segment_data.nodes);
|
||||
reader.ReadInto(segment_data.fwd_weights);
|
||||
reader.ReadInto(segment_data.rev_weights);
|
||||
reader.ReadInto(segment_data.fwd_durations);
|
||||
reader.ReadInto(segment_data.rev_durations);
|
||||
reader.ReadInto(segment_data.datasources);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void write(const boost::filesystem::path &path, const SegmentDataContainer &segment_data)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteElementCount32(segment_data.index.size());
|
||||
writer.WriteFrom(segment_data.index);
|
||||
|
||||
writer.WriteElementCount32(segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.fwd_weights.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.rev_weights.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.fwd_durations.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.rev_durations.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.datasources.size() == segment_data.nodes.size());
|
||||
writer.WriteFrom(segment_data.nodes);
|
||||
writer.WriteFrom(segment_data.fwd_weights);
|
||||
writer.WriteFrom(segment_data.rev_weights);
|
||||
writer.WriteFrom(segment_data.fwd_durations);
|
||||
writer.WriteFrom(segment_data.rev_durations);
|
||||
writer.WriteFrom(segment_data.datasources);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,10 @@
|
||||
#ifndef OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
|
||||
#define OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
|
||||
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -27,13 +28,13 @@ namespace detail
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl;
|
||||
}
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
}
|
||||
|
||||
@@ -41,7 +42,7 @@ namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
friend CompressedEdgeContainer;
|
||||
|
||||
@@ -190,11 +191,12 @@ template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
auto GetNumberOfGeometries() const { return index.size() - 1; }
|
||||
auto GetNumberOfSegments() const { return fwd_weights.size(); }
|
||||
|
||||
friend void io::read<Ownership>(const boost::filesystem::path &path,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
friend void
|
||||
io::write<Ownership>(const boost::filesystem::path &path,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
friend void serialization::write<Ownership>(
|
||||
storage::io::FileWriter &writer,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
|
||||
private:
|
||||
Vector<std::uint32_t> index;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef OSRM_EXTRACTOR_IO_HPP
|
||||
#define OSRM_EXTRACTOR_IO_HPP
|
||||
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/serialization.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
inline void read(storage::io::FileReader &reader, Datasources &sources)
|
||||
{
|
||||
reader.ReadInto(sources);
|
||||
}
|
||||
|
||||
inline void write(storage::io::FileWriter &writer, Datasources &sources)
|
||||
{
|
||||
writer.WriteFrom(sources);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data)
|
||||
{
|
||||
storage::serialization::read(reader, segment_data.index);
|
||||
storage::serialization::read(reader, segment_data.nodes);
|
||||
storage::serialization::read(reader, segment_data.fwd_weights);
|
||||
storage::serialization::read(reader, segment_data.rev_weights);
|
||||
storage::serialization::read(reader, segment_data.fwd_durations);
|
||||
storage::serialization::read(reader, segment_data.rev_durations);
|
||||
storage::serialization::read(reader, segment_data.datasources);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data)
|
||||
{
|
||||
storage::serialization::write(writer, segment_data.index);
|
||||
storage::serialization::write(writer, segment_data.nodes);
|
||||
storage::serialization::write(writer, segment_data.fwd_weights);
|
||||
storage::serialization::write(writer, segment_data.rev_weights);
|
||||
storage::serialization::write(writer, segment_data.fwd_durations);
|
||||
storage::serialization::write(writer, segment_data.rev_durations);
|
||||
storage::serialization::write(writer, segment_data.datasources);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::TurnDataContainerImpl<Ownership> &turn_data_container)
|
||||
{
|
||||
storage::serialization::read(reader, turn_data_container.geometry_ids);
|
||||
storage::serialization::read(reader, turn_data_container.name_ids);
|
||||
storage::serialization::read(reader, turn_data_container.turn_instructions);
|
||||
storage::serialization::read(reader, turn_data_container.lane_data_ids);
|
||||
storage::serialization::read(reader, turn_data_container.travel_modes);
|
||||
storage::serialization::read(reader, turn_data_container.entry_class_ids);
|
||||
storage::serialization::read(reader, turn_data_container.pre_turn_bearings);
|
||||
storage::serialization::read(reader, turn_data_container.post_turn_bearings);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::TurnDataContainerImpl<Ownership> &turn_data_container)
|
||||
{
|
||||
storage::serialization::write(writer, turn_data_container.geometry_ids);
|
||||
storage::serialization::write(writer, turn_data_container.name_ids);
|
||||
storage::serialization::write(writer, turn_data_container.turn_instructions);
|
||||
storage::serialization::write(writer, turn_data_container.lane_data_ids);
|
||||
storage::serialization::write(writer, turn_data_container.travel_modes);
|
||||
storage::serialization::write(writer, turn_data_container.entry_class_ids);
|
||||
storage::serialization::write(writer, turn_data_container.pre_turn_bearings);
|
||||
storage::serialization::write(writer, turn_data_container.post_turn_bearings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
#ifndef OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
|
||||
#define OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
|
||||
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/guidance/turn_bearing.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class TurnDataContainerImpl;
|
||||
}
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
void read(storage::io::FileReader &reader, detail::TurnDataContainerImpl<Ownership> &turn_data);
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
void write(storage::io::FileWriter &writer,
|
||||
const detail::TurnDataContainerImpl<Ownership> &turn_data);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class TurnDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
TurnDataContainerImpl() = default;
|
||||
|
||||
TurnDataContainerImpl(Vector<GeometryID> geometry_ids_,
|
||||
Vector<NameID> name_ids_,
|
||||
Vector<extractor::guidance::TurnInstruction> turn_instructions_,
|
||||
Vector<LaneDataID> lane_data_ids_,
|
||||
Vector<extractor::TravelMode> travel_modes_,
|
||||
Vector<EntryClassID> entry_class_ids_,
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings_,
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings_)
|
||||
: geometry_ids(std::move(geometry_ids_)), name_ids(std::move(name_ids_)),
|
||||
turn_instructions(std::move(turn_instructions_)),
|
||||
lane_data_ids(std::move(lane_data_ids_)), travel_modes(std::move(travel_modes_)),
|
||||
entry_class_ids(std::move(entry_class_ids_)),
|
||||
pre_turn_bearings(std::move(pre_turn_bearings_)),
|
||||
post_turn_bearings(std::move(post_turn_bearings_))
|
||||
{
|
||||
}
|
||||
|
||||
GeometryID GetGeometryID(const EdgeID id) const { return geometry_ids[id]; }
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
|
||||
|
||||
extractor::TravelMode GetTravelMode(const EdgeID id) const { return travel_modes[id]; }
|
||||
|
||||
util::guidance::TurnBearing GetPreTurnBearing(const EdgeID id) const
|
||||
{
|
||||
return pre_turn_bearings[id];
|
||||
}
|
||||
|
||||
util::guidance::TurnBearing GetPostTurnBearing(const EdgeID id) const
|
||||
{
|
||||
return post_turn_bearings[id];
|
||||
}
|
||||
|
||||
LaneDataID GetLaneDataID(const EdgeID id) const { return lane_data_ids[id]; }
|
||||
|
||||
bool HasLaneData(const EdgeID id) const { return INVALID_LANE_DATAID != lane_data_ids[id]; }
|
||||
|
||||
NameID GetNameID(const EdgeID id) const { return name_ids[id]; }
|
||||
|
||||
extractor::guidance::TurnInstruction GetTurnInstruction(const EdgeID id) const
|
||||
{
|
||||
return turn_instructions[id];
|
||||
}
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void push_back(GeometryID geometry_id,
|
||||
NameID name_id,
|
||||
extractor::guidance::TurnInstruction turn_instruction,
|
||||
LaneDataID lane_data_id,
|
||||
EntryClassID entry_class_id,
|
||||
extractor::TravelMode travel_mode,
|
||||
util::guidance::TurnBearing pre_turn_bearing,
|
||||
util::guidance::TurnBearing post_turn_bearing)
|
||||
{
|
||||
geometry_ids.push_back(geometry_id);
|
||||
name_ids.push_back(name_id);
|
||||
turn_instructions.push_back(turn_instruction);
|
||||
lane_data_ids.push_back(lane_data_id);
|
||||
travel_modes.push_back(travel_mode);
|
||||
entry_class_ids.push_back(entry_class_id);
|
||||
pre_turn_bearings.push_back(pre_turn_bearing);
|
||||
post_turn_bearings.push_back(post_turn_bearing);
|
||||
}
|
||||
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
TurnDataContainerImpl &turn_data_container);
|
||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const TurnDataContainerImpl &turn_data_container);
|
||||
|
||||
private:
|
||||
Vector<GeometryID> geometry_ids;
|
||||
Vector<NameID> name_ids;
|
||||
Vector<extractor::guidance::TurnInstruction> turn_instructions;
|
||||
Vector<LaneDataID> lane_data_ids;
|
||||
Vector<extractor::TravelMode> travel_modes;
|
||||
Vector<EntryClassID> entry_class_ids;
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings;
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings;
|
||||
};
|
||||
}
|
||||
|
||||
using TurnDataExternalContainer = detail::TurnDataContainerImpl<storage::Ownership::External>;
|
||||
using TurnDataContainer = detail::TurnDataContainerImpl<storage::Ownership::Container>;
|
||||
using TurnDataView = detail::TurnDataContainerImpl<storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "osrm/trip_parameters.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/make_unique.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#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)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
auto engine_config = boost::make_unique<osrm::EngineConfig>();
|
||||
auto engine_config = std::make_unique<osrm::EngineConfig>();
|
||||
|
||||
if (args.Length() == 0)
|
||||
{
|
||||
@@ -631,7 +630,7 @@ inline route_parameters_ptr
|
||||
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
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);
|
||||
if (!has_base_params)
|
||||
return route_parameters_ptr();
|
||||
@@ -681,7 +680,7 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
inline tile_parameters_ptr
|
||||
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)
|
||||
{
|
||||
@@ -742,7 +741,7 @@ inline nearest_parameters_ptr
|
||||
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
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);
|
||||
if (!has_base_params)
|
||||
return nearest_parameters_ptr();
|
||||
@@ -781,7 +780,7 @@ inline table_parameters_ptr
|
||||
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
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);
|
||||
if (!has_base_params)
|
||||
return table_parameters_ptr();
|
||||
@@ -875,7 +874,7 @@ inline trip_parameters_ptr
|
||||
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
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);
|
||||
if (!has_base_params)
|
||||
return trip_parameters_ptr();
|
||||
@@ -970,7 +969,7 @@ inline match_parameters_ptr
|
||||
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
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);
|
||||
if (!has_base_params)
|
||||
return match_parameters_ptr();
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
#include "util/assert.hpp"
|
||||
#include "util/for_each_range.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
@@ -32,12 +32,12 @@ template <storage::Ownership Ownership> class CellStorageImpl;
|
||||
using CellStorage = detail::CellStorageImpl<storage::Ownership::Container>;
|
||||
using CellStorageView = detail::CellStorageImpl<storage::Ownership::View>;
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(const boost::filesystem::path &path, detail::CellStorageImpl<Ownership> &storage);
|
||||
inline void read(storage::io::FileReader &reader, detail::CellStorageImpl<Ownership> &storage);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
// Implementation of the cell view. We need a template parameter here
|
||||
// because we need to derive a read-only and read-write view from this.
|
||||
@@ -352,10 +352,10 @@ template <storage::Ownership Ownership> class CellStorageImpl
|
||||
cells[cell_index], weights.data(), source_boundary.data(), destination_boundary.data()};
|
||||
}
|
||||
|
||||
friend void io::read<Ownership>(const boost::filesystem::path &path,
|
||||
detail::CellStorageImpl<Ownership> &storage);
|
||||
friend void io::write<Ownership>(const boost::filesystem::path &path,
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
detail::CellStorageImpl<Ownership> &storage);
|
||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
|
||||
private:
|
||||
Vector<EdgeWeight> weights;
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef OSRM_PARTITION_SERILIZATION_HPP
|
||||
#define OSRM_PARTITION_SERILIZATION_HPP
|
||||
|
||||
#include "customizer/edge_based_graph.hpp"
|
||||
|
||||
#include "partition/serialization.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace files
|
||||
{
|
||||
|
||||
// reads .osrm.mldgr file
|
||||
template <typename MultiLevelGraphT>
|
||||
inline void readGraph(const boost::filesystem::path &path, MultiLevelGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
|
||||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, graph);
|
||||
}
|
||||
|
||||
// writes .osrm.mldgr file
|
||||
template <typename MultiLevelGraphT>
|
||||
inline void writeGraph(const boost::filesystem::path &path, const MultiLevelGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
|
||||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, graph);
|
||||
}
|
||||
|
||||
// read .osrm.partition file
|
||||
template <typename MultiLevelPartitionT>
|
||||
inline void readPartition(const boost::filesystem::path &path, MultiLevelPartitionT &mlp)
|
||||
{
|
||||
static_assert(std::is_same<MultiLevelPartitionView, MultiLevelPartitionT>::value ||
|
||||
std::is_same<MultiLevelPartition, MultiLevelPartitionT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, mlp);
|
||||
}
|
||||
|
||||
// writes .osrm.partition file
|
||||
template <typename MultiLevelPartitionT>
|
||||
inline void writePartition(const boost::filesystem::path &path, const MultiLevelPartitionT &mlp)
|
||||
{
|
||||
static_assert(std::is_same<MultiLevelPartitionView, MultiLevelPartitionT>::value ||
|
||||
std::is_same<MultiLevelPartition, MultiLevelPartitionT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, mlp);
|
||||
}
|
||||
|
||||
// reads .osrm.cells file
|
||||
template <typename CellStorageT>
|
||||
inline void readCells(const boost::filesystem::path &path, CellStorageT &storage)
|
||||
{
|
||||
static_assert(std::is_same<CellStorageView, CellStorageT>::value ||
|
||||
std::is_same<CellStorage, CellStorageT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, storage);
|
||||
}
|
||||
|
||||
// writes .osrm.cells file
|
||||
template <typename CellStorageT>
|
||||
inline void writeCells(const boost::filesystem::path &path, CellStorageT &storage)
|
||||
{
|
||||
static_assert(std::is_same<CellStorageView, CellStorageT>::value ||
|
||||
std::is_same<CellStorage, CellStorageT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,89 +0,0 @@
|
||||
#ifndef OSRM_PARTITION_IO_HPP
|
||||
#define OSRM_PARTITION_IO_HPP
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/edge_based_graph.hpp"
|
||||
#include "partition/multi_level_graph.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(graph.node_array);
|
||||
reader.DeserializeVector(graph.edge_array);
|
||||
reader.DeserializeVector(graph.edge_to_level);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.SerializeVector(graph.node_array);
|
||||
writer.SerializeVector(graph.edge_array);
|
||||
writer.SerializeVector(graph.node_to_edge_offset);
|
||||
}
|
||||
|
||||
template <> inline void read(const boost::filesystem::path &path, MultiLevelPartition &mlp)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.ReadInto<MultiLevelPartition::LevelData>(mlp.level_data);
|
||||
reader.DeserializeVector(mlp.partition);
|
||||
reader.DeserializeVector(mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <> inline void write(const boost::filesystem::path &path, const MultiLevelPartition &mlp)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteOne(mlp.level_data);
|
||||
writer.SerializeVector(mlp.partition);
|
||||
writer.SerializeVector(mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <> inline void read(const boost::filesystem::path &path, CellStorage &storage)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(storage.weights);
|
||||
reader.DeserializeVector(storage.source_boundary);
|
||||
reader.DeserializeVector(storage.destination_boundary);
|
||||
reader.DeserializeVector(storage.cells);
|
||||
reader.DeserializeVector(storage.level_to_cell_offset);
|
||||
}
|
||||
|
||||
template <> inline void write(const boost::filesystem::path &path, const CellStorage &storage)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.SerializeVector(storage.weights);
|
||||
writer.SerializeVector(storage.source_boundary);
|
||||
writer.SerializeVector(storage.destination_boundary);
|
||||
writer.SerializeVector(storage.cells);
|
||||
writer.SerializeVector(storage.level_to_cell_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
@@ -14,17 +16,18 @@
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
namespace partition
|
||||
{
|
||||
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
void read(storage::io::FileReader &reader, MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void write(const boost::filesystem::path &path, const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
void write(storage::io::FileWriter &writer, const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
@@ -32,7 +35,7 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
||||
{
|
||||
private:
|
||||
using SuperT = util::StaticGraph<EdgeDataT, Ownership>;
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
// We limit each node to have 255 edges
|
||||
@@ -190,10 +193,12 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
||||
node_to_edge_offset.push_back(mlp.GetNumberOfLevels());
|
||||
}
|
||||
|
||||
friend void io::read<EdgeDataT, Ownership>(const boost::filesystem::path &path,
|
||||
MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
friend void io::write<EdgeDataT, Ownership>(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
friend void
|
||||
serialization::read<EdgeDataT, Ownership>(storage::io::FileReader &reader,
|
||||
MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
friend void
|
||||
serialization::write<EdgeDataT, Ownership>(storage::io::FileWriter &writer,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
Vector<EdgeOffset> node_to_edge_offset;
|
||||
};
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#include "util/exception.hpp"
|
||||
#include "util/for_each_pair.hpp"
|
||||
#include "util/msb.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -31,13 +31,12 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl;
|
||||
using MultiLevelPartition = detail::MultiLevelPartitionImpl<storage::Ownership::Container>;
|
||||
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<storage::Ownership::View>;
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
void read(const boost::filesystem::path &file, detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
void read(storage::io::FileReader &reader, detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
template <storage::Ownership Ownership>
|
||||
void write(const boost::filesystem::path &file,
|
||||
const detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
void write(storage::io::FileWriter &writer, const detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
@@ -49,7 +48,7 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
static const constexpr std::uint8_t MAX_NUM_LEVEL = 16;
|
||||
static const constexpr std::uint8_t NUM_PARTITION_BITS = sizeof(PartitionID) * CHAR_BIT;
|
||||
|
||||
template <typename T> using Vector = typename util::ShM<T, Ownership>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
// Contains all data necessary to describe the level hierarchy
|
||||
@@ -62,8 +61,11 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
std::array<LevelID, NUM_PARTITION_BITS> bit_to_level;
|
||||
std::array<std::uint32_t, MAX_NUM_LEVEL - 1> lidx_to_children_offsets;
|
||||
};
|
||||
using LevelDataPtr = typename std::conditional<Ownership == storage::Ownership::View,
|
||||
LevelData *,
|
||||
std::unique_ptr<LevelData>>::type;
|
||||
|
||||
MultiLevelPartitionImpl() = default;
|
||||
MultiLevelPartitionImpl();
|
||||
|
||||
// cell_sizes is index by level (starting at 0, the base graph).
|
||||
// However level 0 always needs to have cell size 1, since it is the
|
||||
@@ -77,7 +79,7 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
}
|
||||
|
||||
template <typename = typename std::enable_if<Ownership == storage::Ownership::View>>
|
||||
MultiLevelPartitionImpl(LevelData level_data,
|
||||
MultiLevelPartitionImpl(LevelDataPtr level_data,
|
||||
Vector<PartitionID> partition_,
|
||||
Vector<CellID> cell_to_children_)
|
||||
: level_data(std::move(level_data)), partition(std::move(partition_)),
|
||||
@@ -90,8 +92,8 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
{
|
||||
auto p = partition[node];
|
||||
auto lidx = LevelIDToIndex(l);
|
||||
auto masked = p & level_data.lidx_to_mask[lidx];
|
||||
return masked >> level_data.lidx_to_offset[lidx];
|
||||
auto masked = p & level_data->lidx_to_mask[lidx];
|
||||
return masked >> level_data->lidx_to_offset[lidx];
|
||||
}
|
||||
|
||||
LevelID GetQueryLevel(NodeID start, NodeID target, NodeID node) const
|
||||
@@ -106,10 +108,10 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
return 0;
|
||||
|
||||
auto msb = util::msb(partition[first] ^ partition[second]);
|
||||
return level_data.bit_to_level[msb];
|
||||
return level_data->bit_to_level[msb];
|
||||
}
|
||||
|
||||
std::uint8_t GetNumberOfLevels() const { return level_data.num_level; }
|
||||
std::uint8_t GetNumberOfLevels() const { return level_data->num_level; }
|
||||
|
||||
std::uint32_t GetNumberOfCells(LevelID level) const
|
||||
{
|
||||
@@ -121,7 +123,7 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
{
|
||||
BOOST_ASSERT(level > 1);
|
||||
auto lidx = LevelIDToIndex(level);
|
||||
auto offset = level_data.lidx_to_children_offsets[lidx];
|
||||
auto offset = level_data->lidx_to_children_offsets[lidx];
|
||||
return cell_to_children[offset + cell];
|
||||
}
|
||||
|
||||
@@ -130,14 +132,14 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
{
|
||||
BOOST_ASSERT(level > 1);
|
||||
auto lidx = LevelIDToIndex(level);
|
||||
auto offset = level_data.lidx_to_children_offsets[lidx];
|
||||
auto offset = level_data->lidx_to_children_offsets[lidx];
|
||||
return cell_to_children[offset + cell + 1];
|
||||
}
|
||||
|
||||
friend void io::read<Ownership>(const boost::filesystem::path &file,
|
||||
MultiLevelPartitionImpl &mlp);
|
||||
friend void io::write<Ownership>(const boost::filesystem::path &file,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
MultiLevelPartitionImpl &mlp);
|
||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
|
||||
private:
|
||||
auto MakeLevelData(const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
@@ -146,7 +148,7 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
auto offsets = MakeLevelOffsets(lidx_to_num_cells);
|
||||
auto masks = MakeLevelMasks(offsets, num_level);
|
||||
auto bits = MakeBitToLevel(offsets, num_level);
|
||||
return LevelData{num_level, offsets, masks, bits, {0}};
|
||||
return std::make_unique<LevelData>(LevelData{num_level, offsets, masks, bits, {0}});
|
||||
}
|
||||
|
||||
inline std::size_t LevelIDToIndex(LevelID l) const { return l - 1; }
|
||||
@@ -160,8 +162,8 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
{
|
||||
auto lidx = LevelIDToIndex(l);
|
||||
|
||||
auto shifted_id = cell_id << level_data.lidx_to_offset[lidx];
|
||||
auto cleared_cell = partition[node] & ~level_data.lidx_to_mask[lidx];
|
||||
auto shifted_id = cell_id << level_data->lidx_to_offset[lidx];
|
||||
auto cleared_cell = partition[node] & ~level_data->lidx_to_mask[lidx];
|
||||
partition[node] = cleared_cell | shifted_id;
|
||||
}
|
||||
|
||||
@@ -289,13 +291,13 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
level--;
|
||||
}
|
||||
|
||||
level_data.lidx_to_children_offsets[0] = 0;
|
||||
level_data->lidx_to_children_offsets[0] = 0;
|
||||
|
||||
for (auto level_idx = 0UL; level_idx < partitions.size() - 1; ++level_idx)
|
||||
{
|
||||
const auto &parent_partition = partitions[level_idx + 1];
|
||||
|
||||
level_data.lidx_to_children_offsets[level_idx + 1] = cell_to_children.size();
|
||||
level_data->lidx_to_children_offsets[level_idx + 1] = cell_to_children.size();
|
||||
|
||||
CellID last_parent_id = parent_partition[permutation.front()];
|
||||
cell_to_children.push_back(GetCell(level_idx + 1, permutation.front()));
|
||||
@@ -314,11 +316,22 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
}
|
||||
}
|
||||
|
||||
//! this is always owned by this class because it is so small
|
||||
LevelData level_data;
|
||||
LevelDataPtr level_data = {};
|
||||
Vector<PartitionID> partition;
|
||||
Vector<CellID> cell_to_children;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline MultiLevelPartitionImpl<storage::Ownership::Container>::MultiLevelPartitionImpl()
|
||||
: level_data(std::make_unique<LevelData>())
|
||||
{
|
||||
}
|
||||
|
||||
template <>
|
||||
inline MultiLevelPartitionImpl<storage::Ownership::View>::MultiLevelPartitionImpl()
|
||||
: level_data(nullptr)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef OSRM_PARTITION_SERIALIZATION_HPP
|
||||
#define OSRM_PARTITION_SERIALIZATION_HPP
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/edge_based_graph.hpp"
|
||||
#include "partition/multi_level_graph.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/serialization.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
storage::serialization::read(reader, graph.node_array);
|
||||
storage::serialization::read(reader, graph.edge_array);
|
||||
storage::serialization::read(reader, graph.node_to_edge_offset);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
storage::serialization::write(writer, graph.node_array);
|
||||
storage::serialization::write(writer, graph.edge_array);
|
||||
storage::serialization::write(writer, graph.node_to_edge_offset);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::MultiLevelPartitionImpl<Ownership> &mlp)
|
||||
{
|
||||
reader.ReadInto(*mlp.level_data);
|
||||
storage::serialization::read(reader, mlp.partition);
|
||||
storage::serialization::read(reader, mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::MultiLevelPartitionImpl<Ownership> &mlp)
|
||||
{
|
||||
writer.WriteOne(*mlp.level_data);
|
||||
storage::serialization::write(writer, mlp.partition);
|
||||
storage::serialization::write(writer, mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::CellStorageImpl<Ownership> &storage)
|
||||
{
|
||||
storage::serialization::read(reader, storage.weights);
|
||||
storage::serialization::read(reader, storage.source_boundary);
|
||||
storage::serialization::read(reader, storage.destination_boundary);
|
||||
storage::serialization::read(reader, storage.cells);
|
||||
storage::serialization::read(reader, storage.level_to_cell_offset);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::CellStorageImpl<Ownership> &storage)
|
||||
{
|
||||
storage::serialization::write(writer, storage.weights);
|
||||
storage::serialization::write(writer, storage.source_boundary);
|
||||
storage::serialization::write(writer, storage.destination_boundary);
|
||||
storage::serialization::write(writer, storage.cells);
|
||||
storage::serialization::write(writer, storage.level_to_cell_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -128,20 +128,6 @@ class FileReader
|
||||
std::uint32_t ReadElementCount32() { return ReadOne<std::uint32_t>(); }
|
||||
std::uint64_t ReadElementCount64() { return ReadOne<std::uint64_t>(); }
|
||||
|
||||
template <typename T> void DeserializeVector(std::vector<T> &data)
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
data.resize(count);
|
||||
ReadInto(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> std::size_t GetVectorMemorySize()
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
Skip<T>(count);
|
||||
return sizeof(count) + sizeof(T) * count;
|
||||
}
|
||||
|
||||
template <typename T> std::size_t ReadVectorSize()
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
@@ -149,19 +135,6 @@ class FileReader
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename T> void *DeserializeVector(void *begin, const void *end)
|
||||
{
|
||||
auto count = ReadElementCount64();
|
||||
auto required = reinterpret_cast<char *>(begin) + sizeof(count) + sizeof(T) * count;
|
||||
if (required > end)
|
||||
throw util::exception("Not enough memory ");
|
||||
|
||||
*reinterpret_cast<decltype(count) *>(begin) = count;
|
||||
ReadInto(reinterpret_cast<T *>(reinterpret_cast<char *>(begin) + sizeof(decltype(count))),
|
||||
count);
|
||||
return required;
|
||||
}
|
||||
|
||||
bool ReadAndCheckFingerprint()
|
||||
{
|
||||
auto loaded_fingerprint = ReadOne<util::FingerPrint>();
|
||||
@@ -199,42 +172,6 @@ class FileReader
|
||||
input_stream.seekg(current_pos, input_stream.beg);
|
||||
return length;
|
||||
}
|
||||
|
||||
std::vector<std::string> ReadLines()
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::string thisline;
|
||||
try
|
||||
{
|
||||
while (std::getline(input_stream, thisline))
|
||||
{
|
||||
result.push_back(thisline);
|
||||
}
|
||||
}
|
||||
catch (const std::ios_base::failure &)
|
||||
{
|
||||
// EOF is OK here, everything else, re-throw
|
||||
if (!input_stream.eof())
|
||||
throw;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ReadLine()
|
||||
{
|
||||
std::string thisline;
|
||||
try
|
||||
{
|
||||
std::getline(input_stream, thisline);
|
||||
}
|
||||
catch (const std::ios_base::failure & /*e*/)
|
||||
{
|
||||
// EOF is OK here, everything else, re-throw
|
||||
if (!input_stream.eof())
|
||||
throw;
|
||||
}
|
||||
return thisline;
|
||||
}
|
||||
};
|
||||
|
||||
class FileWriter
|
||||
@@ -296,13 +233,6 @@ class FileWriter
|
||||
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
||||
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
||||
|
||||
template <typename T> void SerializeVector(const std::vector<T> &data)
|
||||
{
|
||||
const auto count = data.size();
|
||||
WriteElementCount64(count);
|
||||
return WriteFrom(data.data(), count);
|
||||
}
|
||||
|
||||
void WriteFingerprint()
|
||||
{
|
||||
const auto fingerprint = util::FingerPrint::GetValid();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef OSRM_STORAGE_IO_FWD_HPP_
|
||||
#define OSRM_STORAGE_IO_FWD_HPP_
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace storage
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class FileReader;
|
||||
class FileWriter;
|
||||
|
||||
} // ns io
|
||||
} // ns storage
|
||||
} // ns osrm
|
||||
|
||||
#endif
|
||||
@@ -1,23 +1,12 @@
|
||||
#ifndef OSRM_STORAGE_SERIALIZATION_HPP_
|
||||
#define OSRM_STORAGE_SERIALIZATION_HPP_
|
||||
#ifndef OSRM_STORAGE_SERIALIZATION_HPP
|
||||
#define OSRM_STORAGE_SERIALIZATION_HPP
|
||||
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "extractor/extractor.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "storage/io.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/iostreams/seek.hpp>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -25,105 +14,54 @@ namespace storage
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
// To make function calls consistent, this function returns the fixed number of properties
|
||||
inline std::size_t readPropertiesCount() { return 1; }
|
||||
|
||||
struct HSGRHeader
|
||||
template <typename T> inline void read(storage::io::FileReader &reader, stxxl::vector<T> &vec)
|
||||
{
|
||||
std::uint32_t checksum;
|
||||
std::uint64_t number_of_nodes;
|
||||
std::uint64_t number_of_edges;
|
||||
};
|
||||
|
||||
// Reads the checksum, number of nodes and number of edges written in the header file of a `.hsgr`
|
||||
// file and returns them in a HSGRHeader struct
|
||||
inline HSGRHeader readHSGRHeader(io::FileReader &input_file)
|
||||
{
|
||||
|
||||
HSGRHeader header;
|
||||
input_file.ReadInto(header.checksum);
|
||||
input_file.ReadInto(header.number_of_nodes);
|
||||
input_file.ReadInto(header.number_of_edges);
|
||||
|
||||
// If we have edges, then we must have nodes.
|
||||
// However, there can be nodes with no edges (some test cases create this)
|
||||
BOOST_ASSERT_MSG(header.number_of_edges == 0 || header.number_of_nodes > 0,
|
||||
"edges exist, but there are no nodes");
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
// Reads the graph data of a `.hsgr` file into memory
|
||||
// Needs to be called after readHSGRHeader() to get the correct offset in the stream
|
||||
using NodeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::NodeArrayEntry;
|
||||
using EdgeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::EdgeArrayEntry;
|
||||
inline void readHSGR(io::FileReader &input_file,
|
||||
NodeT *node_buffer,
|
||||
const std::uint64_t number_of_nodes,
|
||||
EdgeT *edge_buffer,
|
||||
const std::uint64_t number_of_edges)
|
||||
{
|
||||
BOOST_ASSERT(node_buffer);
|
||||
BOOST_ASSERT(edge_buffer);
|
||||
input_file.ReadInto(node_buffer, number_of_nodes);
|
||||
input_file.ReadInto(edge_buffer, number_of_edges);
|
||||
}
|
||||
|
||||
// Loads edge data from .edge files into memory which includes its
|
||||
// geometry, name ID, turn instruction, lane data ID, travel mode, entry class ID
|
||||
// Needs to be called after readElementCount() to get the correct offset in the stream
|
||||
inline void readEdges(io::FileReader &edges_input_file,
|
||||
GeometryID *geometry_list,
|
||||
NameID *name_id_list,
|
||||
extractor::guidance::TurnInstruction *turn_instruction_list,
|
||||
LaneDataID *lane_data_id_list,
|
||||
extractor::TravelMode *travel_mode_list,
|
||||
EntryClassID *entry_class_id_list,
|
||||
util::guidance::TurnBearing *pre_turn_bearing_list,
|
||||
util::guidance::TurnBearing *post_turn_bearing_list,
|
||||
const std::uint64_t number_of_edges)
|
||||
{
|
||||
BOOST_ASSERT(geometry_list);
|
||||
BOOST_ASSERT(name_id_list);
|
||||
BOOST_ASSERT(turn_instruction_list);
|
||||
BOOST_ASSERT(lane_data_id_list);
|
||||
BOOST_ASSERT(travel_mode_list);
|
||||
BOOST_ASSERT(entry_class_id_list);
|
||||
extractor::OriginalEdgeData current_edge_data;
|
||||
for (std::uint64_t i = 0; i < number_of_edges; ++i)
|
||||
auto size = reader.ReadOne<std::uint64_t>();
|
||||
vec.reserve(size);
|
||||
for (auto idx : util::irange<std::size_t>(0, size))
|
||||
{
|
||||
edges_input_file.ReadInto(current_edge_data);
|
||||
|
||||
geometry_list[i] = current_edge_data.via_geometry;
|
||||
name_id_list[i] = current_edge_data.name_id;
|
||||
turn_instruction_list[i] = current_edge_data.turn_instruction;
|
||||
lane_data_id_list[i] = current_edge_data.lane_data_id;
|
||||
travel_mode_list[i] = current_edge_data.travel_mode;
|
||||
entry_class_id_list[i] = current_edge_data.entry_classid;
|
||||
pre_turn_bearing_list[i] = current_edge_data.pre_turn_bearing;
|
||||
post_turn_bearing_list[i] = current_edge_data.post_turn_bearing;
|
||||
(void)idx;
|
||||
vec.push_back(reader.ReadOne<T>());
|
||||
}
|
||||
}
|
||||
|
||||
// Loads coordinates and OSM node IDs from .nodes files into memory
|
||||
// Needs to be called after readElementCount() to get the correct offset in the stream
|
||||
template <typename OSMNodeIDVectorT>
|
||||
void readNodes(io::FileReader &nodes_file,
|
||||
util::Coordinate *coordinate_list,
|
||||
OSMNodeIDVectorT &osmnodeid_list,
|
||||
const std::uint64_t number_of_coordinates)
|
||||
template <typename T>
|
||||
inline void write(storage::io::FileWriter &writer, const stxxl::vector<T> &vec)
|
||||
{
|
||||
BOOST_ASSERT(coordinate_list);
|
||||
extractor::QueryNode current_node;
|
||||
for (std::uint64_t i = 0; i < number_of_coordinates; ++i)
|
||||
writer.WriteOne(vec.size());
|
||||
for (auto idx : util::irange<std::size_t>(0, vec.size()))
|
||||
{
|
||||
nodes_file.ReadInto(current_node);
|
||||
coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
|
||||
osmnodeid_list.push_back(current_node.node_id);
|
||||
BOOST_ASSERT(coordinate_list[i].IsValid());
|
||||
writer.WriteOne<T>(vec[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void read(io::FileReader &reader, std::vector<T> &data)
|
||||
{
|
||||
const auto count = reader.ReadElementCount64();
|
||||
data.resize(count);
|
||||
reader.ReadInto(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void write(io::FileWriter &writer, const std::vector<T> &data)
|
||||
{
|
||||
const auto count = data.size();
|
||||
writer.WriteElementCount64(count);
|
||||
return writer.WriteFrom(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void read(io::FileReader &reader, util::vector_view<T> &data)
|
||||
{
|
||||
const auto count = reader.ReadElementCount64();
|
||||
BOOST_ASSERT(data.size() == count);
|
||||
reader.ReadInto(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void write(io::FileWriter &writer, const util::vector_view<T> &data)
|
||||
{
|
||||
const auto count = data.size();
|
||||
writer.WriteElementCount64(count);
|
||||
return writer.WriteFrom(data.data(), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ namespace storage
|
||||
enum class Ownership
|
||||
{
|
||||
Container,
|
||||
View
|
||||
View,
|
||||
External
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/spin_mutex.h>
|
||||
|
||||
#include <boost/interprocess/file_mapping.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/iostreams/device/mapped_file.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/support_line_pos_iterator.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
@@ -24,20 +23,15 @@ namespace osrm
|
||||
namespace updater
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Also the Value structure must have source member that will be filled
|
||||
// with the corresponding file index in the CSV filenames vector.
|
||||
template <typename Key, typename Value> struct CSVFilesParser
|
||||
{
|
||||
using Iterator = boost::spirit::line_pos_iterator<boost::spirit::istream_iterator>;
|
||||
using KeyRule = qi::rule<Iterator, Key()>;
|
||||
using ValueRule = qi::rule<Iterator, Value()>;
|
||||
using Iterator = boost::iostreams::mapped_file_source::iterator;
|
||||
using KeyRule = boost::spirit::qi::rule<Iterator, Key()>;
|
||||
using ValueRule = boost::spirit::qi::rule<Iterator, Value()>;
|
||||
|
||||
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)
|
||||
@@ -95,30 +89,46 @@ template <typename Key, typename Value> struct CSVFilesParser
|
||||
// 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
|
||||
{
|
||||
std::ifstream input_stream(filename, std::ios::binary);
|
||||
input_stream.unsetf(std::ios::skipws);
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
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;
|
||||
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
|
||||
|
||||
if (!ok || first != last)
|
||||
try
|
||||
{
|
||||
const auto message =
|
||||
boost::format("CSV file %1% malformed on line %2%") % filename % first.position();
|
||||
if (boost::filesystem::file_size(filename) == 0)
|
||||
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);
|
||||
}
|
||||
|
||||
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
|
||||
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
const std::size_t start_index;
|
||||
|
||||
@@ -49,9 +49,9 @@ struct Segment 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;
|
||||
double weight;
|
||||
double rate;
|
||||
std::uint8_t source;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
||||
do \
|
||||
{ \
|
||||
(void)cond; \
|
||||
(void)coordinate; \
|
||||
(void)msg; \
|
||||
(void)(cond); \
|
||||
(void)(coordinate); \
|
||||
(void)(msg); \
|
||||
} while (0)
|
||||
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
||||
|
||||
|
||||
@@ -239,6 +239,13 @@ class DeallocatingVector
|
||||
bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
|
||||
// copying is not safe since this would only do a shallow copy
|
||||
DeallocatingVector(DeallocatingVector &other) = delete;
|
||||
DeallocatingVector &operator=(DeallocatingVector &other) = delete;
|
||||
// moving is fine
|
||||
DeallocatingVector(DeallocatingVector &&other) = default;
|
||||
DeallocatingVector &operator=(DeallocatingVector &&other) = default;
|
||||
|
||||
~DeallocatingVector() { clear(); }
|
||||
|
||||
friend void swap<>(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &lhs,
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -19,6 +21,16 @@ namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
template <typename EdgeDataT> class DynamicGraph;
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void read(storage::io::FileReader &reader, DynamicGraph<EdgeDataT> &graph);
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void write(storage::io::FileWriter &writer, const DynamicGraph<EdgeDataT> &graph);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT> class DynamicGraph
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -57,21 +58,23 @@ template <typename BarrierOutIter, typename TrafficSignalsOutIter>
|
||||
NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
|
||||
BarrierOutIter barriers,
|
||||
TrafficSignalsOutIter traffic_signals,
|
||||
std::vector<extractor::QueryNode> &node_array)
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids)
|
||||
{
|
||||
NodeID number_of_nodes = file_reader.ReadElementCount32();
|
||||
Log() << "Importing number_of_nodes new = " << number_of_nodes << " nodes ";
|
||||
|
||||
node_array.resize(number_of_nodes);
|
||||
coordinates.resize(number_of_nodes);
|
||||
osm_node_ids.reserve(number_of_nodes);
|
||||
|
||||
extractor::ExternalMemoryNode current_node;
|
||||
for (NodeID i = 0; i < number_of_nodes; ++i)
|
||||
{
|
||||
file_reader.ReadInto(¤t_node, 1);
|
||||
|
||||
node_array[i].lon = current_node.lon;
|
||||
node_array[i].lat = current_node.lat;
|
||||
node_array[i].node_id = current_node.node_id;
|
||||
coordinates[i].lon = current_node.lon;
|
||||
coordinates[i].lat = current_node.lat;
|
||||
osm_node_ids.push_back(current_node.node_id);
|
||||
|
||||
if (current_node.barrier)
|
||||
{
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#ifndef OSRM_INCLUDE_UTIL_IO_HPP_
|
||||
#define OSRM_INCLUDE_UTIL_IO_HPP_
|
||||
|
||||
#include "util/log.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include <bitset>
|
||||
#include <fstream>
|
||||
#include <stxxl/vector>
|
||||
#include <vector>
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
template <typename simple_type>
|
||||
void deserializeAdjacencyArray(const std::string &filename,
|
||||
std::vector<std::uint32_t> &offsets,
|
||||
std::vector<simple_type> &data)
|
||||
{
|
||||
storage::io::FileReader file(filename, storage::io::FileReader::HasNoFingerprint);
|
||||
|
||||
file.DeserializeVector(offsets);
|
||||
file.DeserializeVector(data);
|
||||
|
||||
// offsets have to match up with the size of the data
|
||||
if (offsets.empty() || (offsets.back() != boost::numeric_cast<std::uint32_t>(data.size())))
|
||||
throw util::exception(
|
||||
"Error in " + filename +
|
||||
(offsets.empty() ? "Offsets are empty" : "Offset and data size do not match") +
|
||||
SOURCE_REF);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_INCLUDE_UTIL_IO_HPP_
|
||||
@@ -2,7 +2,6 @@
|
||||
#define OSRM_UTIL_NAME_TABLE_HPP
|
||||
|
||||
#include "util/indexed_data.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/string_view.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#ifndef PACKED_VECTOR_HPP
|
||||
#define PACKED_VECTOR_HPP
|
||||
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <cmath>
|
||||
@@ -13,7 +14,22 @@ namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership> class PackedVector;
|
||||
}
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Ownership> &vec);
|
||||
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const detail::PackedVector<T, Ownership> &vec);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Since OSM node IDs are (at the time of writing) not quite yet overflowing 32 bits, and
|
||||
* will predictably be containable within 33 bits for a long time, the following packs
|
||||
@@ -22,14 +38,15 @@ namespace util
|
||||
* NOTE: this type is templated for future use, but will require a slight refactor to
|
||||
* configure BITSIZE and ELEMSIZE
|
||||
*/
|
||||
template <typename T, storage::Ownership Ownership = storage::Ownership::Container>
|
||||
class PackedVector
|
||||
template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
{
|
||||
static const constexpr std::size_t BITSIZE = 33;
|
||||
static const constexpr std::size_t ELEMSIZE = 64;
|
||||
static const constexpr std::size_t PACKSIZE = BITSIZE * ELEMSIZE;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
/**
|
||||
* Returns the size of the packed vector datastructure with `elements` packed elements (the size
|
||||
* of
|
||||
@@ -80,7 +97,9 @@ class PackedVector
|
||||
num_elements++;
|
||||
}
|
||||
|
||||
T at(const std::size_t &a_index) const
|
||||
T operator[](const std::size_t index) const { return at(index); }
|
||||
|
||||
T at(const std::size_t a_index) const
|
||||
{
|
||||
BOOST_ASSERT(a_index < num_elements);
|
||||
|
||||
@@ -147,10 +166,16 @@ class PackedVector
|
||||
return std::floor(static_cast<double>(vec.capacity()) * ELEMSIZE / BITSIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
typename util::ShM<std::uint64_t, Ownership>::vector vec;
|
||||
friend void serialization::read<T, Ownership>(storage::io::FileReader &reader,
|
||||
detail::PackedVector<T, Ownership> &vec);
|
||||
|
||||
std::size_t num_elements = 0;
|
||||
friend void serialization::write<T, Ownership>(storage::io::FileWriter &writer,
|
||||
const detail::PackedVector<T, Ownership> &vec);
|
||||
|
||||
private:
|
||||
util::ViewOrVector<std::uint64_t, Ownership> vec;
|
||||
|
||||
std::uint64_t num_elements = 0;
|
||||
|
||||
signed cursor = -1;
|
||||
|
||||
@@ -192,6 +217,10 @@ class PackedVector
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T> using PackedVector = detail::PackedVector<T, storage::Ownership::Container>;
|
||||
template <typename T> using PackedVectorView = detail::PackedVector<T, storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PACKED_VECTOR_HPP */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user