Compare commits
69 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6f745b40d0 | ||
|
8789b4bee9 | ||
|
7000cfa472 | ||
|
b29cbd3711 | ||
|
1454d6d7d0 | ||
|
3cf8835552 | ||
|
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 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,6 +7,8 @@
|
|||||||
#############################
|
#############################
|
||||||
osrm-deps
|
osrm-deps
|
||||||
|
|
||||||
|
.ycm_extra_conf.py
|
||||||
|
|
||||||
# Compiled source #
|
# Compiled source #
|
||||||
###################
|
###################
|
||||||
*.com
|
*.com
|
||||||
|
10
.npmignore
10
.npmignore
@ -1,10 +0,0 @@
|
|||||||
*
|
|
||||||
!README.md
|
|
||||||
!CHANGELOG.md
|
|
||||||
!CONTRIBUTING.MD
|
|
||||||
!LICENCE.TXT
|
|
||||||
!package.json
|
|
||||||
!example
|
|
||||||
!lib/*.js
|
|
||||||
!profiles/*
|
|
||||||
!profiles/lib/*
|
|
41
.travis.yml
41
.travis.yml
@ -7,8 +7,9 @@ git:
|
|||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
nodejs:
|
node_js:
|
||||||
- "4"
|
- "4"
|
||||||
|
- "6"
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
@ -16,6 +17,7 @@ notifications:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
- "5.7"
|
||||||
# enable building tags
|
# enable building tags
|
||||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||||
|
|
||||||
@ -36,6 +38,8 @@ env:
|
|||||||
- CCACHE_VERSION=3.3.1
|
- CCACHE_VERSION=3.3.1
|
||||||
- CMAKE_VERSION=3.7.2
|
- CMAKE_VERSION=3.7.2
|
||||||
- MASON="$(pwd)/scripts/mason.sh"
|
- MASON="$(pwd)/scripts/mason.sh"
|
||||||
|
- ENABLE_NODE_BINDINGS=On
|
||||||
|
- NODE="4"
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
@ -45,12 +49,14 @@ matrix:
|
|||||||
|
|
||||||
# Debug Builds
|
# Debug Builds
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "gcc-6-debug"
|
compiler: "gcc-6-debug-cov-asan"
|
||||||
addons: &gcc6
|
addons: &gcc6
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
|
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang-4.0-debug"
|
compiler: "clang-4.0-debug"
|
||||||
@ -61,12 +67,12 @@ matrix:
|
|||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "mason-linux-debug-santize"
|
compiler: "mason-linux-debug-asan"
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON ENABLE_NODE_BINDINGS=ON
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
|
||||||
|
|
||||||
# Release Builds
|
# Release Builds
|
||||||
- os: linux
|
- os: linux
|
||||||
@ -75,7 +81,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "gcc-6-release"
|
compiler: "gcc-6-release"
|
||||||
@ -104,6 +110,8 @@ matrix:
|
|||||||
compiler: "mason-osx-release"
|
compiler: "mason-osx-release"
|
||||||
# we use the xcode provides clang and don't install our own
|
# we use the xcode provides clang and don't install our own
|
||||||
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
|
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
|
||||||
|
after_success:
|
||||||
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
# Disabled because of CI slowness
|
# Disabled because of CI slowness
|
||||||
#- os: linux
|
#- os: linux
|
||||||
@ -140,8 +148,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
|
||||||
nodejs: "4"
|
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
- |
|
- |
|
||||||
@ -164,8 +171,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
|
||||||
nodejs: "4"
|
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
- |
|
- |
|
||||||
@ -188,8 +194,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
|
||||||
nodejs: "6"
|
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
- |
|
- |
|
||||||
@ -212,8 +217,7 @@ matrix:
|
|||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['libstdc++-5-dev']
|
packages: ['libstdc++-5-dev']
|
||||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
|
||||||
nodejs: "6"
|
|
||||||
install:
|
install:
|
||||||
- pushd ${OSRM_BUILD_DIR}
|
- pushd ${OSRM_BUILD_DIR}
|
||||||
- |
|
- |
|
||||||
@ -230,6 +234,10 @@ matrix:
|
|||||||
- ./scripts/travis/publish.sh
|
- ./scripts/travis/publish.sh
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
- source $NVM_DIR/nvm.sh
|
||||||
|
- nvm install $NODE
|
||||||
|
- nvm use $NODE
|
||||||
|
- node --version
|
||||||
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
|
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
|
||||||
- |
|
- |
|
||||||
if [[ -z $JOBS ]]; then
|
if [[ -z $JOBS ]]; then
|
||||||
@ -331,14 +339,9 @@ script:
|
|||||||
- ./unit_tests/server-tests
|
- ./unit_tests/server-tests
|
||||||
- ./unit_tests/partition-tests
|
- ./unit_tests/partition-tests
|
||||||
- |
|
- |
|
||||||
if [ -n "${ENABLE_NODE_BINDINGS}" ] && [ -z "${ENABLE_SANITIZER}" ]; then
|
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
|
||||||
npm run nodejs-tests
|
npm run nodejs-tests
|
||||||
fi
|
fi
|
||||||
- popd
|
- popd
|
||||||
- yarn test
|
- yarn test
|
||||||
|
|
||||||
after_success:
|
|
||||||
- |
|
|
||||||
if [ -n "${ENABLE_COVERAGE}" ]; then
|
|
||||||
bash <(curl -s https://codecov.io/bash)
|
|
||||||
fi
|
|
||||||
|
40
CHANGELOG.md
40
CHANGELOG.md
@ -1,17 +1,55 @@
|
|||||||
- Track preprocessing flag in the map matching plugin.
|
# 5.7.3
|
||||||
|
- Changes from 5.7.2:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes 4097: .ramIndex files was able to be truncated siliently
|
||||||
|
|
||||||
|
# 5.7.2
|
||||||
|
- Changes from 5.7.1:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes segmentation fault caused by the fix for 3977
|
||||||
|
|
||||||
|
# 5.7.1
|
||||||
|
- Changes from 5.7.0:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes 3995: Negative duration caused by rounding issues.
|
||||||
|
- Fixes 3977: Fixes exit number in roundabout if starting inside the roundabout
|
||||||
|
- Fixes 3981: The NodeJS documentation was outdated and incomplete.
|
||||||
|
- Fixes 4010: Performance regression while parsing CSV files. Now 5x faster.
|
||||||
|
- Fixes 3919: Turn penalties on the cyclabilty metric were disabled.
|
||||||
|
- Fixes 3992: Table plugin not checking for valid phantom nodes
|
||||||
|
- Fixes 4013: `continue_straight` interaction with bearing constraints
|
||||||
|
- Fixes 4063: Potential overflow in custom profiles for restricted ways
|
||||||
|
- Fixes 4030: Roundabout edge-case crashes post-processing
|
||||||
|
|
||||||
# 5.7.0
|
# 5.7.0
|
||||||
- Changes from 5.6
|
- Changes from 5.6
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixed 505: Invalid distance value for distance as routing weight.
|
||||||
|
- Fixed 3958: Fix traffic light penalties for non-turns
|
||||||
|
- Fixed 3933: crash when collapsing instructions
|
||||||
|
- Algorithm:
|
||||||
|
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
|
||||||
|
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
|
||||||
|
- Allows for fast metric updates in below a minute on continental sized networks (osrm-customize)
|
||||||
|
- Plugins supported: `match` and `route`
|
||||||
|
- Quickstart: `osrm-extract data.osm.pbf`, `osrm-partition data.osrm`, `osrm-customize data.osrm`, `osrm-routed --algorithm=MLD data.osrm`
|
||||||
- NodeJs Bindings
|
- NodeJs Bindings
|
||||||
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
|
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
|
||||||
|
- `OSRM` object has new option `algorihtm="CH","CoreCH","MLD"`
|
||||||
- Internals
|
- Internals
|
||||||
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
|
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
|
||||||
- Files
|
- Files
|
||||||
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
|
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
|
||||||
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
|
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
|
||||||
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
|
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
|
||||||
|
- `osrm-extract` creates new file `.osrm.cnbg` and `.cnbg_to_ebg`
|
||||||
|
- `osrm-partition` creates new file `.osrm.partition` and `.osrm.cells`
|
||||||
|
- `osrm-customize` creates new file `.osrm.mldgr`
|
||||||
- Profiles
|
- Profiles
|
||||||
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
|
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
|
||||||
|
- Map Matching:
|
||||||
|
- new option `gaps=split|ignore` to enable/disbale track splitting
|
||||||
|
- new option `tidy=true|false` to simplify traces automatically
|
||||||
|
|
||||||
# 5.6.3
|
# 5.6.3
|
||||||
- Changes from 5.6.0
|
- Changes from 5.6.0
|
||||||
|
@ -55,7 +55,7 @@ endif()
|
|||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
set(OSRM_VERSION_MAJOR 5)
|
||||||
set(OSRM_VERSION_MINOR 7)
|
set(OSRM_VERSION_MINOR 7)
|
||||||
set(OSRM_VERSION_PATCH 0)
|
set(OSRM_VERSION_PATCH 3)
|
||||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||||
|
|
||||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
@ -1,66 +1,59 @@
|
|||||||
# OSRM
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
||||||
|
|
||||||
The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance requires a `.osrm` network,
|
## OSRM
|
||||||
which is prepared by the OSRM Backend C++ library.
|
|
||||||
|
|
||||||
|
The `OSRM` method is the main constructor for creating an OSRM instance.
|
||||||
|
An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
||||||
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
|
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
|
||||||
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
|
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
|
||||||
|
|
||||||
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
|
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
|
||||||
node_modules/osrm/lib/binding/osrm-contract data.osrm
|
node_modules/osrm/lib/binding/osrm-contract data.osrm
|
||||||
|
|
||||||
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation or further details.
|
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
|
||||||
|
|
||||||
Once you have a complete `network.osrm` file, you can calculate networks in javascript with this library using the
|
Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
|
||||||
methods below. To create an OSRM instance with your network you need to construct an instance like this:
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM('network.osrm');
|
var osrm = new OSRM('network.osrm');
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Methods
|
**Parameters**
|
||||||
|
|
||||||
| Service | Description |
|
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Options for creating an OSRM object or string to the `.osrm` file. (optional, default `{shared_memory:true}`)
|
||||||
| -------------------------- | --------------------------------------------------------- |
|
- `options.algorithm` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
|
||||||
| [`osrm.route`](#route) | shortest path between given coordinates |
|
Make sure you prepared the dataset with the correct toolchain.
|
||||||
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
|
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
|
||||||
| [`osrm.table`](#table) | computes distance tables for given coordinates |
|
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
||||||
| [`osrm.match`](#match) | matches given coordinates to the road network |
|
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
|
||||||
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
|
|
||||||
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
|
|
||||||
|
|
||||||
#### General Options
|
### route
|
||||||
|
|
||||||
Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options, outlined below.
|
|
||||||
|
|
||||||
| Option | Values | Description | Format |
|
|
||||||
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
|
|
||||||
| coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
|
|
||||||
| bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
|
|
||||||
| radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
|
|
||||||
| hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
|
|
||||||
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
|
|
||||||
|
|
||||||
## route
|
|
||||||
|
|
||||||
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
|
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
|
||||||
- `options.alternatives` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Search for alternative routes and return as well. _Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route leg. (optional, default `false`)
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
- `options.continue_straight` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. `null`/`true`/`false`
|
- `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes and return as well.
|
||||||
|
_Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
|
||||||
|
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`)
|
||||||
|
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
|
||||||
|
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
||||||
|
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||||
|
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
|
||||||
|
`null`/`true`/`false`
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM("berlin-latest.osrm");
|
var osrm = new OSRM("berlin-latest.osrm");
|
||||||
osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, function(err, result) {
|
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
|
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
|
||||||
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
||||||
@ -69,7 +62,7 @@ osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, funct
|
|||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
|
||||||
|
|
||||||
## nearest
|
### nearest
|
||||||
|
|
||||||
Snaps a coordinate to the street network and returns the nearest n matches.
|
Snaps a coordinate to the street network and returns the nearest n matches.
|
||||||
|
|
||||||
@ -78,7 +71,12 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
|
|||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
|
||||||
- `options.number` **\[[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)]** Number of nearest segments that should be returned.
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
|
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
|
||||||
Must be an integer greater than or equal to `1`. (optional, default `1`)
|
Must be an integer greater than or equal to `1`. (optional, default `1`)
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
@ -98,19 +96,26 @@ osrm.nearest(options, function(err, response) {
|
|||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
|
||||||
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
|
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
|
||||||
Each object has an additional `distance` property, which is the distance in meters to the supplied
|
Each object has an additional `distance` property, which is the distance in meters to the supplied input coordinate.
|
||||||
input coordinate.
|
|
||||||
|
|
||||||
## table
|
### table
|
||||||
|
|
||||||
Computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
|
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
|
||||||
|
tables.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
|
||||||
- `options.sources` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
|
- `options.sources` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to
|
||||||
|
use
|
||||||
location with given index as source. Default is to use all.
|
location with given index as source. Default is to use all.
|
||||||
- `options.destinations` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
|
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
|
||||||
|
#coordinates`) to use location with given index as destination. Default is to use all.
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
@ -132,24 +137,25 @@ osrm.table(options, function(err, response) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
|
||||||
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
|
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from the i-th waypoint to the j-th waypoint.
|
||||||
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
|
Values are given in seconds.
|
||||||
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
|
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
|
||||||
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
|
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
|
||||||
|
|
||||||
## tile
|
### tile
|
||||||
|
|
||||||
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
|
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
|
||||||
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
|
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
|
||||||
be used to examine the routing graph. The tiles are generated directly from the data in-memory,
|
be used to examine the routing graph. The tiles are generated directly from the data in-memory,
|
||||||
so are in sync with actual routing results, and let you examine which roads are actually routable,
|
so are in sync with actual routing results, and let you examine which roads are actually
|
||||||
|
routable,
|
||||||
and what weights they have applied.
|
and what weights they have applied.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
|
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
|
||||||
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
|
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
|
||||||
and are supported by vector tile viewers like [Mapbox GL JS]\(<https://www.mapbox.com/mapbox-gl-js/api/>.
|
and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
@ -164,7 +170,7 @@ osrm.tile([0, 0, 0], function(err, response) {
|
|||||||
|
|
||||||
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
|
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
|
||||||
|
|
||||||
## match
|
### match
|
||||||
|
|
||||||
Map matching matches given GPS points to the road network in the most plausible way.
|
Map matching matches given GPS points to the road network in the most plausible way.
|
||||||
Please note the request might result multiple sub-traces. Large jumps in the timestamps
|
Please note the request might result multiple sub-traces. Large jumps in the timestamps
|
||||||
@ -175,15 +181,16 @@ if they can not be matched successfully.
|
|||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
|
||||||
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
and per step). Can also be `geojson`. (optional, default `polyline`)
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified`
|
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
|
||||||
according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
|
||||||
- `options.timestamps` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>]** Timestamp of the input location (integers, UNIX-like timestamp).
|
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
||||||
- `options.radiuses` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** Standard deviation of GPS precision used for map matching.
|
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||||
If applicable use GPS accuracy (`double >= 0`, default `5m`).
|
- `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp).
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
@ -203,69 +210,54 @@ osrm.match(options, function(err, response) {
|
|||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
|
||||||
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) objects representing all points of the trace in order.
|
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) objects representing all points of the trace in order.
|
||||||
If the trace point was ommited by map matching because it is an outlier, the entry will be null. Each
|
If the trace point was ommited by map matching because it is an outlier, the entry will be null.
|
||||||
`Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
|
Each `Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
|
||||||
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
|
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
|
||||||
the waypoint inside the matched route.
|
the waypoint inside the matched route.
|
||||||
**`matchings`** is an array of [`Route`](#route) objects that
|
**`matchings`** is an array of [`Route`](#route) objects that assemble the trace. Each `Route` object has an additional `confidence` property,
|
||||||
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
|
which is the confidence of the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
|
||||||
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
|
|
||||||
|
|
||||||
## trip
|
### trip
|
||||||
|
|
||||||
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm). The returned path does not have to be the fastest path, as TSP is NP-hard it is only an approximation. Note that all input coordinates have to be connected for the trip service to work.
|
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
|
||||||
|
(farthest-insertion algorithm) for 10 or _ more waypoints and uses brute force for less than 10
|
||||||
**Parameters**
|
waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is
|
||||||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
|
only an approximation.
|
||||||
- `options.roundtrip` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route is a roundtrip. (optional, default `true`)
|
|
||||||
- `options.source` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route starts at `any` coordinate. Can also be `first`. (optional, default `any`)
|
|
||||||
- `options.destination` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route ends at `any` coordinate. Can also be `last`. (optional, default `any`)
|
|
||||||
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
|
|
||||||
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
|
|
||||||
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
|
|
||||||
and per step). Can also be `geojson`. (optional, default `polyline`)
|
|
||||||
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
|
|
||||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
|
||||||
|
|
||||||
**Fixing Start and End Points**
|
|
||||||
|
|
||||||
It is possible to explicitly set the start or end coordinate of the trip. When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
|
|
||||||
|
|
||||||
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
|
|
||||||
|
|
||||||
|
Note that all input coordinates have to be connected for the trip service to work.
|
||||||
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
|
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
|
||||||
Right now, the following combinations are possible:
|
Right now, the following combinations are possible:
|
||||||
|
|
||||||
| roundtrip | source | destination | supported |
|
| roundtrip | source | destination | supported |
|
||||||
| :-- | :-- | :-- | :-- |
|
| :-------- | :----- | :---------- | :-------- |
|
||||||
| true | first | last | **yes** |
|
| true | first | last | **yes** |
|
||||||
| true | first | any | **yes** |
|
| true | first | any | **yes** |
|
||||||
| true | any | last | **yes** |
|
| true | any | last | **yes** |
|
||||||
| true | any | any | **yes** |
|
| true | any | any | **yes** |
|
||||||
| false | first | last | **yes** |
|
| false | first | last | **yes** |
|
||||||
| false | first | any | no |
|
| false | first | any | no |
|
||||||
| false | any | last | no |
|
| false | any | last | no |
|
||||||
| false | any | any | no |
|
| false | any | any | no |
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
|
||||||
|
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
|
||||||
|
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
|
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
|
||||||
|
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
|
||||||
|
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
|
||||||
|
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
|
||||||
|
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
|
||||||
|
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
|
||||||
|
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
|
||||||
|
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
Roundtrip Request
|
|
||||||
```javascript
|
|
||||||
var osrm = new OSRM('network.osrm');
|
|
||||||
var options = {
|
|
||||||
coordinates: [
|
|
||||||
[13.36761474609375, 52.51663871100423],
|
|
||||||
[13.374481201171875, 52.506191342034576]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
osrm.trip(options, function(err, response) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.log(response.waypoints); // array of Waypoint objects
|
|
||||||
console.log(response.trips); // array of Route objects
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Non Roundtrip Request
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM('network.osrm');
|
var osrm = new OSRM('network.osrm');
|
||||||
var options = {
|
var options = {
|
||||||
@ -285,49 +277,56 @@ osrm.trip(options, function(err, response) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
|
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
|
||||||
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
|
**`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
|
||||||
Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of the
|
Each Waypoint object has the following additional properties,
|
||||||
sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
|
1) `trips_index`: index to trips of the sub-trip the point was matched to, and
|
||||||
|
2) `waypoint_index`: index of the point in the trip.
|
||||||
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
||||||
|
|
||||||
# Responses
|
## Responses
|
||||||
|
|
||||||
Responses
|
Responses
|
||||||
|
|
||||||
## Route
|
### Route
|
||||||
|
|
||||||
Represents a route through (potentially multiple) waypoints.
|
Represents a route through (potentially multiple) waypoints.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](../http.md#route)
|
||||||
|
|
||||||
## RouteLeg
|
### RouteLeg
|
||||||
|
|
||||||
Represents a route between two waypoints.
|
Represents a route between two waypoints.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](../http.md#routeleg)
|
||||||
|
|
||||||
## RouteStep
|
### RouteStep
|
||||||
|
|
||||||
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a single way to the subsequent step.
|
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a
|
||||||
|
single way to the subsequent step.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
|
||||||
|
|
||||||
## StepManeuver
|
### StepManeuver
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmanuever)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
|
||||||
|
|
||||||
## Waypoint
|
### Waypoint
|
||||||
|
|
||||||
Object used to describe waypoint on a route.
|
Object used to describe waypoint on a route.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
|
- `exteral` **documentation** in
|
||||||
|
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
|
||||||
|
35
features/bicycle/alley.feature
Normal file
35
features/bicycle/alley.feature
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
@routing @bicycle @alley
|
||||||
|
Feature: Bicycle - Route around alleys
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
require 'bicycle'
|
||||||
|
properties.weight_name = 'cyclability'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Scenario: Bicycle - Avoid taking alleys
|
||||||
|
Given the query options
|
||||||
|
| annotations | nodes |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-----b-----c
|
||||||
|
| : |
|
||||||
|
d.....e.....f
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | service |
|
||||||
|
| abc | residential | |
|
||||||
|
| def | service | alley |
|
||||||
|
| ad | residential | |
|
||||||
|
| be | service | alley |
|
||||||
|
| cf | residential | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | a:nodes | weight | # |
|
||||||
|
| a | f | 1:2:3:6 | 200.4 | Avoids d,e,f |
|
||||||
|
| a | e | 1:2:5 | 176.4 | Take the alley b,e if neccessary |
|
||||||
|
| d | f | 4:1:2:3:6 | 252.6 | Avoids the alley d,e,f |
|
||||||
|
|
@ -34,3 +34,39 @@ Feature: Turn Penalties
|
|||||||
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
|
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
|
||||||
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
|
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
|
||||||
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
|
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
|
||||||
|
|
||||||
|
Scenario: Bicycle - Turn penalties on cyclability
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
require 'bicycle'
|
||||||
|
properties.weight_name = 'cyclability'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a--b-----c
|
||||||
|
|
|
||||||
|
|
|
||||||
|
d
|
||||||
|
|
||||||
|
e--------f-----------g
|
||||||
|
/
|
||||||
|
/
|
||||||
|
/
|
||||||
|
h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | residential |
|
||||||
|
| bd | residential |
|
||||||
|
| efg | residential |
|
||||||
|
| fh | residential |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | distance | weight | # |
|
||||||
|
| a | c | 900m +- 1 | 216 | Going straight has no penalties |
|
||||||
|
| a | d | 900m +- 1 | 220.2 | Turning right had penalties |
|
||||||
|
| e | g | 2100m +- 4| 503.9 | Going straght has no penalties |
|
||||||
|
| e | h | 2100m +- 4| 515.1 | Turn sharp right has even higher penalties|
|
||||||
|
|
||||||
|
39
features/car/traffic_light_penalties.feature
Normal file
39
features/car/traffic_light_penalties.feature
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@routing @car @traffic_light
|
||||||
|
Feature: Car - Handle traffic lights
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
|
||||||
|
Scenario: Car - Encounters a traffic light
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
|
||||||
|
d-3-e-4-f
|
||||||
|
|
||||||
|
g-h-i k-l-m
|
||||||
|
| |
|
||||||
|
j n
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
| def | primary |
|
||||||
|
| ghi | primary |
|
||||||
|
| klm | primary |
|
||||||
|
| hj | primary |
|
||||||
|
| ln | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway |
|
||||||
|
| e | traffic_signals |
|
||||||
|
| l | traffic_signals |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | time | # |
|
||||||
|
| 1 | 2 | 11.1s | no turn with no traffic light |
|
||||||
|
| 3 | 4 | 13.1s | no turn with traffic light |
|
||||||
|
| g | j | 18.7s | turn with no traffic light |
|
||||||
|
| k | n | 20.7s | turn with traffic light |
|
@ -48,7 +48,6 @@ Feature: Traffic - turn penalties
|
|||||||
| mn | primary |
|
| mn | primary |
|
||||||
| mp | primary |
|
| mp | primary |
|
||||||
And the profile "car"
|
And the profile "car"
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
|
|
||||||
Scenario: Weighting not based on turn penalty file
|
Scenario: Weighting not based on turn penalty file
|
||||||
When I route I should get
|
When I route I should get
|
||||||
|
@ -51,7 +51,6 @@ Feature: Car - weights
|
|||||||
| cd | primary | yes |
|
| cd | primary | yes |
|
||||||
| be | service | yes |
|
| be | service | yes |
|
||||||
| ec | service | yes |
|
| ec | service | yes |
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the speed file
|
And the speed file
|
||||||
@ -62,3 +61,28 @@ Feature: Car - weights
|
|||||||
| from | to | route | speed | weight |
|
| from | to | route | speed | weight |
|
||||||
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
||||||
| a | e | ab,be,be | 14 km/h | 112 |
|
| a | e | ab,be,be | 14 km/h | 112 |
|
||||||
|
|
||||||
|
Scenario: Distance weights
|
||||||
|
Given the profile file "car" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.weight_name = 'distance'
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c
|
||||||
|
|
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| bd |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route | distance | weights | times |
|
||||||
|
| a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
|
||||||
|
| b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
|
||||||
|
| a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s |
|
||||||
|
@ -1019,3 +1019,39 @@ Feature: Collapse
|
|||||||
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
|
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
|
||||||
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
|
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
|
||||||
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
|
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
|
||||||
|
|
||||||
|
|
||||||
|
# http://www.openstreetmap.org/way/92415447 #3933
|
||||||
|
Scenario: Use total angle for turn instruction if entry step has large distance
|
||||||
|
# """
|
||||||
|
# kf-_ a
|
||||||
|
# | - b
|
||||||
|
# | c
|
||||||
|
# |d
|
||||||
|
# e
|
||||||
|
# |
|
||||||
|
# i
|
||||||
|
# """
|
||||||
|
|
||||||
|
And the node locations
|
||||||
|
| node | lat | lon | #id |
|
||||||
|
| a | -33.9644254 | 151.1378673 | 33226063 |
|
||||||
|
| b | -33.9644373 | 151.1377172 | 1072787030 |
|
||||||
|
| c | -33.9644791 | 151.1374452 | 4222903609 |
|
||||||
|
| d | -33.9645661 | 151.1372654 | 4222903610 |
|
||||||
|
| e | -33.9646986 | 151.1371539 | 4222903611 |
|
||||||
|
| f | -33.964386 | 151.1372133 | 1072786875 |
|
||||||
|
| i | -33.9661796 | 151.1368491 | 2781176918 |
|
||||||
|
| k | -33.9643781 | 151.1371422 | 1684173853 |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway | #id |
|
||||||
|
| ab | trunk | President Avenue | yes | 92415447 |
|
||||||
|
| bcde | trunk | President Avenue | yes | 422534457 |
|
||||||
|
| bf | trunk | President Avenue | yes | 447779786 |
|
||||||
|
| fk | trunk | President Avenue | yes | 179293012 |
|
||||||
|
| fei | trunk | Princes Highway | yes | 130099670 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns | locations |
|
||||||
|
| a,i | President Avenue,Princes Highway,Princes Highway | depart,turn left,arrive | a,b,i |
|
||||||
|
@ -222,6 +222,43 @@ Feature: Basic Roundabout
|
|||||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
||||||
|
|
||||||
|
Scenario: Mixed Entry and Exit - clockwise order
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
c a
|
||||||
|
j b f
|
||||||
|
k e
|
||||||
|
l h d
|
||||||
|
g i
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | junction | oneway |
|
||||||
|
| abc | | yes |
|
||||||
|
| def | | yes |
|
||||||
|
| ghi | | yes |
|
||||||
|
| jkl | | yes |
|
||||||
|
| behkb | roundabout | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
|
||||||
|
| a,l | abc,jkl,jkl | depart,roundabout-exit-3,arrive |
|
||||||
|
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
||||||
|
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
|
||||||
|
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
||||||
|
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
|
||||||
|
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
||||||
|
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
|
||||||
|
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
||||||
|
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
|
||||||
|
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
||||||
|
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
|
||||||
|
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
||||||
|
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
|
||||||
|
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||||
|
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
|
||||||
|
|
||||||
Scenario: Mixed Entry and Exit - segregated roads, different names
|
Scenario: Mixed Entry and Exit - segregated roads, different names
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@ -707,3 +744,79 @@ Feature: Basic Roundabout
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
|
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,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,7 +20,7 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
|
|||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
|
|
||||||
Scenario: Logging weight with updates over factor of 2, long segment
|
Scenario: Logging weight with updates over factor of 2, long segment
|
||||||
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
||||||
Then stderr should not contain "Speed values were used to update 2 segment(s)"
|
Then stderr should not contain "Speed values were used to update 2 segment(s)"
|
||||||
And stderr should contain "Segment: 1,2"
|
And stderr should contain "Segment: 1,2"
|
||||||
@ -44,6 +44,6 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
|
|||||||
"""
|
"""
|
||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
|
|
||||||
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
||||||
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"
|
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"
|
||||||
|
@ -16,10 +16,13 @@ module.exports = function () {
|
|||||||
|
|
||||||
var headers = new Set(table.raw()[0]);
|
var headers = new Set(table.raw()[0]);
|
||||||
|
|
||||||
|
got.code = 'unknown';
|
||||||
if (res.body.length) {
|
if (res.body.length) {
|
||||||
json = JSON.parse(res.body);
|
json = JSON.parse(res.body);
|
||||||
|
got.code = json.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (headers.has('status')) {
|
if (headers.has('status')) {
|
||||||
got.status = json.status.toString();
|
got.status = json.status.toString();
|
||||||
}
|
}
|
||||||
@ -33,7 +36,7 @@ module.exports = function () {
|
|||||||
got['#'] = row['#'];
|
got['#'] = row['#'];
|
||||||
}
|
}
|
||||||
|
|
||||||
var subMatchings = [],
|
var subMatchings = [''],
|
||||||
turns = '',
|
turns = '',
|
||||||
route = '',
|
route = '',
|
||||||
duration = '',
|
duration = '',
|
||||||
|
@ -126,6 +126,7 @@ module.exports = function () {
|
|||||||
|
|
||||||
r.query = this.query;
|
r.query = this.query;
|
||||||
r.json = JSON.parse(body);
|
r.json = JSON.parse(body);
|
||||||
|
r.code = r.json.code;
|
||||||
r.status = res.statusCode === 200 ? 'x' : null;
|
r.status = res.statusCode === 200 ? 'x' : null;
|
||||||
if (r.status) {
|
if (r.status) {
|
||||||
r.route = this.wayList(r.json.routes[0]);
|
r.route = this.wayList(r.json.routes[0]);
|
||||||
|
@ -29,8 +29,10 @@ module.exports = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var json;
|
var json;
|
||||||
|
got.code = 'unknown';
|
||||||
if (res.body.length) {
|
if (res.body.length) {
|
||||||
json = JSON.parse(res.body);
|
json = JSON.parse(res.body);
|
||||||
|
got.code = json.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('status')) {
|
if (headers.has('status')) {
|
||||||
|
@ -39,6 +39,8 @@ module.exports = function () {
|
|||||||
|
|
||||||
let json = JSON.parse(body);
|
let json = JSON.parse(body);
|
||||||
|
|
||||||
|
got.code = json.code;
|
||||||
|
|
||||||
let hasRoute = json.code === 'Ok';
|
let hasRoute = json.code === 'Ok';
|
||||||
|
|
||||||
if (hasRoute) {
|
if (hasRoute) {
|
||||||
@ -79,102 +81,102 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (headers.has('route')) {
|
if (headers.has('route')) {
|
||||||
got.route = (instructions || '').trim();
|
got.route = (instructions || '').trim();
|
||||||
|
|
||||||
if (headers.has('summary')) {
|
|
||||||
got.summary = (summary || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('alternative')) {
|
|
||||||
// TODO examine more than first alternative?
|
|
||||||
got.alternative ='';
|
|
||||||
if (json.routes && json.routes.length > 1)
|
|
||||||
got.alternative = this.wayList(json.routes[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var distance = hasRoute && json.routes[0].distance,
|
|
||||||
time = hasRoute && json.routes[0].duration,
|
|
||||||
weight = hasRoute && json.routes[0].weight;
|
|
||||||
|
|
||||||
if (headers.has('distance')) {
|
|
||||||
if (row.distance.length) {
|
|
||||||
if (!row.distance.match(/\d+m/))
|
|
||||||
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
|
||||||
got.distance = instructions ? util.format('%dm', distance) : '';
|
|
||||||
} else {
|
|
||||||
got.distance = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('weight')) {
|
|
||||||
if (row.weight.length) {
|
|
||||||
if (!row.weight.match(/[\d\.]+/))
|
|
||||||
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
|
||||||
got.weight = instructions ? util.format('%d', weight) : '';
|
|
||||||
} else {
|
|
||||||
got.weight = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('time')) {
|
|
||||||
if (!row.time.match(/\d+s/))
|
|
||||||
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
|
||||||
got.time = instructions ? util.format('%ds', time) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('lanes')) {
|
|
||||||
got.lanes = (lanes || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('speed')) {
|
|
||||||
if (row.speed !== '' && instructions) {
|
|
||||||
if (!row.speed.match(/\d+ km\/h/))
|
|
||||||
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
|
||||||
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
|
||||||
got.speed = util.format('%d km/h', speed);
|
|
||||||
} else {
|
|
||||||
got.speed = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('intersections')) {
|
|
||||||
got.intersections = (intersections || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers.has('locations')){
|
|
||||||
got.locations = (locations || '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if header matches 'a:*', parse out the values for *
|
|
||||||
// and return in that header
|
|
||||||
headers.forEach((k) => {
|
|
||||||
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
|
||||||
if (k.match(/^a:/)) {
|
|
||||||
let a_type = k.slice(2);
|
|
||||||
if (whitelist.indexOf(a_type) == -1)
|
|
||||||
return cb(new Error('Unrecognized annotation field', a_type));
|
|
||||||
if (annotation && !annotation[a_type])
|
|
||||||
return cb(new Error('Annotation not found in response', a_type));
|
|
||||||
got[k] = annotation && annotation[a_type] || '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var putValue = (key, value) => {
|
|
||||||
if (headers.has(key)) got[key] = instructions ? value : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
putValue('ref', refs);
|
|
||||||
putValue('bearing', bearings);
|
|
||||||
putValue('turns', turns);
|
|
||||||
putValue('modes', modes);
|
|
||||||
putValue('times', times);
|
|
||||||
putValue('distances', distances);
|
|
||||||
putValue('pronunciations', pronunciations);
|
|
||||||
putValue('destinations', destinations);
|
|
||||||
putValue('weight_name', weight_name);
|
|
||||||
putValue('weights', weights);
|
|
||||||
putValue('weight', weight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers.has('summary')) {
|
||||||
|
got.summary = (summary || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('alternative')) {
|
||||||
|
// TODO examine more than first alternative?
|
||||||
|
got.alternative ='';
|
||||||
|
if (json.routes && json.routes.length > 1)
|
||||||
|
got.alternative = this.wayList(json.routes[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var distance = hasRoute && json.routes[0].distance,
|
||||||
|
time = hasRoute && json.routes[0].duration,
|
||||||
|
weight = hasRoute && json.routes[0].weight;
|
||||||
|
|
||||||
|
if (headers.has('distance')) {
|
||||||
|
if (row.distance.length) {
|
||||||
|
if (!row.distance.match(/\d+m/))
|
||||||
|
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
|
||||||
|
got.distance = instructions ? util.format('%dm', distance) : '';
|
||||||
|
} else {
|
||||||
|
got.distance = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('weight')) {
|
||||||
|
if (row.weight.length) {
|
||||||
|
if (!row.weight.match(/[\d\.]+/))
|
||||||
|
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
||||||
|
got.weight = instructions ? util.format('%d', weight) : '';
|
||||||
|
} else {
|
||||||
|
got.weight = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('time')) {
|
||||||
|
if (!row.time.match(/\d+s/))
|
||||||
|
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
|
||||||
|
got.time = instructions ? util.format('%ds', time) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('lanes')) {
|
||||||
|
got.lanes = (lanes || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('speed')) {
|
||||||
|
if (row.speed !== '' && instructions) {
|
||||||
|
if (!row.speed.match(/\d+ km\/h/))
|
||||||
|
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
|
||||||
|
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
|
||||||
|
got.speed = util.format('%d km/h', speed);
|
||||||
|
} else {
|
||||||
|
got.speed = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('intersections')) {
|
||||||
|
got.intersections = (intersections || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.has('locations')){
|
||||||
|
got.locations = (locations || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if header matches 'a:*', parse out the values for *
|
||||||
|
// and return in that header
|
||||||
|
headers.forEach((k) => {
|
||||||
|
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
||||||
|
if (k.match(/^a:/)) {
|
||||||
|
let a_type = k.slice(2);
|
||||||
|
if (whitelist.indexOf(a_type) == -1)
|
||||||
|
return cb(new Error('Unrecognized annotation field', a_type));
|
||||||
|
if (annotation && !annotation[a_type])
|
||||||
|
return cb(new Error('Annotation not found in response', a_type));
|
||||||
|
got[k] = annotation && annotation[a_type] || '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var putValue = (key, value) => {
|
||||||
|
if (headers.has(key)) got[key] = instructions ? value : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
putValue('ref', refs);
|
||||||
|
putValue('bearing', bearings);
|
||||||
|
putValue('turns', turns);
|
||||||
|
putValue('modes', modes);
|
||||||
|
putValue('times', times);
|
||||||
|
putValue('distances', distances);
|
||||||
|
putValue('pronunciations', pronunciations);
|
||||||
|
putValue('destinations', destinations);
|
||||||
|
putValue('weight_name', weight_name);
|
||||||
|
putValue('weights', weights);
|
||||||
|
putValue('weight', weight);
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
|
@ -4,7 +4,6 @@ Feature: Basic Map Matching
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the query options
|
Given the query options
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
|
|
||||||
|
@ -36,3 +36,38 @@ Feature: Projection to nearest point on road
|
|||||||
| from | to | route | distance |
|
| from | to | route | distance |
|
||||||
| d | b | abc,abc | 0m |
|
| d | b | abc,abc | 0m |
|
||||||
| b | d | abc,abc | 0m |
|
| b | d | abc,abc | 0m |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Projection results negative duration
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
function segment_function (segment)
|
||||||
|
segment.weight = 5.5
|
||||||
|
segment.duration = 2.8
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node locations
|
||||||
|
| node | lon | lat |
|
||||||
|
| e | -51.218994 | -30.023866 |
|
||||||
|
| f | -51.218918 | -30.023741 |
|
||||||
|
| 1 | -51.219109 | -30.023766 |
|
||||||
|
| 2 | -51.219109 | -30.023764 |
|
||||||
|
| 3 | -51.219109 | -30.023763 |
|
||||||
|
| 4 | -51.219109 | -30.023762 |
|
||||||
|
| 5 | -51.219109 | -30.023761 |
|
||||||
|
| 6 | -51.219109 | -30.023756 |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ef |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | time | weight |
|
||||||
|
| 1,4 | ef,ef | 0.4m | 0.1s | 0.1 |
|
||||||
|
| 2,4 | ef,ef | 0.1m | 0s | 0 |
|
||||||
|
| 3,4 | ef,ef | 0.1m | 0s | 0 |
|
||||||
|
| 4,4 | ef,ef | 0m | 0s | 0 |
|
||||||
|
| 5,4 | ef,ef | 0.1m | 0s | 0.1 |
|
||||||
|
| 6,4 | ef,ef | 0.6m | 0.1s | 0.2 |
|
||||||
|
@ -22,7 +22,6 @@ Feature: Traffic - speeds
|
|||||||
| df | primary |
|
| df | primary |
|
||||||
| fb | primary |
|
| fb | primary |
|
||||||
And the profile "testbot"
|
And the profile "testbot"
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file
|
Scenario: Weighting based on speed file
|
||||||
@ -154,3 +153,11 @@ Feature: Traffic - speeds
|
|||||||
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
And stderr should contain "malformed"
|
And stderr should contain "malformed"
|
||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
|
|
||||||
|
Scenario: Check with an empty speed file
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
And the data has been extracted
|
||||||
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
|
And it should exit successfully
|
||||||
|
@ -31,7 +31,6 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
|
|||||||
| dg | primary |
|
| dg | primary |
|
||||||
And the profile "testbot"
|
And the profile "testbot"
|
||||||
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
|
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
|
||||||
And the extract extra arguments "--generate-edge-lookup"
|
|
||||||
|
|
||||||
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
|
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
|
||||||
Given the turn penalty file
|
Given the turn penalty file
|
||||||
|
@ -352,3 +352,64 @@ Feature: Via points
|
|||||||
| waypoints | bearings | route | turns |
|
| waypoints | bearings | route | turns |
|
||||||
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
|
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
|
||||||
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
|
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
|
||||||
|
|
||||||
|
Scenario: Continue Straight in presence of Bearings
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
h - a 1 b -- g
|
||||||
|
| |
|
||||||
|
| |- 2 c - f
|
||||||
|
| 3
|
||||||
|
e ------ d - i
|
||||||
|
|
|
||||||
|
j
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| continue_straight | false |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | no |
|
||||||
|
| bc | no |
|
||||||
|
| cdea | no |
|
||||||
|
| ah | yes |
|
||||||
|
| bg | yes |
|
||||||
|
| cf | yes |
|
||||||
|
| di | yes |
|
||||||
|
| dj | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route |
|
||||||
|
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,cdea,cdea |
|
||||||
|
|
||||||
|
Scenario: Continue Straight in presence of Bearings
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
h - a 1 b -- g
|
||||||
|
| |
|
||||||
|
| |- 2 c - f
|
||||||
|
| 3
|
||||||
|
e ------ d - i
|
||||||
|
|
|
||||||
|
j
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| continue_straight | true |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | no |
|
||||||
|
| bc | no |
|
||||||
|
| cdea | no |
|
||||||
|
| ah | yes |
|
||||||
|
| bg | yes |
|
||||||
|
| cf | yes |
|
||||||
|
| di | yes |
|
||||||
|
| dj | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | bearings | route |
|
||||||
|
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,ab,cdea,cdea,cdea |
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ Feature: Weight tests
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the query options
|
Given the query options
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
|
|
||||||
|
163
features/testbot/zero-speed-updates.feature
Normal file
163
features/testbot/zero-speed-updates.feature
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
Feature: Check zero speed updates
|
||||||
|
|
||||||
|
Scenario: Matching on restricted way, single segment
|
||||||
|
Given the query options
|
||||||
|
| geometries | geojson |
|
||||||
|
| annotations | true |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1--b--c-2-d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcd |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | code |
|
||||||
|
| 12 | NoMatch |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Matching restricted way, both segments
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1--b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | code |
|
||||||
|
| 12 | NoMatch |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Matching on restricted oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1--b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | yes |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | code |
|
||||||
|
| 12 | NoMatch |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Routing on restricted way
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | code |
|
||||||
|
| 1 | 2 | NoRoute |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Routing on restricted oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | yes |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | bearings | code |
|
||||||
|
| 1 | 2 | 270 270 | NoRoute |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Via routing on restricted oneway
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c-3-d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
2,3,0
|
||||||
|
3,2,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | code |
|
||||||
|
| 1,2,3 | NoRoute |
|
||||||
|
| 3,2,1 | NoRoute |
|
||||||
|
|
||||||
|
|
||||||
|
@trip
|
||||||
|
Scenario: Trip
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
| cb |
|
||||||
|
| da |
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
1,2,0
|
||||||
|
2,1,0
|
||||||
|
"""
|
||||||
|
|
||||||
|
When I plan a trip I should get
|
||||||
|
| waypoints | trips | code |
|
||||||
|
| a,b,c,d | abcda | NoTrips |
|
||||||
|
| d,b,c,a | dbcad | NoTrips |
|
@ -80,6 +80,8 @@ inline Result keep_all(const MatchParameters ¶ms)
|
|||||||
|
|
||||||
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(!params.coordinates.empty());
|
||||||
|
|
||||||
Result result;
|
Result result;
|
||||||
|
|
||||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||||
@ -91,10 +93,8 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
Thresholds running{0., 0};
|
Thresholds running{0., 0};
|
||||||
|
|
||||||
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
|
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
|
||||||
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
|
for (std::size_t current = 0, next = 1; next < params.coordinates.size() - 1; ++current, ++next)
|
||||||
{
|
{
|
||||||
const auto next = current + 1;
|
|
||||||
|
|
||||||
auto distance_delta = util::coordinate_calculation::haversineDistance(
|
auto distance_delta = util::coordinate_calculation::haversineDistance(
|
||||||
params.coordinates[current], params.coordinates[next]);
|
params.coordinates[current], params.coordinates[next]);
|
||||||
running.distance_in_meters += distance_delta;
|
running.distance_in_meters += distance_delta;
|
||||||
@ -130,7 +130,11 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
|
// Always use the last coordinate if more than two original coordinates
|
||||||
|
if (params.coordinates.size() > 1)
|
||||||
|
{
|
||||||
|
result.tidied_to_original.push_back(params.coordinates.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||||
|
@ -167,8 +167,8 @@ class RouteAPI : public BaseAPI
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
guidance::trimShortSegments(steps, leg_geometry);
|
guidance::trimShortSegments(steps, leg_geometry);
|
||||||
leg.steps = guidance::collapseTurnInstructions(std::move(steps));
|
leg.steps = guidance::postProcess(std::move(steps));
|
||||||
leg.steps = guidance::postProcess(std::move(leg.steps));
|
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
|
||||||
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
||||||
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
|
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
|
||||||
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
||||||
|
@ -416,6 +416,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
|
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check phantom node segments validity
|
||||||
|
auto areSegmentsValid = [](auto first, auto last) -> bool {
|
||||||
|
return std::find(first, last, INVALID_EDGE_WEIGHT) == last;
|
||||||
|
};
|
||||||
|
bool is_forward_valid_source =
|
||||||
|
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
|
||||||
|
bool is_forward_valid_target =
|
||||||
|
areSegmentsValid(forward_weight_vector.begin(),
|
||||||
|
forward_weight_vector.begin() + data.fwd_segment_position + 1);
|
||||||
|
bool is_reverse_valid_source =
|
||||||
|
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
|
||||||
|
bool is_reverse_valid_target = areSegmentsValid(
|
||||||
|
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
|
||||||
|
|
||||||
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
||||||
forward_weight,
|
forward_weight,
|
||||||
reverse_weight,
|
reverse_weight,
|
||||||
@ -425,6 +439,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_duration,
|
reverse_duration,
|
||||||
forward_duration_offset,
|
forward_duration_offset,
|
||||||
reverse_duration_offset,
|
reverse_duration_offset,
|
||||||
|
is_forward_valid_source,
|
||||||
|
is_forward_valid_target,
|
||||||
|
is_reverse_valid_source,
|
||||||
|
is_reverse_valid_target,
|
||||||
point_on_segment,
|
point_on_segment,
|
||||||
input_coordinate},
|
input_coordinate},
|
||||||
current_perpendicular_distance};
|
current_perpendicular_distance};
|
||||||
|
@ -170,10 +170,13 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
weight = weight + target_weight;
|
weight = weight + target_weight;
|
||||||
if (route_data.empty())
|
if (route_data.empty())
|
||||||
{
|
{
|
||||||
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
|
|
||||||
: source_node.forward_duration);
|
|
||||||
weight -=
|
weight -=
|
||||||
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
|
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
|
||||||
|
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
|
||||||
|
: source_node.forward_duration);
|
||||||
|
// use rectified linear unit function to avoid negative duration values
|
||||||
|
// due to flooring errors in phantom snapping
|
||||||
|
duration = std::max(0, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string summary;
|
std::string summary;
|
||||||
|
@ -222,10 +222,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
// u-------------v
|
// u-------------v
|
||||||
// | |---------| source_weight
|
// | |---------| source_weight
|
||||||
// | |---| target_weight
|
// | |---| target_weight
|
||||||
|
BOOST_ASSERT(target_weight >= source_weight);
|
||||||
const EdgeWeight weight = target_weight - source_weight;
|
const EdgeWeight weight = target_weight - source_weight;
|
||||||
const EdgeWeight duration = target_duration - source_duration;
|
|
||||||
BOOST_ASSERT(weight >= 0);
|
// use rectified linear unit function to avoid negative duration values
|
||||||
BOOST_ASSERT(duration >= 0);
|
// due to flooring errors in phantom snapping
|
||||||
|
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
|
||||||
|
const EdgeWeight duration = std::max(0, target_duration - source_duration);
|
||||||
|
|
||||||
steps.push_back(RouteStep{source_node.name_id,
|
steps.push_back(RouteStep{source_node.name_id,
|
||||||
facade.GetNameForID(source_node.name_id).to_string(),
|
facade.GetNameForID(source_node.name_id).to_string(),
|
||||||
|
@ -46,37 +46,6 @@ namespace engine
|
|||||||
|
|
||||||
struct PhantomNode
|
struct PhantomNode
|
||||||
{
|
{
|
||||||
PhantomNode(SegmentID forward_segment_id,
|
|
||||||
SegmentID reverse_segment_id,
|
|
||||||
unsigned name_id,
|
|
||||||
EdgeWeight forward_weight,
|
|
||||||
EdgeWeight reverse_weight,
|
|
||||||
EdgeWeight forward_weight_offset,
|
|
||||||
EdgeWeight reverse_weight_offset,
|
|
||||||
EdgeWeight forward_duration,
|
|
||||||
EdgeWeight reverse_duration,
|
|
||||||
EdgeWeight forward_duration_offset,
|
|
||||||
EdgeWeight reverse_duration_offset,
|
|
||||||
unsigned packed_geometry_id_,
|
|
||||||
bool is_tiny_component,
|
|
||||||
unsigned component_id,
|
|
||||||
util::Coordinate location,
|
|
||||||
util::Coordinate input_location,
|
|
||||||
unsigned short fwd_segment_position,
|
|
||||||
extractor::TravelMode forward_travel_mode,
|
|
||||||
extractor::TravelMode backward_travel_mode)
|
|
||||||
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
|
|
||||||
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
|
|
||||||
forward_weight_offset(forward_weight_offset),
|
|
||||||
reverse_weight_offset(reverse_weight_offset), forward_duration(forward_duration),
|
|
||||||
reverse_duration(reverse_duration), forward_duration_offset(forward_duration_offset),
|
|
||||||
reverse_duration_offset(reverse_duration_offset), packed_geometry_id(packed_geometry_id_),
|
|
||||||
component{component_id, is_tiny_component}, location(std::move(location)),
|
|
||||||
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
|
|
||||||
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PhantomNode()
|
PhantomNode()
|
||||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
@ -86,7 +55,9 @@ struct PhantomNode
|
|||||||
forward_duration_offset(0), reverse_duration_offset(0),
|
forward_duration_offset(0), reverse_duration_offset(0),
|
||||||
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
||||||
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE), is_valid_forward_source(false),
|
||||||
|
is_valid_forward_target(false), is_valid_reverse_source(false),
|
||||||
|
is_valid_reverse_target(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +105,23 @@ struct PhantomNode
|
|||||||
|
|
||||||
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
||||||
|
|
||||||
|
bool IsValidForwardSource() const
|
||||||
|
{
|
||||||
|
return forward_segment_id.enabled && is_valid_forward_source;
|
||||||
|
}
|
||||||
|
bool IsValidForwardTarget() const
|
||||||
|
{
|
||||||
|
return forward_segment_id.enabled && is_valid_forward_target;
|
||||||
|
}
|
||||||
|
bool IsValidReverseSource() const
|
||||||
|
{
|
||||||
|
return reverse_segment_id.enabled && is_valid_reverse_source;
|
||||||
|
}
|
||||||
|
bool IsValidReverseTarget() const
|
||||||
|
{
|
||||||
|
return reverse_segment_id.enabled && is_valid_reverse_target;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
bool operator==(const PhantomNode &other) const { return location == other.location; }
|
||||||
|
|
||||||
template <class OtherT>
|
template <class OtherT>
|
||||||
@ -146,6 +134,10 @@ struct PhantomNode
|
|||||||
EdgeWeight reverse_duration,
|
EdgeWeight reverse_duration,
|
||||||
EdgeWeight forward_duration_offset,
|
EdgeWeight forward_duration_offset,
|
||||||
EdgeWeight reverse_duration_offset,
|
EdgeWeight reverse_duration_offset,
|
||||||
|
bool is_valid_forward_source,
|
||||||
|
bool is_valid_forward_target,
|
||||||
|
bool is_valid_reverse_source,
|
||||||
|
bool is_valid_reverse_target,
|
||||||
const util::Coordinate location,
|
const util::Coordinate location,
|
||||||
const util::Coordinate input_location)
|
const util::Coordinate input_location)
|
||||||
: forward_segment_id{other.forward_segment_id},
|
: forward_segment_id{other.forward_segment_id},
|
||||||
@ -159,7 +151,11 @@ struct PhantomNode
|
|||||||
component{other.component.id, other.component.is_tiny}, location{location},
|
component{other.component.id, other.component.is_tiny}, location{location},
|
||||||
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
||||||
forward_travel_mode{other.forward_travel_mode},
|
forward_travel_mode{other.forward_travel_mode},
|
||||||
backward_travel_mode{other.backward_travel_mode}
|
backward_travel_mode{other.backward_travel_mode},
|
||||||
|
is_valid_forward_source{is_valid_forward_source},
|
||||||
|
is_valid_forward_target{is_valid_forward_target},
|
||||||
|
is_valid_reverse_source{is_valid_reverse_source},
|
||||||
|
is_valid_reverse_target{is_valid_reverse_target}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,8 +183,14 @@ struct PhantomNode
|
|||||||
unsigned short fwd_segment_position;
|
unsigned short fwd_segment_position;
|
||||||
// note 4 bits would suffice for each,
|
// note 4 bits would suffice for each,
|
||||||
// but the saved byte would be padding anyway
|
// but the saved byte would be padding anyway
|
||||||
extractor::TravelMode forward_travel_mode;
|
extractor::TravelMode forward_travel_mode : 4;
|
||||||
extractor::TravelMode backward_travel_mode;
|
extractor::TravelMode backward_travel_mode : 4;
|
||||||
|
// is phantom node valid to be used as source or target
|
||||||
|
private:
|
||||||
|
bool is_valid_forward_source : 1;
|
||||||
|
bool is_valid_forward_target : 1;
|
||||||
|
bool is_valid_reverse_source : 1;
|
||||||
|
bool is_valid_reverse_target : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
|
||||||
|
@ -41,54 +41,44 @@ bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &targ
|
|||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
|
|
||||||
template <bool DIRECTION, typename Heap>
|
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node);
|
||||||
{
|
|
||||||
BOOST_ASSERT(phantom_node.IsValid());
|
|
||||||
|
|
||||||
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
|
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
if (phantom_node.forward_segment_id.enabled)
|
const PhantomNode &phantom_node);
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
phantom_node.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
if (phantom_node.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
phantom_node.reverse_segment_id.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool DIRECTION>
|
|
||||||
void insertNodesInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
|
||||||
const PhantomNode &phantom_node)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(phantom_node.IsValid());
|
|
||||||
|
|
||||||
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
|
|
||||||
if (phantom_node.forward_segment_id.enabled)
|
|
||||||
{
|
|
||||||
heap.Insert(
|
|
||||||
phantom_node.forward_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
{phantom_node.forward_segment_id.id, weight_sign * phantom_node.GetForwardDuration()});
|
|
||||||
}
|
|
||||||
if (phantom_node.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
heap.Insert(
|
|
||||||
phantom_node.reverse_segment_id.id,
|
|
||||||
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
{phantom_node.reverse_segment_id.id, weight_sign * phantom_node.GetReverseDuration()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Heap>
|
template <typename Heap>
|
||||||
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
||||||
{
|
{
|
||||||
insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
|
const auto &source = nodes.source_phantom;
|
||||||
insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
|
if (source.IsValidForwardSource())
|
||||||
|
{
|
||||||
|
forward_heap.Insert(source.forward_segment_id.id,
|
||||||
|
-source.GetForwardWeightPlusOffset(),
|
||||||
|
source.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.IsValidReverseSource())
|
||||||
|
{
|
||||||
|
forward_heap.Insert(source.reverse_segment_id.id,
|
||||||
|
-source.GetReverseWeightPlusOffset(),
|
||||||
|
source.reverse_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &target = nodes.target_phantom;
|
||||||
|
if (target.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
reverse_heap.Insert(target.forward_segment_id.id,
|
||||||
|
target.GetForwardWeightPlusOffset(),
|
||||||
|
target.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
reverse_heap.Insert(target.reverse_segment_id.id,
|
||||||
|
target.GetReverseWeightPlusOffset(),
|
||||||
|
target.reverse_segment_id.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FacadeT>
|
template <typename FacadeT>
|
||||||
|
@ -190,6 +190,11 @@ search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
EdgeWeight weight_upper_bound,
|
EdgeWeight weight_upper_bound,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
|
if (forward_heap.Empty() || reverse_heap.Empty())
|
||||||
|
{
|
||||||
|
return std::make_tuple(
|
||||||
|
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||||
|
}
|
||||||
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
|
|
||||||
@ -389,7 +394,7 @@ getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||||
|
|
||||||
EdgeWeight weight;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
NodeID source_node, target_node;
|
NodeID source_node, target_node;
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
|
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
|
||||||
@ -402,7 +407,9 @@ getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
phantom_nodes);
|
phantom_nodes);
|
||||||
|
|
||||||
if (weight == INVALID_EDGE_WEIGHT)
|
if (weight == INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<PathData> unpacked_path;
|
std::vector<PathData> unpacked_path;
|
||||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "osrm/trip_parameters.hpp"
|
#include "osrm/trip_parameters.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/make_unique.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -81,7 +80,7 @@ inline void ParseResult(const osrm::Status &result_status, const std::string & /
|
|||||||
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
|
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
|
||||||
{
|
{
|
||||||
Nan::HandleScope scope;
|
Nan::HandleScope scope;
|
||||||
auto engine_config = boost::make_unique<osrm::EngineConfig>();
|
auto engine_config = std::make_unique<osrm::EngineConfig>();
|
||||||
|
|
||||||
if (args.Length() == 0)
|
if (args.Length() == 0)
|
||||||
{
|
{
|
||||||
@ -631,7 +630,7 @@ inline route_parameters_ptr
|
|||||||
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
route_parameters_ptr params = boost::make_unique<osrm::RouteParameters>();
|
route_parameters_ptr params = std::make_unique<osrm::RouteParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return route_parameters_ptr();
|
return route_parameters_ptr();
|
||||||
@ -681,7 +680,7 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
|||||||
inline tile_parameters_ptr
|
inline tile_parameters_ptr
|
||||||
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
|
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
|
||||||
{
|
{
|
||||||
tile_parameters_ptr params = boost::make_unique<osrm::TileParameters>();
|
tile_parameters_ptr params = std::make_unique<osrm::TileParameters>();
|
||||||
|
|
||||||
if (args.Length() < 2)
|
if (args.Length() < 2)
|
||||||
{
|
{
|
||||||
@ -742,7 +741,7 @@ inline nearest_parameters_ptr
|
|||||||
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
nearest_parameters_ptr params = boost::make_unique<osrm::NearestParameters>();
|
nearest_parameters_ptr params = std::make_unique<osrm::NearestParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return nearest_parameters_ptr();
|
return nearest_parameters_ptr();
|
||||||
@ -781,7 +780,7 @@ inline table_parameters_ptr
|
|||||||
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
table_parameters_ptr params = boost::make_unique<osrm::TableParameters>();
|
table_parameters_ptr params = std::make_unique<osrm::TableParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return table_parameters_ptr();
|
return table_parameters_ptr();
|
||||||
@ -875,7 +874,7 @@ inline trip_parameters_ptr
|
|||||||
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
trip_parameters_ptr params = boost::make_unique<osrm::TripParameters>();
|
trip_parameters_ptr params = std::make_unique<osrm::TripParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return trip_parameters_ptr();
|
return trip_parameters_ptr();
|
||||||
@ -970,7 +969,7 @@ inline match_parameters_ptr
|
|||||||
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
{
|
{
|
||||||
match_parameters_ptr params = boost::make_unique<osrm::MatchParameters>();
|
match_parameters_ptr params = std::make_unique<osrm::MatchParameters>();
|
||||||
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
|
||||||
if (!has_base_params)
|
if (!has_base_params)
|
||||||
return match_parameters_ptr();
|
return match_parameters_ptr();
|
||||||
|
@ -228,7 +228,7 @@ class FileWriter
|
|||||||
|
|
||||||
template <typename T> void WriteFrom(const T &src) { WriteFrom(&src, 1); }
|
template <typename T> void WriteFrom(const T &src) { WriteFrom(&src, 1); }
|
||||||
|
|
||||||
template <typename T> void WriteOne(const T tmp) { WriteFrom(tmp); }
|
template <typename T> void WriteOne(const T &tmp) { WriteFrom(tmp); }
|
||||||
|
|
||||||
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
||||||
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
||||||
|
@ -10,13 +10,12 @@
|
|||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/spin_mutex.h>
|
#include <tbb/spin_mutex.h>
|
||||||
|
|
||||||
#include <boost/interprocess/file_mapping.hpp>
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
#include <boost/interprocess/mapped_region.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
#include <boost/spirit/include/phoenix.hpp>
|
#include <boost/spirit/include/phoenix.hpp>
|
||||||
#include <boost/spirit/include/qi.hpp>
|
#include <boost/spirit/include/qi.hpp>
|
||||||
#include <boost/spirit/include/support_line_pos_iterator.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -24,20 +23,15 @@ namespace osrm
|
|||||||
namespace updater
|
namespace updater
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
namespace qi = boost::spirit::qi;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functor to parse a list of CSV files using "key,value,comment" grammar.
|
// Functor to parse a list of CSV files using "key,value,comment" grammar.
|
||||||
// Key and Value structures must be a model of Random Access Sequence.
|
// Key and Value structures must be a model of Random Access Sequence.
|
||||||
// Also the Value structure must have source member that will be filled
|
// Also the Value structure must have source member that will be filled
|
||||||
// with the corresponding file index in the CSV filenames vector.
|
// with the corresponding file index in the CSV filenames vector.
|
||||||
template <typename Key, typename Value> struct CSVFilesParser
|
template <typename Key, typename Value> struct CSVFilesParser
|
||||||
{
|
{
|
||||||
using Iterator = boost::spirit::line_pos_iterator<boost::spirit::istream_iterator>;
|
using Iterator = boost::iostreams::mapped_file_source::iterator;
|
||||||
using KeyRule = qi::rule<Iterator, Key()>;
|
using KeyRule = boost::spirit::qi::rule<Iterator, Key()>;
|
||||||
using ValueRule = qi::rule<Iterator, Value()>;
|
using ValueRule = boost::spirit::qi::rule<Iterator, Value()>;
|
||||||
|
|
||||||
CSVFilesParser(std::size_t start_index, const KeyRule &key_rule, const ValueRule &value_rule)
|
CSVFilesParser(std::size_t start_index, const KeyRule &key_rule, const ValueRule &value_rule)
|
||||||
: start_index(start_index), key_rule(key_rule), value_rule(value_rule)
|
: start_index(start_index), key_rule(key_rule), value_rule(value_rule)
|
||||||
@ -95,30 +89,46 @@ template <typename Key, typename Value> struct CSVFilesParser
|
|||||||
// Parse a single CSV file and return result as a vector<Key, Value>
|
// Parse a single CSV file and return result as a vector<Key, Value>
|
||||||
auto ParseCSVFile(const std::string &filename, std::size_t file_id) const
|
auto ParseCSVFile(const std::string &filename, std::size_t file_id) const
|
||||||
{
|
{
|
||||||
std::ifstream input_stream(filename, std::ios::binary);
|
namespace qi = boost::spirit::qi;
|
||||||
input_stream.unsetf(std::ios::skipws);
|
|
||||||
|
|
||||||
boost::spirit::istream_iterator sfirst(input_stream), slast;
|
|
||||||
Iterator first(sfirst), last(slast);
|
|
||||||
|
|
||||||
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
|
|
||||||
ValueRule value_source =
|
|
||||||
value_rule[qi::_val = qi::_1, boost::phoenix::bind(&Value::source, qi::_val) = file_id];
|
|
||||||
qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
|
|
||||||
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
|
|
||||||
std::vector<std::pair<Key, Value>> result;
|
std::vector<std::pair<Key, Value>> result;
|
||||||
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
|
try
|
||||||
|
|
||||||
if (!ok || first != last)
|
|
||||||
{
|
{
|
||||||
const auto message =
|
if (boost::filesystem::file_size(filename) == 0)
|
||||||
boost::format("CSV file %1% malformed on line %2%") % filename % first.position();
|
return result;
|
||||||
|
|
||||||
|
boost::iostreams::mapped_file_source mmap(filename);
|
||||||
|
auto first = mmap.begin(), last = mmap.end();
|
||||||
|
|
||||||
|
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
|
||||||
|
ValueRule value_source =
|
||||||
|
value_rule[qi::_val = qi::_1, bind(&Value::source, qi::_val) = file_id];
|
||||||
|
qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
|
||||||
|
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
|
||||||
|
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
|
||||||
|
|
||||||
|
if (!ok || first != last)
|
||||||
|
{
|
||||||
|
auto begin_of_line = first - 1;
|
||||||
|
while (begin_of_line >= mmap.begin() && *begin_of_line != '\n')
|
||||||
|
--begin_of_line;
|
||||||
|
auto line_number = std::count(mmap.begin(), first, '\n') + 1;
|
||||||
|
const auto message = boost::format("CSV file %1% malformed on line %2%:\n %3%\n") %
|
||||||
|
filename % std::to_string(line_number) %
|
||||||
|
std::string(begin_of_line + 1, std::find(first, last, '\n'));
|
||||||
|
throw util::exception(message.str() + SOURCE_REF);
|
||||||
|
}
|
||||||
|
|
||||||
|
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
catch (const boost::exception &e)
|
||||||
|
{
|
||||||
|
const auto message = boost::format("exception in loading %1%:\n %2%") % filename %
|
||||||
|
boost::diagnostic_information(e);
|
||||||
throw util::exception(message.str() + SOURCE_REF);
|
throw util::exception(message.str() + SOURCE_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
|
|
||||||
|
|
||||||
return std::move(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t start_index;
|
const std::size_t start_index;
|
||||||
|
@ -34,9 +34,9 @@
|
|||||||
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
(void)cond; \
|
(void)(cond); \
|
||||||
(void)coordinate; \
|
(void)(coordinate); \
|
||||||
(void)msg; \
|
(void)(msg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef OSRM_INDEXED_DATA_HPP
|
#ifndef OSRM_INDEXED_DATA_HPP
|
||||||
#define OSRM_INDEXED_DATA_HPP
|
#define OSRM_INDEXED_DATA_HPP
|
||||||
|
|
||||||
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/string_view.hpp"
|
#include "util/string_view.hpp"
|
||||||
|
|
||||||
@ -9,7 +11,6 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
/// prefix length.
|
/// prefix length.
|
||||||
/// Returns the block prefix length.
|
/// Returns the block prefix length.
|
||||||
template <typename Offset, typename OffsetIterator>
|
template <typename Offset, typename OffsetIterator>
|
||||||
Offset WriteBlockReference(std::ostream &out,
|
Offset WriteBlockReference(storage::io::FileWriter &out,
|
||||||
Offset data_offset,
|
Offset data_offset,
|
||||||
OffsetIterator first,
|
OffsetIterator first,
|
||||||
OffsetIterator last) const
|
OffsetIterator last) const
|
||||||
@ -105,7 +106,7 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
prefix_length += byte_length;
|
prefix_length += byte_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write((const char *)&refernce, sizeof(refernce));
|
out.WriteOne(refernce);
|
||||||
|
|
||||||
return prefix_length;
|
return prefix_length;
|
||||||
}
|
}
|
||||||
@ -118,7 +119,8 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
/// [first..last] is an inclusive range of block data.
|
/// [first..last] is an inclusive range of block data.
|
||||||
/// The length of the last item in the block is not stored.
|
/// The length of the last item in the block is not stored.
|
||||||
template <typename OffsetIterator>
|
template <typename OffsetIterator>
|
||||||
void WriteBlockPrefix(std::ostream &out, OffsetIterator first, OffsetIterator last) const
|
void
|
||||||
|
WriteBlockPrefix(storage::io::FileWriter &out, OffsetIterator first, OffsetIterator last) const
|
||||||
{
|
{
|
||||||
for (OffsetIterator curr = first, next = std::next(first); curr != last; ++curr, ++next)
|
for (OffsetIterator curr = first, next = std::next(first); curr != last; ++curr, ++next)
|
||||||
{
|
{
|
||||||
@ -127,7 +129,9 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
if (byte_length == 0)
|
if (byte_length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
out.write((const char *)&data_length, byte_length);
|
// Here, we're only writing a few bytes from the 4-byte std::uint32_t,
|
||||||
|
// so we need to cast to (char *)
|
||||||
|
out.WriteFrom((const char *)&data_length, byte_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,20 +179,23 @@ template <int N, typename T = std::string> struct FixedGroupBlock
|
|||||||
/// Write a block reference {offset}, where offset is a global block offset
|
/// Write a block reference {offset}, where offset is a global block offset
|
||||||
/// Returns the fixed block prefix length.
|
/// Returns the fixed block prefix length.
|
||||||
template <typename Offset, typename OffsetIterator>
|
template <typename Offset, typename OffsetIterator>
|
||||||
Offset
|
Offset WriteBlockReference(storage::io::FileWriter &out,
|
||||||
WriteBlockReference(std::ostream &out, Offset data_offset, OffsetIterator, OffsetIterator) const
|
Offset data_offset,
|
||||||
|
OffsetIterator,
|
||||||
|
OffsetIterator) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(data_offset <= std::numeric_limits<decltype(BlockReference::offset)>::max());
|
BOOST_ASSERT(data_offset <= std::numeric_limits<decltype(BlockReference::offset)>::max());
|
||||||
|
|
||||||
BlockReference refernce{static_cast<decltype(BlockReference::offset)>(data_offset)};
|
BlockReference refernce{static_cast<decltype(BlockReference::offset)>(data_offset)};
|
||||||
out.write((const char *)&refernce, sizeof(refernce));
|
out.WriteOne(refernce);
|
||||||
|
|
||||||
return BLOCK_SIZE;
|
return BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a fixed length block prefix.
|
/// Write a fixed length block prefix.
|
||||||
template <typename OffsetIterator>
|
template <typename OffsetIterator>
|
||||||
void WriteBlockPrefix(std::ostream &out, OffsetIterator first, OffsetIterator last) const
|
void
|
||||||
|
WriteBlockPrefix(storage::io::FileWriter &out, OffsetIterator first, OffsetIterator last) const
|
||||||
{
|
{
|
||||||
std::uint32_t index = 0;
|
std::uint32_t index = 0;
|
||||||
std::array<ValueType, BLOCK_SIZE> block_prefix;
|
std::array<ValueType, BLOCK_SIZE> block_prefix;
|
||||||
@ -200,7 +207,7 @@ template <int N, typename T = std::string> struct FixedGroupBlock
|
|||||||
|
|
||||||
block_prefix[index++] = static_cast<ValueType>(data_length);
|
block_prefix[index++] = static_cast<ValueType>(data_length);
|
||||||
}
|
}
|
||||||
out.write((const char *)block_prefix.data(), block_prefix.size());
|
out.WriteFrom(block_prefix.data(), block_prefix.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advances the range to an item stored in the referenced block.
|
/// Advances the range to an item stored in the referenced block.
|
||||||
@ -244,8 +251,10 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
bool empty() const { return blocks_number == 0; }
|
bool empty() const { return blocks_number == 0; }
|
||||||
|
|
||||||
template <typename OffsetIterator, typename DataIterator>
|
template <typename OffsetIterator, typename DataIterator>
|
||||||
void
|
void write(storage::io::FileWriter &out,
|
||||||
write(std::ostream &out, OffsetIterator first, OffsetIterator last, DataIterator data) const
|
OffsetIterator first,
|
||||||
|
OffsetIterator last,
|
||||||
|
DataIterator data) const
|
||||||
{
|
{
|
||||||
static_assert(sizeof(typename DataIterator::value_type) == 1, "data basic type must char");
|
static_assert(sizeof(typename DataIterator::value_type) == 1, "data basic type must char");
|
||||||
|
|
||||||
@ -259,7 +268,7 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
const BlocksNumberType number_of_blocks =
|
const BlocksNumberType number_of_blocks =
|
||||||
number_of_elements == 0 ? 0
|
number_of_elements == 0 ? 0
|
||||||
: 1 + (std::distance(first, sentinel) - 1) / (BLOCK_SIZE + 1);
|
: 1 + (std::distance(first, sentinel) - 1) / (BLOCK_SIZE + 1);
|
||||||
out.write((const char *)&number_of_blocks, sizeof(number_of_blocks));
|
out.WriteOne(number_of_blocks);
|
||||||
|
|
||||||
// Write block references and compute the total data size that includes prefix and data
|
// Write block references and compute the total data size that includes prefix and data
|
||||||
const GroupBlock block;
|
const GroupBlock block;
|
||||||
@ -273,7 +282,7 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the total data size
|
// Write the total data size
|
||||||
out.write((const char *)&data_size, sizeof(data_size));
|
out.WriteOne(data_size);
|
||||||
|
|
||||||
// Write data blocks that are (prefix, data)
|
// Write data blocks that are (prefix, data)
|
||||||
for (OffsetIterator curr = first, next = first; next != sentinel; curr = next)
|
for (OffsetIterator curr = first, next = first; next != sentinel; curr = next)
|
||||||
@ -281,7 +290,8 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
std::advance(next, std::min<diff_type>(BLOCK_SIZE, std::distance(next, sentinel)));
|
std::advance(next, std::min<diff_type>(BLOCK_SIZE, std::distance(next, sentinel)));
|
||||||
block.WriteBlockPrefix(out, curr, next);
|
block.WriteBlockPrefix(out, curr, next);
|
||||||
std::advance(next, std::min<diff_type>(1, std::distance(next, sentinel)));
|
std::advance(next, std::min<diff_type>(1, std::distance(next, sentinel)));
|
||||||
std::copy(data + *curr, data + *next, std::ostream_iterator<unsigned char>(out));
|
std::for_each(
|
||||||
|
data + *curr, data + *next, [&out](const auto &element) { out.WriteOne(element); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/iostreams/device/mapped_file.hpp>
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
|
||||||
@ -204,73 +203,78 @@ class StaticRTree
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// open leaf file
|
std::vector<TreeNode> tree_nodes_in_level;
|
||||||
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
|
||||||
|
|
||||||
// sort the hilbert-value representatives
|
// sort the hilbert-value representatives
|
||||||
tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
||||||
std::vector<TreeNode> tree_nodes_in_level;
|
|
||||||
|
|
||||||
// pack M elements into leaf node, write to leaf file and add child index to the parent node
|
|
||||||
uint64_t wrapped_element_index = 0;
|
|
||||||
for (std::uint32_t node_index = 0; wrapped_element_index < element_count; ++node_index)
|
|
||||||
{
|
{
|
||||||
TreeNode current_node;
|
storage::io::FileWriter leaf_node_file(leaf_node_filename,
|
||||||
for (std::uint32_t leaf_index = 0;
|
storage::io::FileWriter::HasNoFingerprint);
|
||||||
leaf_index < BRANCHING_FACTOR && wrapped_element_index < element_count;
|
|
||||||
++leaf_index)
|
// pack M elements into leaf node, write to leaf file and add child index to the parent
|
||||||
|
// node
|
||||||
|
uint64_t wrapped_element_index = 0;
|
||||||
|
for (std::uint32_t node_index = 0; wrapped_element_index < element_count; ++node_index)
|
||||||
{
|
{
|
||||||
LeafNode current_leaf;
|
TreeNode current_node;
|
||||||
Rectangle &rectangle = current_leaf.minimum_bounding_rectangle;
|
for (std::uint32_t leaf_index = 0;
|
||||||
for (std::uint32_t object_index = 0;
|
leaf_index < BRANCHING_FACTOR && wrapped_element_index < element_count;
|
||||||
object_index < LEAF_NODE_SIZE && wrapped_element_index < element_count;
|
++leaf_index)
|
||||||
++object_index, ++wrapped_element_index)
|
|
||||||
{
|
{
|
||||||
const std::uint32_t input_object_index =
|
LeafNode current_leaf;
|
||||||
input_wrapper_vector[wrapped_element_index].m_array_index;
|
Rectangle &rectangle = current_leaf.minimum_bounding_rectangle;
|
||||||
const EdgeDataT &object = input_data_vector[input_object_index];
|
for (std::uint32_t object_index = 0;
|
||||||
|
object_index < LEAF_NODE_SIZE && wrapped_element_index < element_count;
|
||||||
|
++object_index, ++wrapped_element_index)
|
||||||
|
{
|
||||||
|
const std::uint32_t input_object_index =
|
||||||
|
input_wrapper_vector[wrapped_element_index].m_array_index;
|
||||||
|
const EdgeDataT &object = input_data_vector[input_object_index];
|
||||||
|
|
||||||
current_leaf.object_count += 1;
|
current_leaf.object_count += 1;
|
||||||
current_leaf.objects[object_index] = object;
|
current_leaf.objects[object_index] = object;
|
||||||
|
|
||||||
Coordinate projected_u{
|
Coordinate projected_u{
|
||||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})};
|
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})};
|
||||||
Coordinate projected_v{
|
Coordinate projected_v{
|
||||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.v]})};
|
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.v]})};
|
||||||
|
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_u.lon).operator double()) <= 180.);
|
BOOST_ASSERT(std::abs(toFloating(projected_u.lon).operator double()) <=
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_u.lat).operator double()) <= 180.);
|
180.);
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_v.lon).operator double()) <= 180.);
|
BOOST_ASSERT(std::abs(toFloating(projected_u.lat).operator double()) <=
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_v.lat).operator double()) <= 180.);
|
180.);
|
||||||
|
BOOST_ASSERT(std::abs(toFloating(projected_v.lon).operator double()) <=
|
||||||
|
180.);
|
||||||
|
BOOST_ASSERT(std::abs(toFloating(projected_v.lat).operator double()) <=
|
||||||
|
180.);
|
||||||
|
|
||||||
rectangle.min_lon =
|
rectangle.min_lon =
|
||||||
std::min(rectangle.min_lon, std::min(projected_u.lon, projected_v.lon));
|
std::min(rectangle.min_lon, std::min(projected_u.lon, projected_v.lon));
|
||||||
rectangle.max_lon =
|
rectangle.max_lon =
|
||||||
std::max(rectangle.max_lon, std::max(projected_u.lon, projected_v.lon));
|
std::max(rectangle.max_lon, std::max(projected_u.lon, projected_v.lon));
|
||||||
|
|
||||||
rectangle.min_lat =
|
rectangle.min_lat =
|
||||||
std::min(rectangle.min_lat, std::min(projected_u.lat, projected_v.lat));
|
std::min(rectangle.min_lat, std::min(projected_u.lat, projected_v.lat));
|
||||||
rectangle.max_lat =
|
rectangle.max_lat =
|
||||||
std::max(rectangle.max_lat, std::max(projected_u.lat, projected_v.lat));
|
std::max(rectangle.max_lat, std::max(projected_u.lat, projected_v.lat));
|
||||||
|
|
||||||
BOOST_ASSERT(rectangle.IsValid());
|
BOOST_ASSERT(rectangle.IsValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the leaf node to the current tree node
|
||||||
|
current_node.child_count += 1;
|
||||||
|
current_node.children[leaf_index] =
|
||||||
|
TreeIndex{node_index * BRANCHING_FACTOR + leaf_index, true};
|
||||||
|
current_node.minimum_bounding_rectangle.MergeBoundingBoxes(
|
||||||
|
current_leaf.minimum_bounding_rectangle);
|
||||||
|
|
||||||
|
// write leaf_node to leaf node file
|
||||||
|
leaf_node_file.WriteOne(current_leaf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the leaf node to the current tree node
|
tree_nodes_in_level.emplace_back(current_node);
|
||||||
current_node.child_count += 1;
|
|
||||||
current_node.children[leaf_index] =
|
|
||||||
TreeIndex{node_index * BRANCHING_FACTOR + leaf_index, true};
|
|
||||||
current_node.minimum_bounding_rectangle.MergeBoundingBoxes(
|
|
||||||
current_leaf.minimum_bounding_rectangle);
|
|
||||||
|
|
||||||
// write leaf_node to leaf node file
|
|
||||||
leaf_node_file.write((char *)¤t_leaf, sizeof(current_leaf));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_nodes_in_level.emplace_back(current_node);
|
|
||||||
}
|
}
|
||||||
leaf_node_file.flush();
|
|
||||||
leaf_node_file.close();
|
|
||||||
|
|
||||||
std::uint32_t processing_level = 0;
|
std::uint32_t processing_level = 0;
|
||||||
while (1 < tree_nodes_in_level.size())
|
while (1 < tree_nodes_in_level.size())
|
||||||
@ -332,15 +336,17 @@ class StaticRTree
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// open tree file
|
{
|
||||||
storage::io::FileWriter tree_node_file(tree_node_filename,
|
// open tree file
|
||||||
storage::io::FileWriter::HasNoFingerprint);
|
storage::io::FileWriter tree_node_file(tree_node_filename,
|
||||||
|
storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
|
||||||
std::uint64_t size_of_tree = m_search_tree.size();
|
std::uint64_t size_of_tree = m_search_tree.size();
|
||||||
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||||
|
|
||||||
tree_node_file.WriteOne(size_of_tree);
|
tree_node_file.WriteOne(size_of_tree);
|
||||||
tree_node_file.WriteFrom(&m_search_tree[0], size_of_tree);
|
tree_node_file.WriteFrom(&m_search_tree[0], size_of_tree);
|
||||||
|
}
|
||||||
|
|
||||||
MapLeafNodesFile(leaf_node_filename);
|
MapLeafNodesFile(leaf_node_filename);
|
||||||
}
|
}
|
||||||
@ -379,6 +385,24 @@ class StaticRTree
|
|||||||
std::size_t num_leaves = m_leaves_region.size() / sizeof(LeafNode);
|
std::size_t num_leaves = m_leaves_region.size() / sizeof(LeafNode);
|
||||||
auto data_ptr = m_leaves_region.data();
|
auto data_ptr = m_leaves_region.data();
|
||||||
BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(LeafNode) == 0);
|
BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(LeafNode) == 0);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Find the maximum leaf node ID and make sure we have that many from our file
|
||||||
|
BOOST_ASSERT(m_search_tree.size() > 0);
|
||||||
|
std::uint32_t max_leaf_node_id = 0;
|
||||||
|
// Search in reverse, the bottom of the tree is at the end of the array
|
||||||
|
for (auto iter = m_search_tree.rbegin(); iter != m_search_tree.rend(); iter++)
|
||||||
|
{
|
||||||
|
// If we find a non-leaf node, we can quit, we've seen the
|
||||||
|
// bottom level of the tree
|
||||||
|
if (iter->child_count > 0 && !iter->children[0].is_leaf)
|
||||||
|
break;
|
||||||
|
for (std::uint32_t i = 0; i < iter->child_count; ++i)
|
||||||
|
{
|
||||||
|
max_leaf_node_id = std::max(max_leaf_node_id, iter->children[i].index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(max_leaf_node_id == num_leaves - 1);
|
||||||
|
#endif
|
||||||
m_leaves.reset(reinterpret_cast<const LeafNode *>(data_ptr), num_leaves);
|
m_leaves.reset(reinterpret_cast<const LeafNode *>(data_ptr), num_leaves);
|
||||||
}
|
}
|
||||||
catch (const std::exception &exc)
|
catch (const std::exception &exc)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.7.0-latest.6",
|
"version": "5.7.3",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -101,6 +101,10 @@ local profile = {
|
|||||||
'tertiary_link'
|
'tertiary_link'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
service_penalties = {
|
||||||
|
alley = 0.5,
|
||||||
|
},
|
||||||
|
|
||||||
bicycle_speeds = {
|
bicycle_speeds = {
|
||||||
cycleway = default_speed,
|
cycleway = default_speed,
|
||||||
primary = default_speed,
|
primary = default_speed,
|
||||||
@ -480,29 +484,29 @@ function way_function (way, result)
|
|||||||
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
|
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
|
||||||
|
|
||||||
-- convert duration into cyclability
|
-- convert duration into cyclability
|
||||||
local is_unsafe = profile.safety_penalty < 1 and profile.unsafe_highway_list[data.highway]
|
if properties.weight_name == 'cyclability' then
|
||||||
if result.forward_speed > 0 then
|
local is_unsafe = profile.safety_penalty < 1 and profile.unsafe_highway_list[data.highway]
|
||||||
-- convert from km/h to m/s
|
local is_undesireable = data.highway == "service" and profile.service_penalties[service]
|
||||||
result.forward_rate = result.forward_speed / 3.6;
|
local penalty = 1.0
|
||||||
if is_unsafe then
|
if is_unsafe then
|
||||||
result.forward_rate = result.forward_rate * profile.safety_penalty
|
penalty = math.min(penalty, profile.safety_penalty)
|
||||||
end
|
end
|
||||||
end
|
if is_undesireable then
|
||||||
if result.backward_speed > 0 then
|
penalty = math.min(penalty, profile.service_penalties[service])
|
||||||
-- convert from km/h to m/s
|
end
|
||||||
result.backward_rate = result.backward_speed / 3.6;
|
|
||||||
if is_unsafe then
|
|
||||||
result.backward_rate = result.backward_rate * profile.safety_penalty
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if result.duration > 0 then
|
|
||||||
result.weight = result.duration;
|
|
||||||
if is_unsafe then
|
|
||||||
result.weight = result.weight * (1+profile.safety_penalty)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
if result.forward_speed > 0 then
|
||||||
|
-- convert from km/h to m/s
|
||||||
|
result.forward_rate = result.forward_speed / 3.6 * penalty
|
||||||
|
end
|
||||||
|
if result.backward_speed > 0 then
|
||||||
|
-- convert from km/h to m/s
|
||||||
|
result.backward_rate = result.backward_speed / 3.6 * penalty
|
||||||
|
end
|
||||||
|
if result.duration > 0 then
|
||||||
|
result.weight = result.duration / penalty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local handlers = Sequence {
|
local handlers = Sequence {
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
@ -540,6 +544,7 @@ function turn_function(turn)
|
|||||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
turn.duration = turn.duration + profile.traffic_light_penalty
|
||||||
end
|
end
|
||||||
if properties.weight_name == 'cyclability' then
|
if properties.weight_name == 'cyclability' then
|
||||||
|
turn.weight = turn.duration
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = turn.weight + 3000
|
turn.weight = turn.weight + 3000
|
||||||
|
@ -34,9 +34,6 @@ local profile = {
|
|||||||
speed_reduction = 0.8,
|
speed_reduction = 0.8,
|
||||||
traffic_light_penalty = 2,
|
traffic_light_penalty = 2,
|
||||||
u_turn_penalty = 20,
|
u_turn_penalty = 20,
|
||||||
restricted_penalty = 3000,
|
|
||||||
-- Note^: abstract value but in seconds correlates approximately to 50 min
|
|
||||||
-- meaning that a route through a local access way is > 50 min faster than around
|
|
||||||
|
|
||||||
-- Note: this biases right-side driving.
|
-- Note: this biases right-side driving.
|
||||||
-- Should be inverted for left-driving countries.
|
-- Should be inverted for left-driving countries.
|
||||||
@ -392,21 +389,21 @@ function turn_function (turn)
|
|||||||
local turn_penalty = profile.turn_penalty
|
local turn_penalty = profile.turn_penalty
|
||||||
local turn_bias = profile.turn_bias
|
local turn_bias = profile.turn_bias
|
||||||
|
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = profile.traffic_light_penalty
|
||||||
|
end
|
||||||
|
|
||||||
if turn.turn_type ~= turn_type.no_turn then
|
if turn.turn_type ~= turn_type.no_turn then
|
||||||
if turn.angle >= 0 then
|
if turn.angle >= 0 then
|
||||||
turn.duration = turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
||||||
else
|
else
|
||||||
turn.duration = turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
turn.duration = turn.duration + turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.direction_modifier == direction_modifier.u_turn then
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
turn.duration = turn.duration + profile.u_turn_penalty
|
turn.duration = turn.duration + profile.u_turn_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
|
||||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
|
||||||
end
|
|
||||||
|
|
||||||
-- for distance based routing we don't want to have penalties based on turn angle
|
-- for distance based routing we don't want to have penalties based on turn angle
|
||||||
if properties.weight_name == 'distance' then
|
if properties.weight_name == 'distance' then
|
||||||
turn.weight = 0
|
turn.weight = 0
|
||||||
@ -417,7 +414,7 @@ function turn_function (turn)
|
|||||||
if properties.weight_name == 'routability' then
|
if properties.weight_name == 'routability' then
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = turn.weight + profile.restricted_penalty
|
turn.weight = properties.max_turn_weight;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -441,7 +441,7 @@ end
|
|||||||
|
|
||||||
function Handlers.handle_weights(way,result,data,profile)
|
function Handlers.handle_weights(way,result,data,profile)
|
||||||
if properties.weight_name == 'distance' then
|
if properties.weight_name == 'distance' then
|
||||||
result.weight = 0
|
result.weight = -1
|
||||||
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
||||||
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
||||||
result.forward_rate = 1
|
result.forward_rate = 1
|
||||||
|
@ -14,7 +14,7 @@ babel -V >/dev/null 2>&1 || { echo >&2 "Can't find babel. Add node_modules/.bin
|
|||||||
browserify --help >/dev/null 2>&1 || { echo >&2 "Can't find browserify. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
browserify --help >/dev/null 2>&1 || { echo >&2 "Can't find browserify. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
||||||
uglifyjs -V >/dev/null 2>&1 || { echo >&2 "Can't find uglifyjs. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
uglifyjs -V >/dev/null 2>&1 || { echo >&2 "Can't find uglifyjs. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
|
||||||
|
|
||||||
#documentation build src/nodejs/node_osrm.cpp --polyglot -f md -o docs/nodejs/api.md
|
documentation build src/nodejs/node_osrm.cpp --polyglot --markdown-toc=false -f md -o docs/nodejs/api.md
|
||||||
|
|
||||||
# Clean up previous version
|
# Clean up previous version
|
||||||
rm -rf build/docs
|
rm -rf build/docs
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
NODE_HOME=$HOME/node
|
|
||||||
export NODE_HOME
|
|
||||||
mkdir ${NODE_HOME}
|
|
||||||
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
|
|
||||||
curl https://s3.amazonaws.com/mapbox/apps/install-node/v2.0.0/run | NV=4.4.2 NP=darwin-x64 OD=${NODE_HOME} sh
|
|
||||||
else
|
|
||||||
curl https://s3.amazonaws.com/mapbox/apps/install-node/v2.0.0/run | NV=4.4.2 NP=linux-x64 OD=${NODE_HOME} sh
|
|
||||||
fi
|
|
||||||
|
|
||||||
PATH="${NODE_HOME}/bin:$PATH"
|
|
||||||
export PATH
|
|
||||||
node --version
|
|
||||||
npm --version
|
|
||||||
which node
|
|
||||||
|
|
||||||
|
|
@ -74,9 +74,6 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
|
|||||||
if (entry_step.distance < MAX_COLLAPSE_DISTANCE)
|
if (entry_step.distance < MAX_COLLAPSE_DISTANCE)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (entry_step.distance > 2 * MAX_COLLAPSE_DISTANCE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// both go roughly in the same direction
|
// both go roughly in the same direction
|
||||||
if ((entry_angle <= 185 && exit_angle <= 185) || (entry_angle >= 175 && exit_angle >= 175))
|
if ((entry_angle <= 185 && exit_angle <= 185) || (entry_angle >= 175 && exit_angle >= 175))
|
||||||
return true;
|
return true;
|
||||||
|
@ -67,7 +67,17 @@ Status TablePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
|
|||||||
return Error("TooBig", "Too many table coordinates", result);
|
return Error("TooBig", "Too many table coordinates", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto snapped_phantoms = SnapPhantomNodes(GetPhantomNodes(facade, params));
|
auto phantom_nodes = GetPhantomNodes(facade, params);
|
||||||
|
|
||||||
|
if (phantom_nodes.size() != params.coordinates.size())
|
||||||
|
{
|
||||||
|
return Error("NoSegment",
|
||||||
|
std::string("Could not find a matching segment for coordinate ") +
|
||||||
|
std::to_string(phantom_nodes.size()),
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto snapped_phantoms = SnapPhantomNodes(phantom_nodes);
|
||||||
auto result_table =
|
auto result_table =
|
||||||
algorithms.ManyToManySearch(snapped_phantoms, params.sources, params.destinations);
|
algorithms.ManyToManySearch(snapped_phantoms, params.sources, params.destinations);
|
||||||
|
|
||||||
|
@ -77,27 +77,10 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca
|
|||||||
|
|
||||||
auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);
|
auto snapped_phantoms = SnapPhantomNodes(phantom_node_pairs);
|
||||||
|
|
||||||
const bool continue_straight_at_waypoint = route_parameters.continue_straight
|
|
||||||
? *route_parameters.continue_straight
|
|
||||||
: facade.GetContinueStraightDefault();
|
|
||||||
|
|
||||||
std::vector<PhantomNodes> start_end_nodes;
|
std::vector<PhantomNodes> start_end_nodes;
|
||||||
auto build_phantom_pairs = [&start_end_nodes, continue_straight_at_waypoint](
|
auto build_phantom_pairs = [&start_end_nodes](const PhantomNode &first_node,
|
||||||
const PhantomNode &first_node, const PhantomNode &second_node) {
|
const PhantomNode &second_node) {
|
||||||
start_end_nodes.push_back(PhantomNodes{first_node, second_node});
|
start_end_nodes.push_back(PhantomNodes{first_node, second_node});
|
||||||
auto &last_inserted = start_end_nodes.back();
|
|
||||||
// enable forward direction if possible
|
|
||||||
if (last_inserted.source_phantom.forward_segment_id.id != SPECIAL_SEGMENTID)
|
|
||||||
{
|
|
||||||
last_inserted.source_phantom.forward_segment_id.enabled |=
|
|
||||||
!continue_straight_at_waypoint;
|
|
||||||
}
|
|
||||||
// enable reverse direction if possible
|
|
||||||
if (last_inserted.source_phantom.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
|
||||||
{
|
|
||||||
last_inserted.source_phantom.reverse_segment_id.enabled |=
|
|
||||||
!continue_straight_at_waypoint;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
util::for_each_pair(snapped_phantoms, build_phantom_pairs);
|
util::for_each_pair(snapped_phantoms, build_phantom_pairs);
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ InternalRouteResult directShortestPathSearch(
|
|||||||
|
|
||||||
// TODO: when structured bindings will be allowed change to
|
// TODO: when structured bindings will be allowed change to
|
||||||
// auto [weight, source_node, target_node, unpacked_edges] = ...
|
// auto [weight, source_node, target_node, unpacked_edges] = ...
|
||||||
EdgeWeight weight;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
NodeID source_node, target_node;
|
NodeID source_node, target_node;
|
||||||
std::vector<EdgeID> unpacked_edges;
|
std::vector<EdgeID> unpacked_edges;
|
||||||
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
||||||
|
@ -176,7 +176,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto search_target_phantom = [&](const PhantomNode &phantom) {
|
const auto search_target_phantom = [&](const PhantomNode &phantom) {
|
||||||
// clear heap and insert target nodes
|
// clear heap and insert target nodes
|
||||||
query_heap.Clear();
|
query_heap.Clear();
|
||||||
insertNodesInHeap<REVERSE_DIRECTION>(query_heap, phantom);
|
insertTargetInHeap(query_heap, phantom);
|
||||||
|
|
||||||
// explore search space
|
// explore search space
|
||||||
while (!query_heap.Empty())
|
while (!query_heap.Empty())
|
||||||
@ -191,7 +191,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto search_source_phantom = [&](const PhantomNode &phantom) {
|
const auto search_source_phantom = [&](const PhantomNode &phantom) {
|
||||||
// clear heap and insert source nodes
|
// clear heap and insert source nodes
|
||||||
query_heap.Clear();
|
query_heap.Clear();
|
||||||
insertNodesInHeap<FORWARD_DIRECTION>(query_heap, phantom);
|
insertSourceInHeap(query_heap, phantom);
|
||||||
|
|
||||||
// explore search space
|
// explore search space
|
||||||
while (!query_heap.Empty())
|
while (!query_heap.Empty())
|
||||||
|
@ -9,7 +9,7 @@ namespace routing_algorithms
|
|||||||
|
|
||||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
{
|
{
|
||||||
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
return source_phantom.IsValidForwardSource() && target_phantom.IsValidForwardTarget() &&
|
||||||
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
||||||
source_phantom.GetForwardWeightPlusOffset() >
|
source_phantom.GetForwardWeightPlusOffset() >
|
||||||
target_phantom.GetForwardWeightPlusOffset();
|
target_phantom.GetForwardWeightPlusOffset();
|
||||||
@ -17,12 +17,46 @@ bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &targ
|
|||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||||
{
|
{
|
||||||
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
return source_phantom.IsValidReverseSource() && target_phantom.IsValidReverseTarget() &&
|
||||||
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
||||||
source_phantom.GetReverseWeightPlusOffset() >
|
source_phantom.GetReverseWeightPlusOffset() >
|
||||||
target_phantom.GetReverseWeightPlusOffset();
|
target_phantom.GetReverseWeightPlusOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -82,6 +82,12 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
|
|||||||
const PhantomNodes & /*phantom_nodes*/,
|
const PhantomNodes & /*phantom_nodes*/,
|
||||||
const EdgeWeight weight_upper_bound)
|
const EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
|
if (forward_heap.Empty() || reverse_heap.Empty())
|
||||||
|
{
|
||||||
|
weight = INVALID_EDGE_WEIGHT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
weight = weight_upper_bound;
|
weight = weight_upper_bound;
|
||||||
|
|
||||||
@ -155,31 +161,7 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
forward_heap.Clear();
|
forward_heap.Clear();
|
||||||
reverse_heap.Clear();
|
reverse_heap.Clear();
|
||||||
|
|
||||||
if (source_phantom.forward_segment_id.enabled)
|
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
|
||||||
{
|
|
||||||
forward_heap.Insert(source_phantom.forward_segment_id.id,
|
|
||||||
-source_phantom.GetForwardWeightPlusOffset(),
|
|
||||||
source_phantom.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
if (source_phantom.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
forward_heap.Insert(source_phantom.reverse_segment_id.id,
|
|
||||||
-source_phantom.GetReverseWeightPlusOffset(),
|
|
||||||
source_phantom.reverse_segment_id.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target_phantom.forward_segment_id.enabled)
|
|
||||||
{
|
|
||||||
reverse_heap.Insert(target_phantom.forward_segment_id.id,
|
|
||||||
target_phantom.GetForwardWeightPlusOffset(),
|
|
||||||
target_phantom.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
if (target_phantom.reverse_segment_id.enabled)
|
|
||||||
{
|
|
||||||
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
|
|
||||||
target_phantom.GetReverseWeightPlusOffset(),
|
|
||||||
target_phantom.reverse_segment_id.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
|
@ -63,9 +63,6 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
target_phantom.reverse_segment_id.id);
|
target_phantom.reverse_segment_id.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(forward_heap.Size() > 0);
|
|
||||||
BOOST_ASSERT(reverse_heap.Size() > 0);
|
|
||||||
|
|
||||||
// this is only relevent if source and target are on the same compressed edge
|
// this is only relevent if source and target are on the same compressed edge
|
||||||
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
|
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
|
||||||
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
|
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
|
||||||
@ -236,9 +233,9 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
int total_weight_to_forward = 0;
|
int total_weight_to_forward = 0;
|
||||||
int total_weight_to_reverse = 0;
|
int total_weight_to_reverse = 0;
|
||||||
bool search_from_forward_node =
|
bool search_from_forward_node =
|
||||||
phantom_nodes_vector.front().source_phantom.forward_segment_id.enabled;
|
phantom_nodes_vector.front().source_phantom.IsValidForwardSource();
|
||||||
bool search_from_reverse_node =
|
bool search_from_reverse_node =
|
||||||
phantom_nodes_vector.front().source_phantom.reverse_segment_id.enabled;
|
phantom_nodes_vector.front().source_phantom.IsValidReverseSource();
|
||||||
|
|
||||||
std::vector<NodeID> prev_packed_leg_to_forward;
|
std::vector<NodeID> prev_packed_leg_to_forward;
|
||||||
std::vector<NodeID> prev_packed_leg_to_reverse;
|
std::vector<NodeID> prev_packed_leg_to_reverse;
|
||||||
@ -262,13 +259,11 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto &source_phantom = phantom_node_pair.source_phantom;
|
const auto &source_phantom = phantom_node_pair.source_phantom;
|
||||||
const auto &target_phantom = phantom_node_pair.target_phantom;
|
const auto &target_phantom = phantom_node_pair.target_phantom;
|
||||||
|
|
||||||
bool search_to_forward_node = target_phantom.forward_segment_id.enabled;
|
bool search_to_forward_node = target_phantom.IsValidForwardTarget();
|
||||||
bool search_to_reverse_node = target_phantom.reverse_segment_id.enabled;
|
bool search_to_reverse_node = target_phantom.IsValidReverseTarget();
|
||||||
|
|
||||||
BOOST_ASSERT(!search_from_forward_node || source_phantom.forward_segment_id.enabled);
|
BOOST_ASSERT(!search_from_forward_node || source_phantom.IsValidForwardSource());
|
||||||
BOOST_ASSERT(!search_from_reverse_node || source_phantom.reverse_segment_id.enabled);
|
BOOST_ASSERT(!search_from_reverse_node || source_phantom.IsValidReverseSource());
|
||||||
|
|
||||||
BOOST_ASSERT(search_from_forward_node || search_from_reverse_node);
|
|
||||||
|
|
||||||
if (search_to_reverse_node || search_to_forward_node)
|
if (search_to_reverse_node || search_to_forward_node)
|
||||||
{
|
{
|
||||||
@ -290,9 +285,9 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
packed_leg_to_forward);
|
packed_leg_to_forward);
|
||||||
// if only the reverse node is valid (e.g. when using the match plugin) we
|
// if only the reverse node is valid (e.g. when using the match plugin) we
|
||||||
// actually need to move
|
// actually need to move
|
||||||
if (!target_phantom.forward_segment_id.enabled)
|
if (!target_phantom.IsValidForwardTarget())
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(target_phantom.reverse_segment_id.enabled);
|
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
|
||||||
new_total_weight_to_reverse = new_total_weight_to_forward;
|
new_total_weight_to_reverse = new_total_weight_to_forward;
|
||||||
packed_leg_to_reverse = std::move(packed_leg_to_forward);
|
packed_leg_to_reverse = std::move(packed_leg_to_forward);
|
||||||
new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
|
new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
|
||||||
@ -302,7 +297,7 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
// Below we have to check if new_total_weight_to_forward is invalid.
|
// Below we have to check if new_total_weight_to_forward is invalid.
|
||||||
// This prevents use-after-move on packed_leg_to_forward.
|
// This prevents use-after-move on packed_leg_to_forward.
|
||||||
}
|
}
|
||||||
else if (target_phantom.reverse_segment_id.enabled)
|
else if (target_phantom.IsValidReverseTarget())
|
||||||
{
|
{
|
||||||
new_total_weight_to_reverse = new_total_weight_to_forward;
|
new_total_weight_to_reverse = new_total_weight_to_forward;
|
||||||
packed_leg_to_reverse = packed_leg_to_forward;
|
packed_leg_to_reverse = packed_leg_to_forward;
|
||||||
@ -390,7 +385,7 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
if (new_total_weight_to_forward != INVALID_EDGE_WEIGHT)
|
if (new_total_weight_to_forward != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(target_phantom.forward_segment_id.enabled);
|
BOOST_ASSERT(target_phantom.IsValidForwardTarget());
|
||||||
|
|
||||||
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
|
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
|
||||||
total_packed_path_to_forward.insert(total_packed_path_to_forward.end(),
|
total_packed_path_to_forward.insert(total_packed_path_to_forward.end(),
|
||||||
@ -407,7 +402,7 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
if (new_total_weight_to_reverse != INVALID_EDGE_WEIGHT)
|
if (new_total_weight_to_reverse != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(target_phantom.reverse_segment_id.enabled);
|
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
|
||||||
|
|
||||||
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
|
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
|
||||||
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),
|
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),
|
||||||
|
@ -173,7 +173,7 @@ void ExtractionContainers::WriteCharData(const std::string &file_name)
|
|||||||
util::UnbufferedLog log;
|
util::UnbufferedLog log;
|
||||||
log << "writing street name index ... ";
|
log << "writing street name index ... ";
|
||||||
TIMER_START(write_index);
|
TIMER_START(write_index);
|
||||||
boost::filesystem::ofstream file(file_name, std::ios::binary);
|
storage::io::FileWriter file(file_name, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
|
||||||
const util::NameTable::IndexedData indexed_data;
|
const util::NameTable::IndexedData indexed_data;
|
||||||
indexed_data.write(file, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
indexed_data.write(file, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "extractor/geojson_debug_policies.hpp"
|
#include "extractor/geojson_debug_policies.hpp"
|
||||||
#include "util/geojson_debug_logger.hpp"
|
#include "util/geojson_debug_logger.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
@ -278,7 +279,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// due to merging of roads, the u-turn might actually not be part of the intersection anymore
|
// due to merging of roads, the u-turn might actually not be part of the intersection anymore
|
||||||
const auto uturn_bearing = [&]() {
|
// uturn is a pair of {edge id, bearing}
|
||||||
|
const auto uturn = [&]() {
|
||||||
const auto merge_entry = std::find_if(
|
const auto merge_entry = std::find_if(
|
||||||
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
||||||
return entry.merged_eid == uturn_edge_itr->eid;
|
return entry.merged_eid == uturn_edge_itr->eid;
|
||||||
@ -291,7 +293,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
normalized_intersection.end(),
|
normalized_intersection.end(),
|
||||||
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
||||||
BOOST_ASSERT(merged_u_turn != normalized_intersection.end());
|
BOOST_ASSERT(merged_u_turn != normalized_intersection.end());
|
||||||
return util::bearing::reverse(merged_u_turn->bearing);
|
return std::make_pair(merged_u_turn->eid,
|
||||||
|
util::bearing::reverse(merged_u_turn->bearing));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -301,7 +304,9 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
connect_to_previous_node);
|
connect_to_previous_node);
|
||||||
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
||||||
normalized_intersection.end());
|
normalized_intersection.end());
|
||||||
return util::bearing::reverse(uturn_edge_at_normalized_intersection_itr->bearing);
|
return std::make_pair(
|
||||||
|
uturn_edge_at_normalized_intersection_itr->eid,
|
||||||
|
util::bearing::reverse(uturn_edge_at_normalized_intersection_itr->bearing));
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
@ -314,7 +319,7 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
return IntersectionViewData(
|
return IntersectionViewData(
|
||||||
road,
|
road,
|
||||||
is_allowed_turn(road),
|
is_allowed_turn(road),
|
||||||
util::bearing::angleBetween(uturn_bearing, road.bearing));
|
util::bearing::angleBetween(uturn.second, road.bearing));
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto uturn_edge_at_intersection_view_itr =
|
const auto uturn_edge_at_intersection_view_itr =
|
||||||
@ -369,8 +374,22 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
std::end(intersection_view),
|
std::end(intersection_view),
|
||||||
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
||||||
|
|
||||||
BOOST_ASSERT(intersection_view[0].angle >= 0. &&
|
// Move entering_via_edge to intersection front and place all roads prior entering_via_edge
|
||||||
intersection_view[0].angle < std::numeric_limits<double>::epsilon());
|
// at the end of the intersection view with 360° angle
|
||||||
|
auto entering_via_it = std::find_if(intersection_view.begin(),
|
||||||
|
intersection_view.end(),
|
||||||
|
[&uturn](auto &road) { return road.eid == uturn.first; });
|
||||||
|
|
||||||
|
OSRM_ASSERT(entering_via_it != intersection_view.end() && entering_via_it->angle >= 0. &&
|
||||||
|
entering_via_it->angle < std::numeric_limits<double>::epsilon(),
|
||||||
|
coordinates[node_at_intersection]);
|
||||||
|
|
||||||
|
if (entering_via_it != intersection_view.begin() && entering_via_it != intersection_view.end())
|
||||||
|
{
|
||||||
|
std::for_each(
|
||||||
|
intersection_view.begin(), entering_via_it, [](auto &road) { road.angle = 360.; });
|
||||||
|
std::rotate(intersection_view.begin(), entering_via_it, intersection_view.end());
|
||||||
|
}
|
||||||
|
|
||||||
return intersection_view;
|
return intersection_view;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "extractor/guidance/roundabout_handler.hpp"
|
#include "extractor/guidance/roundabout_handler.hpp"
|
||||||
#include "extractor/guidance/constants.hpp"
|
#include "extractor/guidance/constants.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/guidance/name_announcements.hpp"
|
#include "util/guidance/name_announcements.hpp"
|
||||||
@ -111,32 +112,65 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
|||||||
if (in_edge_data.roundabout || in_edge_data.circular)
|
if (in_edge_data.roundabout || in_edge_data.circular)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool past_roundabout_angle = false;
|
// Find range in which exits that must be invalidated (shaded areas):
|
||||||
const bool lhs = profile_properties.left_hand_driving;
|
// exit..end exit..end begin..exit for ↺ roundabouts
|
||||||
const int step = lhs ? -1 : 1;
|
// *************************************
|
||||||
for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size();
|
// * <--. ^ <--. / <--. *
|
||||||
++cnt, idx += step)
|
// * | / | /░ | *
|
||||||
|
// * |/ |v░░ -->| *
|
||||||
|
// * |^ |\ ░ ░░░|\ *
|
||||||
|
// * |░\ |░\░ ░░░| \ *
|
||||||
|
// * --'░░░\ --'░░░v --' v *
|
||||||
|
// *************************************
|
||||||
|
//
|
||||||
|
// begin..exit begin..exit exit..end for ↻ roundabouts
|
||||||
|
// *************************************
|
||||||
|
// * --.░░░^ --.░░░/ --. ^ *
|
||||||
|
// * |░/░ |░/ ░░░| / *
|
||||||
|
// * |/░░ |v ░░░|/ *
|
||||||
|
// * |^░░ |\ -->| *
|
||||||
|
// * | \░ | \ | *
|
||||||
|
// * <--' \ <--' v <--' *
|
||||||
|
// *************************************
|
||||||
|
bool roundabout_entry_first = false;
|
||||||
|
auto invalidate_from = intersection.end(), invalidate_to = intersection.end();
|
||||||
|
for (auto road = intersection.begin(); road != intersection.end(); ++road)
|
||||||
{
|
{
|
||||||
auto &road = intersection[idx];
|
const auto &edge_data = node_based_graph.GetEdgeData(road->eid);
|
||||||
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
|
if (edge_data.roundabout || edge_data.circular)
|
||||||
// only check actual outgoing edges
|
|
||||||
if (edge_data.reversed)
|
|
||||||
{
|
{
|
||||||
// remember whether we have seen the roundabout in-part
|
if (edge_data.reversed)
|
||||||
if (edge_data.roundabout || edge_data.circular)
|
{
|
||||||
past_roundabout_angle = true;
|
if (roundabout_entry_first)
|
||||||
|
{ // invalidate turns in range exit..end
|
||||||
continue;
|
invalidate_from = road + 1;
|
||||||
|
invalidate_to = intersection.end();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // invalidate turns in range begin..exit
|
||||||
|
invalidate_from = intersection.begin() + 1;
|
||||||
|
invalidate_to = road;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roundabout_entry_first = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
OSRM_ASSERT(invalidate_from <= invalidate_to, coordinates[from_nid]);
|
||||||
// This workaround handles cases in which an exit precedes and entry. The resulting
|
|
||||||
// u-turn against the roundabout direction is invalidated.
|
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
||||||
// The sorting of the angles represents a problem for left-sided driving, though.
|
// This workaround handles cases in which an exit precedes and entry. The resulting
|
||||||
|
// u-turn against the roundabout direction is invalidated.
|
||||||
|
for (; invalidate_from != invalidate_to; ++invalidate_from)
|
||||||
|
{
|
||||||
|
const auto &edge_data = node_based_graph.GetEdgeData(invalidate_from->eid);
|
||||||
if (!edge_data.roundabout && !edge_data.circular &&
|
if (!edge_data.roundabout && !edge_data.circular &&
|
||||||
node_based_graph.GetTarget(road.eid) != from_nid && past_roundabout_angle)
|
node_based_graph.GetTarget(invalidate_from->eid) != from_nid)
|
||||||
{
|
{
|
||||||
road.entry_allowed = false;
|
invalidate_from->entry_allowed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,43 +50,31 @@ NAN_MODULE_INIT(Engine::Init)
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* The `OSRM` method is the main constructor for creating an OSRM instance.
|
* The `OSRM` method is the main constructor for creating an OSRM instance.
|
||||||
* An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
* An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
|
||||||
* The documentation on `osrm-extract` and `osrm-contract` for more information.
|
* You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
|
||||||
* Once you have a complete `network.osrm` file, you can calculate routes in javascript with this library using the methods below.
|
* profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
|
||||||
* To create an OSRM instance with your network you need to construct an instance like this:
|
*
|
||||||
|
* node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
|
||||||
|
* node_modules/osrm/lib/binding/osrm-contract data.osrm
|
||||||
|
*
|
||||||
|
* Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
|
||||||
|
*
|
||||||
|
* Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* var osrm = new OSRM('network.osrm');
|
* var osrm = new OSRM('network.osrm');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* #### Methods
|
* @param {Object|String} [options={shared_memory: true}] Options for creating an OSRM object or string to the `.osrm` file.
|
||||||
*
|
* @param {String} [options.algorithm] The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
|
||||||
* | Service | Description |
|
* Make sure you prepared the dataset with the correct toolchain.
|
||||||
* |-----------------------------|-----------------------------------------------------------|
|
* @param {Boolean} [options.shared_memory] Connects to the persistent shared memory datastore.
|
||||||
* | [`osrm.route`](#route) | shortest path between given coordinates |
|
* This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
||||||
* | [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
|
* @param {String} [options.path] The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
|
||||||
* | [`osrm.table`](#table) | computes distance tables for given coordinates |
|
|
||||||
* | [`osrm.match`](#match) | matches given coordinates to the road network |
|
|
||||||
* | [`osrm.trip`](#trip) | computes the shortest trip between given coordinates |
|
|
||||||
* | [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
|
|
||||||
*
|
|
||||||
* #### General Options
|
|
||||||
*
|
|
||||||
* Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options,
|
|
||||||
* outlined below.
|
|
||||||
*
|
|
||||||
* | Option | Values | Description | Format |
|
|
||||||
* | ----------- | -----------------| ------------ | -------|
|
|
||||||
* | coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
|
|
||||||
* | bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
|
|
||||||
* | radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
|
|
||||||
* | hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
|
|
||||||
*
|
*
|
||||||
* @class OSRM
|
* @class OSRM
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
// clang-format on
|
// clang-format on
|
||||||
NAN_METHOD(Engine::New)
|
NAN_METHOD(Engine::New)
|
||||||
@ -192,11 +180,15 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
|||||||
* @name route
|
* @name route
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options Object literal containing parameters for the route query.
|
* @param {Object} options Object literal containing parameters for the route query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Boolean} [options.alternatives=false] Search for alternative routes and return as well.
|
* @param {Boolean} [options.alternatives=false] Search for alternative routes and return as well.
|
||||||
* *Please note that even if an alternative route is requested, a result cannot be guaranteed.*
|
* *Please note that even if an alternative route is requested, a result cannot be guaranteed.*
|
||||||
* @param {Boolean} [options.steps=false] Return route steps for each route leg.
|
* @param {Boolean} [options.steps=false] Return route steps for each route leg.
|
||||||
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
|
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
|
||||||
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
|
|
||||||
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
||||||
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
||||||
* @param {Boolean} [options.continue_straight] Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
|
* @param {Boolean} [options.continue_straight] Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
|
||||||
@ -228,6 +220,11 @@ NAN_METHOD(Engine::route) //
|
|||||||
* @name nearest
|
* @name nearest
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the nearest query.
|
* @param {Object} options - Object literal containing parameters for the nearest query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Number} [options.number=1] Number of nearest segments that should be returned.
|
* @param {Number} [options.number=1] Number of nearest segments that should be returned.
|
||||||
* Must be an integer greater than or equal to `1`.
|
* Must be an integer greater than or equal to `1`.
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
@ -261,6 +258,11 @@ NAN_METHOD(Engine::nearest) //
|
|||||||
* @name table
|
* @name table
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the table query.
|
* @param {Object} options - Object literal containing parameters for the table query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Array} [options.sources] An array of `index` elements (`0 <= integer < #coordinates`) to
|
* @param {Array} [options.sources] An array of `index` elements (`0 <= integer < #coordinates`) to
|
||||||
* use
|
* use
|
||||||
* location with given index as source. Default is to use all.
|
* location with given index as source. Default is to use all.
|
||||||
@ -337,13 +339,16 @@ NAN_METHOD(Engine::tile)
|
|||||||
* @name match
|
* @name match
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the match query.
|
* @param {Object} options - Object literal containing parameters for the match query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
||||||
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg.
|
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
|
||||||
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
|
|
||||||
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
||||||
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
|
||||||
* @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like timestamp).
|
* @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like timestamp).
|
||||||
* @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy (`double >= 0`, default `5m`).
|
* @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*
|
*
|
||||||
* @returns {Object} containing `tracepoints` and `matchings`.
|
* @returns {Object} containing `tracepoints` and `matchings`.
|
||||||
@ -380,14 +385,32 @@ NAN_METHOD(Engine::match) //
|
|||||||
* (farthest-insertion algorithm) for 10 or * more waypoints and uses brute force for less than 10
|
* (farthest-insertion algorithm) for 10 or * more waypoints and uses brute force for less than 10
|
||||||
* waypoints. The returned path does not have to be the shortest path, * as TSP is NP-hard it is
|
* waypoints. The returned path does not have to be the shortest path, * as TSP is NP-hard it is
|
||||||
* only an approximation.
|
* only an approximation.
|
||||||
|
*
|
||||||
* Note that all input coordinates have to be connected for the trip service to work.
|
* Note that all input coordinates have to be connected for the trip service to work.
|
||||||
|
* Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
|
||||||
|
* Right now, the following combinations are possible:
|
||||||
|
*
|
||||||
|
* | roundtrip | source | destination | supported |
|
||||||
|
* | :-- | :-- | :-- | :-- |
|
||||||
|
* | true | first | last | **yes** |
|
||||||
|
* | true | first | any | **yes** |
|
||||||
|
* | true | any | last | **yes** |
|
||||||
|
* | true | any | any | **yes** |
|
||||||
|
* | false | first | last | **yes** |
|
||||||
|
* | false | first | any | no |
|
||||||
|
* | false | any | last | no |
|
||||||
|
* | false | any | any | no |
|
||||||
*
|
*
|
||||||
* @name trip
|
* @name trip
|
||||||
* @memberof OSRM
|
* @memberof OSRM
|
||||||
* @param {Object} options - Object literal containing parameters for the trip query.
|
* @param {Object} options - Object literal containing parameters for the trip query.
|
||||||
|
* @param {Array} [options.coordinates] The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
|
||||||
|
* @param {Array} [options.bearings] Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
|
||||||
|
* Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
|
||||||
|
* @param {Array} [options.radiuses] Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
|
||||||
|
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||||
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
* @param {Boolean} [options.steps=false] Return route steps for each route.
|
||||||
* @param {Boolean} or {Array} [options.annotations=false] Return annotations for each route leg. Can be `false`,
|
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
|
||||||
* `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
|
|
||||||
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
|
||||||
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
|
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified`
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
@ -398,8 +421,8 @@ NAN_METHOD(Engine::match) //
|
|||||||
* @returns {Object} containing `waypoints` and `trips`.
|
* @returns {Object} containing `waypoints` and `trips`.
|
||||||
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
|
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
|
||||||
* Each Waypoint object has the following additional properties,
|
* Each Waypoint object has the following additional properties,
|
||||||
* 1) `trips_index`: index to trips of the sub-trip the point was matched to,
|
* 1) `trips_index`: index to trips of the sub-trip the point was matched to, and
|
||||||
* and 2) `waypoint_index`: index of the point in the trip.
|
* 2) `waypoint_index`: index of the point in the trip.
|
||||||
* **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
* **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@ -408,7 +431,10 @@ NAN_METHOD(Engine::match) //
|
|||||||
* coordinates: [
|
* coordinates: [
|
||||||
* [13.36761474609375, 52.51663871100423],
|
* [13.36761474609375, 52.51663871100423],
|
||||||
* [13.374481201171875, 52.506191342034576]
|
* [13.374481201171875, 52.506191342034576]
|
||||||
* ]
|
* ],
|
||||||
|
* source: "first",
|
||||||
|
* destination: "last",
|
||||||
|
* roundtrip: false
|
||||||
* }
|
* }
|
||||||
* osrm.trip(options, function(err, response) {
|
* osrm.trip(options, function(err, response) {
|
||||||
* if (err) throw err;
|
* if (err) throw err;
|
||||||
|
@ -53,10 +53,10 @@ BOOST_AUTO_TEST_CASE(two_item_trace_needs_tidiying_test)
|
|||||||
auto result = tidy::tidy(params, thresholds);
|
auto result = tidy::tidy(params, thresholds);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
BOOST_CHECK_EQUAL(result.can_be_removed.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 1);
|
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[1], true);
|
BOOST_CHECK_EQUAL(result.can_be_removed[1], false);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,16 +87,18 @@ BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_test)
|
|||||||
auto result = tidy::tidy(params, thresholds);
|
auto result = tidy::tidy(params, thresholds);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 3);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||||
|
BOOST_CHECK_EQUAL(result.tidied_to_original[2], 5);
|
||||||
|
|
||||||
const auto redundant = result.can_be_removed.count();
|
const auto redundant = result.can_be_removed.count();
|
||||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 3);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||||
|
BOOST_CHECK_EQUAL(result.can_be_removed[5], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
||||||
@ -118,15 +120,17 @@ BOOST_AUTO_TEST_CASE(two_blobs_in_traces_needs_tidiying_no_timestamps_test)
|
|||||||
auto result = tidy::tidy(params, thresholds);
|
auto result = tidy::tidy(params, thresholds);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
BOOST_CHECK_EQUAL(result.can_be_removed.size(), params.coordinates.size());
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 2);
|
BOOST_CHECK_EQUAL(result.tidied_to_original.size(), 3);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[0], 0);
|
||||||
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
BOOST_CHECK_EQUAL(result.tidied_to_original[1], 3);
|
||||||
|
BOOST_CHECK_EQUAL(result.tidied_to_original[2], 5);
|
||||||
|
|
||||||
const auto redundant = result.can_be_removed.count();
|
const auto redundant = result.can_be_removed.count();
|
||||||
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 2);
|
BOOST_CHECK_EQUAL(redundant, params.coordinates.size() - 3);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[0], false);
|
||||||
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
BOOST_CHECK_EQUAL(result.can_be_removed[3], false);
|
||||||
|
BOOST_CHECK_EQUAL(result.can_be_removed[5], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -151,4 +151,27 @@ BOOST_AUTO_TEST_CASE(test_table_three_coordinates_matrix)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://github.com/Project-OSRM/osrm-backend/pull/3992
|
||||||
|
BOOST_AUTO_TEST_CASE(test_table_no_segment_for_some_coordinates)
|
||||||
|
{
|
||||||
|
using namespace osrm;
|
||||||
|
|
||||||
|
auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");
|
||||||
|
|
||||||
|
TableParameters params;
|
||||||
|
params.coordinates.push_back(get_dummy_location());
|
||||||
|
params.coordinates.push_back(get_dummy_location());
|
||||||
|
// resembles query option: `&radiuses=0;`
|
||||||
|
params.radiuses.push_back(boost::make_optional(0.));
|
||||||
|
params.radiuses.push_back(boost::none);
|
||||||
|
|
||||||
|
json::Object result;
|
||||||
|
|
||||||
|
const auto rc = osrm.Table(params, result);
|
||||||
|
|
||||||
|
BOOST_CHECK(rc == Status::Error);
|
||||||
|
const auto code = result.values.at("code").get<json::String>().value;
|
||||||
|
BOOST_CHECK_EQUAL(code, "NoSegment");
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "util/indexed_data.hpp"
|
#include "util/indexed_data.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include <boost/test/test_case_template.hpp>
|
#include <boost/test/test_case_template.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@ -34,11 +36,18 @@ BOOST_AUTO_TEST_CASE(check_variable_group_block_bitops)
|
|||||||
template <typename IndexedData, typename Offsets, typename Data>
|
template <typename IndexedData, typename Offsets, typename Data>
|
||||||
void test_rw(const Offsets &offsets, const Data &data)
|
void test_rw(const Offsets &offsets, const Data &data)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
|
||||||
IndexedData indexed_data;
|
IndexedData indexed_data;
|
||||||
indexed_data.write(sstr, offsets.begin(), offsets.end(), data.begin());
|
auto path = boost::filesystem::unique_path();
|
||||||
|
|
||||||
const std::string str = sstr.str();
|
{
|
||||||
|
storage::io::FileWriter writer(path, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
indexed_data.write(writer, offsets.begin(), offsets.end(), data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
storage::io::FileReader reader(path, storage::io::FileReader::HasNoFingerprint);
|
||||||
|
auto length = reader.GetSize();
|
||||||
|
std::string str(length, '\0');
|
||||||
|
reader.ReadInto(const_cast<char *>(str.data()), length);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
std::cout << "\n" << typeid(IndexedData).name() << "\nsaved size = " << str.size() << "\n";
|
std::cout << "\n" << typeid(IndexedData).name() << "\nsaved size = " << str.size() << "\n";
|
||||||
@ -175,14 +184,21 @@ BOOST_AUTO_TEST_CASE(check_corrupted_memory)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(check_string_view)
|
BOOST_AUTO_TEST_CASE(check_string_view)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
auto path = boost::filesystem::unique_path();
|
||||||
std::string name_data = "hellostringview";
|
std::string name_data = "hellostringview";
|
||||||
std::vector<std::uint32_t> name_offsets = {0, 5, 11, 15};
|
std::vector<std::uint32_t> name_offsets = {0, 5, 11, 15};
|
||||||
|
|
||||||
IndexedData<VariableGroupBlock<16, StringView>> indexed_data;
|
IndexedData<VariableGroupBlock<16, StringView>> indexed_data;
|
||||||
indexed_data.write(sstr, name_offsets.begin(), name_offsets.end(), name_data.begin());
|
{
|
||||||
|
storage::io::FileWriter writer(path, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
indexed_data.write(writer, name_offsets.begin(), name_offsets.end(), name_data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
storage::io::FileReader reader(path, storage::io::FileReader::HasNoFingerprint);
|
||||||
|
auto length = reader.GetSize();
|
||||||
|
std::string str(length, '\0');
|
||||||
|
reader.ReadInto(const_cast<char *>(str.data()), length);
|
||||||
|
|
||||||
const std::string str = sstr.str();
|
|
||||||
indexed_data.reset(str.c_str(), str.c_str() + str.size());
|
indexed_data.reset(str.c_str(), str.c_str() + str.size());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(indexed_data.at(0), "hello");
|
BOOST_CHECK_EQUAL(indexed_data.at(0), "hello");
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "util/name_table.hpp"
|
#include "util/name_table.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/test/test_case_template.hpp>
|
#include <boost/test/test_case_template.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@ -19,7 +20,6 @@ using namespace osrm::util;
|
|||||||
|
|
||||||
std::string PrapareNameTableData(std::vector<std::string> &data, bool fill_all)
|
std::string PrapareNameTableData(std::vector<std::string> &data, bool fill_all)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
|
||||||
NameTable::IndexedData indexed_data;
|
NameTable::IndexedData indexed_data;
|
||||||
std::vector<unsigned char> name_char_data;
|
std::vector<unsigned char> name_char_data;
|
||||||
std::vector<std::uint32_t> name_offsets;
|
std::vector<std::uint32_t> name_offsets;
|
||||||
@ -54,9 +54,19 @@ std::string PrapareNameTableData(std::vector<std::string> &data, bool fill_all)
|
|||||||
}
|
}
|
||||||
name_offsets.push_back(name_char_data.size());
|
name_offsets.push_back(name_char_data.size());
|
||||||
|
|
||||||
indexed_data.write(sstr, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
auto path = boost::filesystem::unique_path();
|
||||||
|
{
|
||||||
|
storage::io::FileWriter writer(path, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
indexed_data.write(
|
||||||
|
writer, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
return sstr.str();
|
storage::io::FileReader reader(path, storage::io::FileReader::HasNoFingerprint);
|
||||||
|
auto length = reader.GetSize();
|
||||||
|
std::string str(length, '\0');
|
||||||
|
reader.ReadInto(const_cast<char *>(str.data()), length);
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(check_name_table_fill)
|
BOOST_AUTO_TEST_CASE(check_name_table_fill)
|
||||||
|
Loading…
Reference in New Issue
Block a user