Compare commits

...

63 Commits

Author SHA1 Message Date
Patrick Niklaus
c7293f2024 Bump version to 5.7.2 2017-05-24 16:49:03 +00:00
Patrick Niklaus
ddc8aed25d Fix formating 2017-05-24 16:47:14 +00:00
Michael Krasnyk
5f7410057c Fix OSRM_ASSERT_MSG compilation fail in Release mode 2017-05-24 16:36:21 +00:00
Patrick Niklaus
d55d46e64e Add missing header after cherry-pick 2017-05-24 16:14:06 +00:00
Michael Krasnyk
a83150d311 Place reverse entering_via_edge in the front of intersection_view 2017-05-24 15:52:00 +00:00
Michael Krasnyk
b073bf36f3 Added example for roundabout overlapping 2017-05-24 15:47:58 +00:00
Daniel J. Hofmann
aaea94f776 Asserts Valid Iterators in Roundabout Exit Invalidation, see #4024 2017-05-24 15:44:28 +00:00
Patrick Niklaus
055079192c Bump version to 5.7.1 2017-05-23 17:20:02 +00:00
Patrick Niklaus
c542fc2087 Fix formating after cherry-pick 2017-05-23 16:25:26 +00:00
Patrick Niklaus
64b9b6e888 Accidentally included a un-releated test case from master 2017-05-23 16:24:58 +00:00
Michael Krasnyk
c58052ca04 Adjust CHANGELOG and the test description 2017-05-23 16:02:00 +00:00
Michael Krasnyk
df4d1cb9e6 Change order of guidance post-processing, fix #4030 2017-05-23 16:00:38 +00:00
Daniel J. Hofmann
3349964b96 Updates Changelog 2017-05-19 12:27:32 +02:00
Daniel J. Hofmann
443ebc2551 Applies max turn weight for turns onto restricted weights: no need for custom penalty 2017-05-19 12:22:31 +02:00
Daniel J. Hofmann
e6b1e3564a Prevents possible overflow in applying a turn penalty onto restricted roads 2017-05-19 12:22:31 +02:00
Moritz Kobitzsch
3aeb39ba95 fix continue_straight interaction with bearing specification 2017-05-19 12:22:31 +02:00
Daniel J. Hofmann
51fbb4fcbd Fixes Table not checking for valid phantom nodes
We failed to check if we could actually find phantom nodes for all
coordinates in the table plugin, leading to corrupt internal state.

```
curl 'http://localhost:5000/table/v1/car/7.4151,43.7305;7.4222,43.7368?radiuses=0;'
```

```
[assert][140505627227904] /tmp/osrm-backend/include/engine/routing_algorithms/routing_base.hpp:68
in: void osrm::engine::routing_algorithms::insertNodesInHeap(osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>::ManyToManyQueryHeap&, const osrm::engine::PhantomNode&) [with bool DIRECTION = false; osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>::ManyToManyQueryHeap = osrm::util::BinaryHeap<unsigned int, unsigned int, int, osrm::engine::ManyToManyHeapData, osrm::util::UnorderedMapStorage<unsigned int, int> >]: phantom_node.IsValid()
terminate called without an active exception
```
2017-05-19 12:22:31 +02:00
Michael Krasnyk
f618531cbb Add response code to test result values 2017-05-19 12:22:31 +02:00
Patrick Niklaus
3f737fce46 Update changelog 2017-05-16 16:21:36 +00:00
Patrick Niklaus
11df411da7 Fix weight value for alley 2017-05-16 16:20:46 +00:00
Patrick Niklaus
5f208b913c Add regression test 2017-05-16 16:20:46 +00:00
Patrick Niklaus
3131bffe11 Fix bicycle turn penalties 2017-05-16 16:20:46 +00:00
Michael Krasnyk
4f3a7c1ec3 Adjust method and function names 2017-05-11 09:36:04 +00:00
Michael Krasnyk
321d1988a0 Disable nodes with invalid segments 2017-05-11 09:36:02 +00:00
Michael Krasnyk
b707fcdadc Add response codes of trip and routability queries 2017-05-11 09:16:01 +00:00
Patrick Niklaus
4285660c72 Update changelog 2017-05-05 22:14:50 +00:00
Michael Krasnyk
111e689b09 Added test with an empty CSV file 2017-05-05 22:13:57 +00:00
Michael Krasnyk
ebbb497af2 Hide qi namespace alias 2017-05-05 22:13:57 +00:00
Michael Krasnyk
dd9ad9fa08 Remove generate-edge-lookup argument in feature tests 2017-05-05 22:13:57 +00:00
Michael Krasnyk
dc55edbeb1 Add zero file size check 2017-05-05 22:13:57 +00:00
Michael Krasnyk
1c59563c9c Print diagnostic information to avoid boost cryptic errors 2017-05-05 22:13:57 +00:00
Michael Krasnyk
f4e1f6a752 Use mapped_file_source for CSV files 2017-05-05 22:13:57 +00:00
Patrick Niklaus
8c1e014d42 For the cyclability profile add alley penalties 2017-05-05 17:05:37 +00:00
Patrick Niklaus
b27fa42b0a Add failing test case for alleys 2017-05-05 17:05:28 +00:00
Patrick Niklaus
73e008e1b0 Regenerate docs 2017-05-05 08:50:22 +00:00
Patrick Niklaus
45fe4b80dd Fix docs for radius 2017-05-05 08:50:07 +00:00
Patrick Niklaus
65732db266 Fix overloaded parameter docs 2017-05-05 08:49:51 +00:00
Patrick Niklaus
55a7e1082f Disable TOC 2017-05-05 08:49:42 +00:00
Patrick Niklaus
34d5ba8fdd Update changelog 2017-05-04 21:08:28 +00:00
Michael Krasnyk
ec26756084 Updated assertions to catch negative duration values for weights > 0
but still clamping negative duration values at 0 without checking weights
2017-05-04 21:02:28 +00:00
Michael Krasnyk
0f55f24bfe Use rectified linear unit to prevent negative duration values 2017-05-04 21:02:17 +00:00
Patrick Niklaus
07f2c8fd4c Regenerate API docs 2017-05-03 15:22:28 +00:00
Patrick Niklaus
3289d53617 Update nodejs docs to document the constructor better 2017-05-03 15:22:11 +00:00
Michael Krasnyk
1ea5e44094 Adjusted to PR comments 2017-05-03 15:21:47 +00:00
Michael Krasnyk
ee208cd450 Fix incorrect exit turn invalidation 2017-05-03 15:21:36 +00:00
Patrick Niklaus
4370fd126d Final version bump 2017-04-21 08:49:00 +00:00
Patrick Niklaus
15a2fdd1f8 Update changelog 2017-04-20 13:58:29 +00:00
Patrick Niklaus
0eedcf69bc Fix checking columns if route is not specified 2017-04-20 13:52:23 +00:00
Patrick Niklaus
62abea30f5 Apply traffic light penalty also for non-turns 2017-04-20 13:52:11 +00:00
Michael Krasnyk
3364be1860 Fix incorrect weight fallback for distance-based weights 2017-04-20 13:51:59 +00:00
Patrick Niklaus
a5eeca9b51 Bump version to RC3 2017-04-18 17:09:49 +00:00
Michael Krasnyk
1a09ff6005 Don't remove the last original coordinate during tiding 2017-04-18 13:36:28 +00:00
Patrick Niklaus
2794a52902 Remove boost::make_unique to fix travis node builds 2017-04-13 21:18:08 +00:00
Patrick Niklaus
cb796e4cfc Use .gitignore default instead of .npmignore 2017-04-13 21:17:58 +00:00
Patrick Niklaus
522ec4fc2e Restructure travis build 2017-04-13 21:17:45 +00:00
Michael Krasnyk
15dc5899b0 Use total angle for turn instruction if entry step has large distance 2017-04-12 23:32:12 +00:00
Patrick Niklaus
7e932ffbc3 Bump package version 2017-04-12 22:58:58 +00:00
Patrick Niklaus
810596bb83 Install node version as well 2017-04-12 20:28:19 +00:00
Patrick Niklaus
acabf0075c Only use three jobs for node builds 2017-04-12 20:28:05 +00:00
Patrick Niklaus
1ed72db210 Use nvm instead of travis node_js key
This fixes issues on container builds that would always use
node 6 even when 4 was specified.
2017-04-12 20:27:53 +00:00
Patrick Niklaus
6bdf95dfb4 Change version to RC1 2017-04-12 14:58:51 +00:00
Patrick Niklaus
785ae89cd8 Update changelog 2017-04-12 14:58:25 +00:00
Patrick Niklaus
16680191de Enable 5.7 branch in travis 2017-04-12 14:28:37 +00:00
55 changed files with 1294 additions and 587 deletions

2
.gitignore vendored
View File

@ -7,6 +7,8 @@
#############################
osrm-deps
.ycm_extra_conf.py
# Compiled source #
###################
*.com

View File

@ -1,10 +0,0 @@
*
!README.md
!CHANGELOG.md
!CONTRIBUTING.MD
!LICENCE.TXT
!package.json
!example
!lib/*.js
!profiles/*
!profiles/lib/*

View File

@ -7,8 +7,9 @@ git:
sudo: required
dist: trusty
nodejs:
node_js:
- "4"
- "6"
notifications:
email: false
@ -16,6 +17,7 @@ notifications:
branches:
only:
- master
- "5.7"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@ -36,6 +38,8 @@ env:
- CCACHE_VERSION=3.3.1
- CMAKE_VERSION=3.7.2
- MASON="$(pwd)/scripts/mason.sh"
- ENABLE_NODE_BINDINGS=On
- NODE="4"
matrix:
fast_finish: true
@ -45,12 +49,14 @@ matrix:
# Debug Builds
- os: linux
compiler: "gcc-6-debug"
compiler: "gcc-6-debug-cov-asan"
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
after_success:
- bash <(curl -s https://codecov.io/bash)
- os: linux
compiler: "clang-4.0-debug"
@ -61,12 +67,12 @@ matrix:
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
compiler: "mason-linux-debug-santize"
compiler: "mason-linux-debug-asan"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON ENABLE_NODE_BINDINGS=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
# Release Builds
- os: linux
@ -75,7 +81,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
- os: linux
compiler: "gcc-6-release"
@ -104,6 +110,8 @@ matrix:
compiler: "mason-osx-release"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
after_success:
- ./scripts/travis/publish.sh
# Disabled because of CI slowness
#- os: linux
@ -140,8 +148,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
nodejs: "4"
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
- |
@ -164,8 +171,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
nodejs: "4"
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
- |
@ -188,8 +194,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
nodejs: "6"
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
- |
@ -212,8 +217,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
nodejs: "6"
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
- |
@ -230,6 +234,10 @@ matrix:
- ./scripts/travis/publish.sh
before_install:
- source $NVM_DIR/nvm.sh
- nvm install $NODE
- nvm use $NODE
- node --version
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
- |
if [[ -z $JOBS ]]; then
@ -331,14 +339,9 @@ script:
- ./unit_tests/server-tests
- ./unit_tests/partition-tests
- |
if [ -n "${ENABLE_NODE_BINDINGS}" ] && [ -z "${ENABLE_SANITIZER}" ]; then
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
npm run nodejs-tests
fi
- popd
- yarn test
after_success:
- |
if [ -n "${ENABLE_COVERAGE}" ]; then
bash <(curl -s https://codecov.io/bash)
fi

View File

@ -1,17 +1,50 @@
- Track preprocessing flag in the map matching plugin.
# 5.7.2
- Changes from 5.7.1:
- Bug fixes:
- Fixes segmentation fault caused by the fix for 3977
# 5.7.1
- Changes from 5.7.0:
- Bug fixes:
- Fixes 3995: Negative duration caused by rounding issues.
- Fixes 3977: Fixes exit number in roundabout if starting inside the roundabout
- Fixes 3981: The NodeJS documentation was outdated and incomplete.
- Fixes 4010: Performance regression while parsing CSV files. Now 5x faster.
- Fixes 3919: Turn penalties on the cyclabilty metric were disabled.
- Fixes 3992: Table plugin not checking for valid phantom nodes
- Fixes 4013: `continue_straight` interaction with bearing constraints
- Fixes 4063: Potential overflow in custom profiles for restricted ways
- Fixes 4030: Roundabout edge-case crashes post-processing
# 5.7.0
- Changes from 5.6
- Bug fixes:
- Fixed 505: Invalid distance value for distance as routing weight.
- Fixed 3958: Fix traffic light penalties for non-turns
- Fixed 3933: crash when collapsing instructions
- Algorithm:
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
- Allows for fast metric updates in below a minute on continental sized networks (osrm-customize)
- Plugins supported: `match` and `route`
- Quickstart: `osrm-extract data.osm.pbf`, `osrm-partition data.osrm`, `osrm-customize data.osrm`, `osrm-routed --algorithm=MLD data.osrm`
- NodeJs Bindings
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
- `OSRM` object has new option `algorihtm="CH","CoreCH","MLD"`
- Internals
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
- Files
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
- `osrm-extract` creates new file `.osrm.cnbg` and `.cnbg_to_ebg`
- `osrm-partition` creates new file `.osrm.partition` and `.osrm.cells`
- `osrm-customize` creates new file `.osrm.mldgr`
- Profiles
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
- Map Matching:
- new option `gaps=split|ignore` to enable/disbale track splitting
- new option `tidy=true|false` to simplify traces automatically
# 5.6.3
- Changes from 5.6.0

View File

@ -55,7 +55,7 @@ endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 7)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION_PATCH 2)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")

View File

@ -1,66 +1,59 @@
# OSRM
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance requires a `.osrm` network,
which is prepared by the OSRM Backend C++ library.
## OSRM
The `OSRM` method is the main constructor for creating an OSRM instance.
An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
node_modules/osrm/lib/binding/osrm-contract data.osrm
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation or further details.
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
Once you have a complete `network.osrm` file, you can calculate networks in javascript with this library using the
methods below. To create an OSRM instance with your network you need to construct an instance like this:
Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
```javascript
var osrm = new OSRM('network.osrm');
```
#### Methods
**Parameters**
| Service | Description |
| -------------------------- | --------------------------------------------------------- |
| [`osrm.route`](#route) | shortest path between given coordinates |
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
| [`osrm.table`](#table) | computes distance tables for given coordinates |
| [`osrm.match`](#match) | matches given coordinates to the road network |
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Options for creating an OSRM object or string to the `.osrm` file. (optional, default `{shared_memory:true}`)
- `options.algorithm` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
Make sure you prepared the dataset with the correct toolchain.
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
#### General Options
Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options, outlined below.
| Option | Values | Description | Format |
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
| bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
| radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
| hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
## route
### route
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
- `options.alternatives` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Search for alternative routes and return as well. _Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route leg. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. `null`/`true`/`false`
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes and return as well.
_Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
`null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM("berlin-latest.osrm");
osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, function(err, result) {
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
if(err) throw err;
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
@ -69,7 +62,7 @@ osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, funct
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
## nearest
### nearest
Snaps a coordinate to the street network and returns the nearest n matches.
@ -78,7 +71,12 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
- `options.number` **\[[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)]** Number of nearest segments that should be returned.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
@ -98,19 +96,26 @@ osrm.nearest(options, function(err, response) {
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied
input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied input coordinate.
## table
### table
Computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
tables.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
- `options.sources` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.sources` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to
use
location with given index as source. Default is to use all.
- `options.destinations` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
#coordinates`) to use location with given index as destination. Default is to use all.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@ -132,24 +137,25 @@ osrm.table(options, function(err, response) {
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from the i-th waypoint to the j-th waypoint.
Values are given in seconds.
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
## tile
### tile
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
be used to examine the routing graph. The tiles are generated directly from the data in-memory,
so are in sync with actual routing results, and let you examine which roads are actually routable,
so are in sync with actual routing results, and let you examine which roads are actually
routable,
and what weights they have applied.
**Parameters**
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
and are supported by vector tile viewers like [Mapbox GL JS]\(<https://www.mapbox.com/mapbox-gl-js/api/>.
and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@ -164,7 +170,7 @@ osrm.tile([0, 0, 0], function(err, response) {
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
## match
### match
Map matching matches given GPS points to the road network in the most plausible way.
Please note the request might result multiple sub-traces. Large jumps in the timestamps
@ -175,15 +181,16 @@ if they can not be matched successfully.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified`
according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>]** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** Standard deviation of GPS precision used for map matching.
If applicable use GPS accuracy (`double >= 0`, default `5m`).
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@ -203,41 +210,26 @@ osrm.match(options, function(err, response) {
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) objects representing all points of the trace in order.
If the trace point was ommited by map matching because it is an outlier, the entry will be null. Each
`Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
If the trace point was ommited by map matching because it is an outlier, the entry will be null.
Each `Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
the waypoint inside the matched route.
**`matchings`** is an array of [`Route`](#route) objects that
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
**`matchings`** is an array of [`Route`](#route) objects that assemble the trace. Each `Route` object has an additional `confidence` property,
which is the confidence of the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
## trip
### trip
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm). The returned path does not have to be the fastest path, as TSP is NP-hard it is only an approximation. Note that all input coordinates have to be connected for the trip service to work.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.roundtrip` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route is a roundtrip. (optional, default `true`)
- `options.source` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route starts at `any` coordinate. Can also be `first`. (optional, default `any`)
- `options.destination` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route ends at `any` coordinate. Can also be `last`. (optional, default `any`)
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Fixing Start and End Points**
It is possible to explicitly set the start or end coordinate of the trip. When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
(farthest-insertion algorithm) for 10 or _ more waypoints and uses brute force for less than 10
waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is
only an approximation.
Note that all input coordinates have to be connected for the trip service to work.
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
Right now, the following combinations are possible:
| roundtrip | source | destination | supported |
| :-- | :-- | :-- | :-- |
| :-------- | :----- | :---------- | :-------- |
| true | first | last | **yes** |
| true | first | any | **yes** |
| true | any | last | **yes** |
@ -247,25 +239,25 @@ Right now, the following combinations are possible:
| false | any | last | no |
| false | any | any | no |
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
}
osrm.trip(options, function(err, response) {
if (err) throw err;
console.log(response.waypoints); // array of Waypoint objects
console.log(response.trips); // array of Route objects
});
```
Non Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
@ -285,49 +277,56 @@ osrm.trip(options, function(err, response) {
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of the
sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
**`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties,
1) `trips_index`: index to trips of the sub-trip the point was matched to, and
2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
# Responses
## Responses
Responses
## Route
### Route
Represents a route through (potentially multiple) waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#route)
## RouteLeg
### RouteLeg
Represents a route between two waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#routeleg)
## RouteStep
### RouteStep
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a single way to the subsequent step.
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a
single way to the subsequent step.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
## StepManeuver
### StepManeuver
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmanuever)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
## Waypoint
### Waypoint
Object used to describe waypoint on a route.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)

View 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 |

View File

@ -34,3 +34,39 @@ Feature: Turn Penalties
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
Scenario: Bicycle - Turn penalties on cyclability
Given the profile file
"""
require 'bicycle'
properties.weight_name = 'cyclability'
"""
Given the node map
"""
a--b-----c
|
|
d
e--------f-----------g
/
/
/
h
"""
And the ways
| nodes | highway |
| abc | residential |
| bd | residential |
| efg | residential |
| fh | residential |
When I route I should get
| from | to | distance | weight | # |
| a | c | 900m +- 1 | 216 | Going straight has no penalties |
| a | d | 900m +- 1 | 220.2 | Turning right had penalties |
| e | g | 2100m +- 4| 503.9 | Going straght has no penalties |
| e | h | 2100m +- 4| 515.1 | Turn sharp right has even higher penalties|

View 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 |

View File

@ -48,7 +48,6 @@ Feature: Traffic - turn penalties
| mn | primary |
| mp | primary |
And the profile "car"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting not based on turn penalty file
When I route I should get

View File

@ -51,7 +51,6 @@ Feature: Car - weights
| cd | primary | yes |
| be | service | yes |
| ec | service | yes |
And the extract extra arguments "--generate-edge-lookup"
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
@ -62,3 +61,28 @@ Feature: Car - weights
| from | to | route | speed | weight |
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
| a | e | ab,be,be | 14 km/h | 112 |
Scenario: Distance weights
Given the profile file "car" extended with
"""
api_version = 1
properties.weight_name = 'distance'
"""
Given the node map
"""
a---b---c
|
d
"""
And the ways
| nodes |
| abc |
| bd |
When I route I should get
| waypoints | bearings | route | distance | weights | times |
| a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
| b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
| a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s |

View File

@ -1019,3 +1019,39 @@ Feature: Collapse
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
# http://www.openstreetmap.org/way/92415447 #3933
Scenario: Use total angle for turn instruction if entry step has large distance
# """
# kf-_ a
# | - b
# | c
# |d
# e
# |
# i
# """
And the node locations
| node | lat | lon | #id |
| a | -33.9644254 | 151.1378673 | 33226063 |
| b | -33.9644373 | 151.1377172 | 1072787030 |
| c | -33.9644791 | 151.1374452 | 4222903609 |
| d | -33.9645661 | 151.1372654 | 4222903610 |
| e | -33.9646986 | 151.1371539 | 4222903611 |
| f | -33.964386 | 151.1372133 | 1072786875 |
| i | -33.9661796 | 151.1368491 | 2781176918 |
| k | -33.9643781 | 151.1371422 | 1684173853 |
And the ways
| nodes | highway | name | oneway | #id |
| ab | trunk | President Avenue | yes | 92415447 |
| bcde | trunk | President Avenue | yes | 422534457 |
| bf | trunk | President Avenue | yes | 447779786 |
| fk | trunk | President Avenue | yes | 179293012 |
| fei | trunk | Princes Highway | yes | 130099670 |
When I route I should get
| waypoints | route | turns | locations |
| a,i | President Avenue,Princes Highway,Princes Highway | depart,turn left,arrive | a,b,i |

View File

@ -222,6 +222,43 @@ Feature: Basic Roundabout
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
Scenario: Mixed Entry and Exit - clockwise order
Given the node map
"""
c a
j b f
k e
l h d
g i
"""
And the ways
| nodes | junction | oneway |
| abc | | yes |
| def | | yes |
| ghi | | yes |
| jkl | | yes |
| behkb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-3,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
Scenario: Mixed Entry and Exit - segregated roads, different names
Given the node map
"""
@ -707,3 +744,79 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns |
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
Scenario: Drive through roundabout
Given the node map
"""
a
b e d f
c
g h
"""
And the ways
| nodes | junction | oneway |
| abcda | roundabout | yes |
| edf | | |
| gch | | yes |
When I route I should get
| waypoints | bearings | route | turns |
| e,f | 90 90 | edf,edf,edf | depart,roundabout-exit-1,arrive |
| e,h | 90 135 | edf,gch,gch | depart,roundabout-exit-2,arrive |
| g,f | 45 90 | gch,edf,edf | depart,roundabout-exit-2,arrive |
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |
@4030 @4075
Scenario: Service roundabout with service exits
# Counting of service exits must be adjusted in #4075
Given the node map
"""
e
f a d
g b1c
h
"""
And the ways
| nodes | highway | junction |
| abcda | service | roundabout |
| de | service | |
| af | service | |
| bg | tertiary | |
| bh | service | |
When I route I should get
| from | to | route | turns |
| 1 | e | abcda,de,de | depart,roundabout-exit-1,arrive |
| 1 | f | abcda,af,af | depart,roundabout-exit-1,arrive |
| 1 | g | abcda,bg,bg | depart,roundabout-exit-1,arrive |
| 1 | h | abcda,bh,bh | depart,roundabout-exit-1,arrive |
Scenario: CCW and CW roundabouts with overlaps
Given the node map
"""
a d g h
b c j i
f e k l
"""
And the ways
| nodes | highway | junction |
| abcda | tertiary | roundabout |
| ed | tertiary | |
| af | tertiary | |
| ghijg | tertiary | roundabout |
| kg | tertiary | |
| hl | tertiary | |
When I route I should get
| from | to | route | turns | distance |
| e | f | ed,af,af | depart,roundabout-exit-1,arrive | 80.1m |
| f | e | af,ed,ed | depart,roundabout-exit-1,arrive | 120.1m |
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |

View File

@ -20,7 +20,7 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
And the data has been saved to disk
Scenario: Logging weight with updates over factor of 2, long segment
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
When I run "osrm-extract --profile {profile_file} {osm_file}"
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
Then stderr should not contain "Speed values were used to update 2 segment(s)"
And stderr should contain "Segment: 1,2"
@ -44,6 +44,6 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
"""
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}"
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"

View File

@ -16,10 +16,13 @@ module.exports = function () {
var headers = new Set(table.raw()[0]);
got.code = 'unknown';
if (res.body.length) {
json = JSON.parse(res.body);
got.code = json.code;
}
if (headers.has('status')) {
got.status = json.status.toString();
}
@ -33,7 +36,7 @@ module.exports = function () {
got['#'] = row['#'];
}
var subMatchings = [],
var subMatchings = [''],
turns = '',
route = '',
duration = '',

View File

@ -126,6 +126,7 @@ module.exports = function () {
r.query = this.query;
r.json = JSON.parse(body);
r.code = r.json.code;
r.status = res.statusCode === 200 ? 'x' : null;
if (r.status) {
r.route = this.wayList(r.json.routes[0]);

View File

@ -29,8 +29,10 @@ module.exports = function () {
}
var json;
got.code = 'unknown';
if (res.body.length) {
json = JSON.parse(res.body);
got.code = json.code;
}
if (headers.has('status')) {

View File

@ -39,6 +39,8 @@ module.exports = function () {
let json = JSON.parse(body);
got.code = json.code;
let hasRoute = json.code === 'Ok';
if (hasRoute) {
@ -79,6 +81,7 @@ module.exports = function () {
if (headers.has('route')) {
got.route = (instructions || '').trim();
}
if (headers.has('summary')) {
got.summary = (summary || '').trim();
@ -173,7 +176,6 @@ module.exports = function () {
putValue('weight_name', weight_name);
putValue('weights', weights);
putValue('weight', weight);
}
for (var key in row) {
if (this.FuzzyMatch.match(got[key], row[key])) {

View File

@ -4,7 +4,6 @@ Feature: Basic Map Matching
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Given the extract extra arguments "--generate-edge-lookup"
Given the query options
| geometries | geojson |

View File

@ -36,3 +36,38 @@ Feature: Projection to nearest point on road
| from | to | route | distance |
| d | b | abc,abc | 0m |
| b | d | abc,abc | 0m |
Scenario: Projection results negative duration
Given the profile file "testbot" extended with
"""
api_version = 1
function segment_function (segment)
segment.weight = 5.5
segment.duration = 2.8
end
"""
Given the node locations
| node | lon | lat |
| e | -51.218994 | -30.023866 |
| f | -51.218918 | -30.023741 |
| 1 | -51.219109 | -30.023766 |
| 2 | -51.219109 | -30.023764 |
| 3 | -51.219109 | -30.023763 |
| 4 | -51.219109 | -30.023762 |
| 5 | -51.219109 | -30.023761 |
| 6 | -51.219109 | -30.023756 |
And the ways
| nodes |
| ef |
When I route I should get
| waypoints | route | distance | time | weight |
| 1,4 | ef,ef | 0.4m | 0.1s | 0.1 |
| 2,4 | ef,ef | 0.1m | 0s | 0 |
| 3,4 | ef,ef | 0.1m | 0s | 0 |
| 4,4 | ef,ef | 0m | 0s | 0 |
| 5,4 | ef,ef | 0.1m | 0s | 0.1 |
| 6,4 | ef,ef | 0.6m | 0.1s | 0.2 |

View File

@ -22,7 +22,6 @@ Feature: Traffic - speeds
| df | primary |
| fb | primary |
And the profile "testbot"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on speed file
@ -154,3 +153,11 @@ Feature: Traffic - speeds
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And stderr should contain "malformed"
And it should exit with an error
Scenario: Check with an empty speed file
Given the speed file
"""
"""
And the data has been extracted
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And it should exit successfully

View File

@ -31,7 +31,6 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
| dg | primary |
And the profile "testbot"
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
Given the turn penalty file

View File

@ -352,3 +352,64 @@ Feature: Via points
| waypoints | bearings | route | turns |
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
Scenario: Continue Straight in presence of Bearings
Given the node map
"""
h - a 1 b -- g
| |
| |- 2 c - f
| 3
e ------ d - i
|
j
"""
And the query options
| continue_straight | false |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cdea | no |
| ah | yes |
| bg | yes |
| cf | yes |
| di | yes |
| dj | yes |
When I route I should get
| waypoints | bearings | route |
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,cdea,cdea |
Scenario: Continue Straight in presence of Bearings
Given the node map
"""
h - a 1 b -- g
| |
| |- 2 c - f
| 3
e ------ d - i
|
j
"""
And the query options
| continue_straight | true |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cdea | no |
| ah | yes |
| bg | yes |
| cf | yes |
| di | yes |
| dj | yes |
When I route I should get
| waypoints | bearings | route |
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,ab,cdea,cdea,cdea |

View File

@ -4,7 +4,6 @@ Feature: Weight tests
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Given the extract extra arguments "--generate-edge-lookup"
Given the query options
| geometries | geojson |

View 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 |

View File

@ -80,6 +80,8 @@ inline Result keep_all(const MatchParameters &params)
inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
BOOST_ASSERT(!params.coordinates.empty());
Result result;
result.can_be_removed.resize(params.coordinates.size(), false);
@ -91,10 +93,8 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
Thresholds running{0., 0};
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
for (std::size_t current = 0, next = 1; next < params.coordinates.size() - 1; ++current, ++next)
{
const auto next = current + 1;
auto distance_delta = util::coordinate_calculation::haversineDistance(
params.coordinates[current], params.coordinates[next]);
running.distance_in_meters += distance_delta;
@ -130,7 +130,11 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
}
}
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
// Always use the last coordinate if more than two original coordinates
if (params.coordinates.size() > 1)
{
result.tidied_to_original.push_back(params.coordinates.size() - 1);
}
// We have to filter parallel arrays that may be empty or the exact same size.
// result.parameters contains an empty MatchParameters at this point: conditionally fill.

View File

@ -167,8 +167,8 @@ class RouteAPI : public BaseAPI
*/
guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::collapseTurnInstructions(std::move(steps));
leg.steps = guidance::postProcess(std::move(leg.steps));
leg.steps = guidance::postProcess(std::move(steps));
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
leg.steps = guidance::buildIntersections(std::move(leg.steps));
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),

View File

@ -416,6 +416,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
}
// check phantom node segments validity
auto areSegmentsValid = [](auto first, auto last) -> bool {
return std::find(first, last, INVALID_EDGE_WEIGHT) == last;
};
bool is_forward_valid_source =
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
bool is_forward_valid_target =
areSegmentsValid(forward_weight_vector.begin(),
forward_weight_vector.begin() + data.fwd_segment_position + 1);
bool is_reverse_valid_source =
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
bool is_reverse_valid_target = areSegmentsValid(
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
forward_weight,
reverse_weight,
@ -425,6 +439,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_duration,
forward_duration_offset,
reverse_duration_offset,
is_forward_valid_source,
is_forward_valid_target,
is_reverse_valid_source,
is_reverse_valid_target,
point_on_segment,
input_coordinate},
current_perpendicular_distance};

View File

@ -170,10 +170,13 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
weight = weight + target_weight;
if (route_data.empty())
{
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
weight -=
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
duration = std::max(0, duration);
}
std::string summary;

View File

@ -222,10 +222,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// u-------------v
// | |---------| source_weight
// | |---| target_weight
BOOST_ASSERT(target_weight >= source_weight);
const EdgeWeight weight = target_weight - source_weight;
const EdgeWeight duration = target_duration - source_duration;
BOOST_ASSERT(weight >= 0);
BOOST_ASSERT(duration >= 0);
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
const EdgeWeight duration = std::max(0, target_duration - source_duration);
steps.push_back(RouteStep{source_node.name_id,
facade.GetNameForID(source_node.name_id).to_string(),

View File

@ -46,37 +46,6 @@ namespace engine
struct PhantomNode
{
PhantomNode(SegmentID forward_segment_id,
SegmentID reverse_segment_id,
unsigned name_id,
EdgeWeight forward_weight,
EdgeWeight reverse_weight,
EdgeWeight forward_weight_offset,
EdgeWeight reverse_weight_offset,
EdgeWeight forward_duration,
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
unsigned packed_geometry_id_,
bool is_tiny_component,
unsigned component_id,
util::Coordinate location,
util::Coordinate input_location,
unsigned short fwd_segment_position,
extractor::TravelMode forward_travel_mode,
extractor::TravelMode backward_travel_mode)
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
forward_weight_offset(forward_weight_offset),
reverse_weight_offset(reverse_weight_offset), forward_duration(forward_duration),
reverse_duration(reverse_duration), forward_duration_offset(forward_duration_offset),
reverse_duration_offset(reverse_duration_offset), packed_geometry_id(packed_geometry_id_),
component{component_id, is_tiny_component}, location(std::move(location)),
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
{
}
PhantomNode()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false},
@ -86,7 +55,9 @@ struct PhantomNode
forward_duration_offset(0), reverse_duration_offset(0),
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE), is_valid_forward_source(false),
is_valid_forward_target(false), is_valid_reverse_source(false),
is_valid_reverse_target(false)
{
}
@ -134,6 +105,23 @@ struct PhantomNode
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
bool IsValidForwardSource() const
{
return forward_segment_id.enabled && is_valid_forward_source;
}
bool IsValidForwardTarget() const
{
return forward_segment_id.enabled && is_valid_forward_target;
}
bool IsValidReverseSource() const
{
return reverse_segment_id.enabled && is_valid_reverse_source;
}
bool IsValidReverseTarget() const
{
return reverse_segment_id.enabled && is_valid_reverse_target;
}
bool operator==(const PhantomNode &other) const { return location == other.location; }
template <class OtherT>
@ -146,6 +134,10 @@ struct PhantomNode
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
bool is_valid_forward_source,
bool is_valid_forward_target,
bool is_valid_reverse_source,
bool is_valid_reverse_target,
const util::Coordinate location,
const util::Coordinate input_location)
: forward_segment_id{other.forward_segment_id},
@ -159,7 +151,11 @@ struct PhantomNode
component{other.component.id, other.component.is_tiny}, location{location},
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
forward_travel_mode{other.forward_travel_mode},
backward_travel_mode{other.backward_travel_mode}
backward_travel_mode{other.backward_travel_mode},
is_valid_forward_source{is_valid_forward_source},
is_valid_forward_target{is_valid_forward_target},
is_valid_reverse_source{is_valid_reverse_source},
is_valid_reverse_target{is_valid_reverse_target}
{
}
@ -187,8 +183,14 @@ struct PhantomNode
unsigned short fwd_segment_position;
// note 4 bits would suffice for each,
// but the saved byte would be padding anyway
extractor::TravelMode forward_travel_mode;
extractor::TravelMode backward_travel_mode;
extractor::TravelMode forward_travel_mode : 4;
extractor::TravelMode backward_travel_mode : 4;
// is phantom node valid to be used as source or target
private:
bool is_valid_forward_source : 1;
bool is_valid_forward_target : 1;
bool is_valid_reverse_source : 1;
bool is_valid_reverse_target : 1;
};
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");

View File

@ -41,54 +41,44 @@ bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &targ
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
template <bool DIRECTION, typename Heap>
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
{
BOOST_ASSERT(phantom_node.IsValid());
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
if (phantom_node.forward_segment_id.enabled)
{
heap.Insert(phantom_node.forward_segment_id.id,
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_segment_id.id);
}
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()});
}
}
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
{
insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
const auto &source = nodes.source_phantom;
if (source.IsValidForwardSource())
{
forward_heap.Insert(source.forward_segment_id.id,
-source.GetForwardWeightPlusOffset(),
source.forward_segment_id.id);
}
if (source.IsValidReverseSource())
{
forward_heap.Insert(source.reverse_segment_id.id,
-source.GetReverseWeightPlusOffset(),
source.reverse_segment_id.id);
}
const auto &target = nodes.target_phantom;
if (target.IsValidForwardTarget())
{
reverse_heap.Insert(target.forward_segment_id.id,
target.GetForwardWeightPlusOffset(),
target.forward_segment_id.id);
}
if (target.IsValidReverseTarget())
{
reverse_heap.Insert(target.reverse_segment_id.id,
target.GetReverseWeightPlusOffset(),
target.reverse_segment_id.id);
}
}
template <typename FacadeT>

View File

@ -190,6 +190,11 @@ search(SearchEngineData<Algorithm> &engine_working_data,
EdgeWeight weight_upper_bound,
Args... args)
{
if (forward_heap.Empty() || reverse_heap.Empty())
{
return std::make_tuple(
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
}
const auto &partition = facade.GetMultiLevelPartition();
@ -389,7 +394,7 @@ getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
EdgeWeight weight;
EdgeWeight weight = INVALID_EDGE_WEIGHT;
NodeID source_node, target_node;
std::vector<EdgeID> unpacked_edges;
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
@ -402,7 +407,9 @@ getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
phantom_nodes);
if (weight == INVALID_EDGE_WEIGHT)
{
return std::numeric_limits<double>::max();
}
std::vector<PathData> unpacked_path;
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);

View File

@ -18,7 +18,6 @@
#include "osrm/trip_parameters.hpp"
#include <boost/assert.hpp>
#include <boost/make_unique.hpp>
#include <boost/optional.hpp>
#include <algorithm>
@ -81,7 +80,7 @@ inline void ParseResult(const osrm::Status &result_status, const std::string & /
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
Nan::HandleScope scope;
auto engine_config = boost::make_unique<osrm::EngineConfig>();
auto engine_config = std::make_unique<osrm::EngineConfig>();
if (args.Length() == 0)
{
@ -631,7 +630,7 @@ inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
route_parameters_ptr params = boost::make_unique<osrm::RouteParameters>();
route_parameters_ptr params = std::make_unique<osrm::RouteParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return route_parameters_ptr();
@ -681,7 +680,7 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
inline tile_parameters_ptr
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
{
tile_parameters_ptr params = boost::make_unique<osrm::TileParameters>();
tile_parameters_ptr params = std::make_unique<osrm::TileParameters>();
if (args.Length() < 2)
{
@ -742,7 +741,7 @@ inline nearest_parameters_ptr
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
nearest_parameters_ptr params = boost::make_unique<osrm::NearestParameters>();
nearest_parameters_ptr params = std::make_unique<osrm::NearestParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return nearest_parameters_ptr();
@ -781,7 +780,7 @@ inline table_parameters_ptr
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
table_parameters_ptr params = boost::make_unique<osrm::TableParameters>();
table_parameters_ptr params = std::make_unique<osrm::TableParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return table_parameters_ptr();
@ -875,7 +874,7 @@ inline trip_parameters_ptr
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
trip_parameters_ptr params = boost::make_unique<osrm::TripParameters>();
trip_parameters_ptr params = std::make_unique<osrm::TripParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return trip_parameters_ptr();
@ -970,7 +969,7 @@ inline match_parameters_ptr
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
match_parameters_ptr params = boost::make_unique<osrm::MatchParameters>();
match_parameters_ptr params = std::make_unique<osrm::MatchParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return match_parameters_ptr();

View File

@ -10,13 +10,12 @@
#include <tbb/parallel_for.h>
#include <tbb/spin_mutex.h>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <fstream>
#include <vector>
namespace osrm
@ -24,20 +23,15 @@ namespace osrm
namespace updater
{
namespace
{
namespace qi = boost::spirit::qi;
}
// Functor to parse a list of CSV files using "key,value,comment" grammar.
// Key and Value structures must be a model of Random Access Sequence.
// Also the Value structure must have source member that will be filled
// with the corresponding file index in the CSV filenames vector.
template <typename Key, typename Value> struct CSVFilesParser
{
using Iterator = boost::spirit::line_pos_iterator<boost::spirit::istream_iterator>;
using KeyRule = qi::rule<Iterator, Key()>;
using ValueRule = qi::rule<Iterator, Value()>;
using Iterator = boost::iostreams::mapped_file_source::iterator;
using KeyRule = boost::spirit::qi::rule<Iterator, Key()>;
using ValueRule = boost::spirit::qi::rule<Iterator, Value()>;
CSVFilesParser(std::size_t start_index, const KeyRule &key_rule, const ValueRule &value_rule)
: start_index(start_index), key_rule(key_rule), value_rule(value_rule)
@ -95,24 +89,33 @@ template <typename Key, typename Value> struct CSVFilesParser
// Parse a single CSV file and return result as a vector<Key, Value>
auto ParseCSVFile(const std::string &filename, std::size_t file_id) const
{
std::ifstream input_stream(filename, std::ios::binary);
input_stream.unsetf(std::ios::skipws);
namespace qi = boost::spirit::qi;
boost::spirit::istream_iterator sfirst(input_stream), slast;
Iterator first(sfirst), last(slast);
std::vector<std::pair<Key, Value>> result;
try
{
if (boost::filesystem::file_size(filename) == 0)
return result;
boost::iostreams::mapped_file_source mmap(filename);
auto first = mmap.begin(), last = mmap.end();
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
ValueRule value_source =
value_rule[qi::_val = qi::_1, boost::phoenix::bind(&Value::source, qi::_val) = file_id];
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));
std::vector<std::pair<Key, Value>> result;
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
if (!ok || first != last)
{
const auto message =
boost::format("CSV file %1% malformed on line %2%") % filename % first.position();
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);
}
@ -120,6 +123,13 @@ template <typename Key, typename Value> struct CSVFilesParser
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);
}
}
const std::size_t start_index;
const KeyRule key_rule;

View File

@ -34,9 +34,9 @@
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
do \
{ \
(void)cond; \
(void)coordinate; \
(void)msg; \
(void)(cond); \
(void)(coordinate); \
(void)(msg); \
} while (0)
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")

View File

@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.7.0-latest.6",
"version": "5.7.2",
"private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": {

View File

@ -101,6 +101,10 @@ local profile = {
'tertiary_link'
},
service_penalties = {
alley = 0.5,
},
bicycle_speeds = {
cycleway = default_speed,
primary = default_speed,
@ -480,30 +484,30 @@ function way_function (way, result)
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
-- convert duration into cyclability
if properties.weight_name == 'cyclability' then
local is_unsafe = profile.safety_penalty < 1 and profile.unsafe_highway_list[data.highway]
local is_undesireable = data.highway == "service" and profile.service_penalties[service]
local penalty = 1.0
if is_unsafe then
penalty = math.min(penalty, profile.safety_penalty)
end
if is_undesireable then
penalty = math.min(penalty, profile.service_penalties[service])
end
if result.forward_speed > 0 then
-- convert from km/h to m/s
result.forward_rate = result.forward_speed / 3.6;
if is_unsafe then
result.forward_rate = result.forward_rate * profile.safety_penalty
end
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;
if is_unsafe then
result.backward_rate = result.backward_rate * profile.safety_penalty
end
result.backward_rate = result.backward_speed / 3.6 * penalty
end
if result.duration > 0 then
result.weight = result.duration;
if is_unsafe then
result.weight = result.weight * (1+profile.safety_penalty)
result.weight = result.duration / penalty
end
end
local handlers = Sequence {
-- compute speed taking into account way type, maxspeed tags, etc.
'handle_surface',
@ -540,6 +544,7 @@ function turn_function(turn)
turn.duration = turn.duration + profile.traffic_light_penalty
end
if properties.weight_name == 'cyclability' then
turn.weight = turn.duration
-- penalize turns from non-local access only segments onto local access only tags
if not turn.source_restricted and turn.target_restricted then
turn.weight = turn.weight + 3000

View File

@ -34,9 +34,6 @@ local profile = {
speed_reduction = 0.8,
traffic_light_penalty = 2,
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.
-- Should be inverted for left-driving countries.
@ -392,21 +389,21 @@ function turn_function (turn)
local turn_penalty = profile.turn_penalty
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.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
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
if turn.direction_modifier == direction_modifier.u_turn then
turn.duration = turn.duration + profile.u_turn_penalty
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
if properties.weight_name == 'distance' then
turn.weight = 0
@ -417,7 +414,7 @@ function turn_function (turn)
if properties.weight_name == 'routability' then
-- penalize turns from non-local access only segments onto local access only tags
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

View File

@ -441,7 +441,7 @@ end
function Handlers.handle_weights(way,result,data,profile)
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
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
result.forward_rate = 1

View File

@ -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; }
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
rm -rf build/docs

View File

@ -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

View File

@ -74,9 +74,6 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
if (entry_step.distance < MAX_COLLAPSE_DISTANCE)
return true;
if (entry_step.distance > 2 * MAX_COLLAPSE_DISTANCE)
return false;
// both go roughly in the same direction
if ((entry_angle <= 185 && exit_angle <= 185) || (entry_angle >= 175 && exit_angle >= 175))
return true;

View File

@ -67,7 +67,17 @@ Status TablePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryData
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 =
algorithms.ManyToManySearch(snapped_phantoms, params.sources, params.destinations);

View File

@ -77,27 +77,10 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca
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;
auto build_phantom_pairs = [&start_end_nodes, continue_straight_at_waypoint](
const PhantomNode &first_node, const PhantomNode &second_node) {
auto build_phantom_pairs = [&start_end_nodes](const PhantomNode &first_node,
const PhantomNode &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);

View File

@ -129,7 +129,7 @@ InternalRouteResult directShortestPathSearch(
// TODO: when structured bindings will be allowed change to
// auto [weight, source_node, target_node, unpacked_edges] = ...
EdgeWeight weight;
EdgeWeight weight = INVALID_EDGE_WEIGHT;
NodeID source_node, target_node;
std::vector<EdgeID> unpacked_edges;
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,

View File

@ -176,7 +176,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const auto search_target_phantom = [&](const PhantomNode &phantom) {
// clear heap and insert target nodes
query_heap.Clear();
insertNodesInHeap<REVERSE_DIRECTION>(query_heap, phantom);
insertTargetInHeap(query_heap, phantom);
// explore search space
while (!query_heap.Empty())
@ -191,7 +191,7 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const auto search_source_phantom = [&](const PhantomNode &phantom) {
// clear heap and insert source nodes
query_heap.Clear();
insertNodesInHeap<FORWARD_DIRECTION>(query_heap, phantom);
insertSourceInHeap(query_heap, phantom);
// explore search space
while (!query_heap.Empty())

View File

@ -9,7 +9,7 @@ namespace routing_algorithms
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.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)
{
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.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 engine
} // namespace osrm

View File

@ -82,6 +82,12 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
const PhantomNodes & /*phantom_nodes*/,
const EdgeWeight weight_upper_bound)
{
if (forward_heap.Empty() || reverse_heap.Empty())
{
weight = INVALID_EDGE_WEIGHT;
return;
}
NodeID middle = SPECIAL_NODEID;
weight = weight_upper_bound;
@ -155,31 +161,7 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
forward_heap.Clear();
reverse_heap.Clear();
if (source_phantom.forward_segment_id.enabled)
{
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);
}
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
EdgeWeight weight = INVALID_EDGE_WEIGHT;
std::vector<NodeID> packed_path;

View File

@ -63,9 +63,6 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
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
auto is_oneway_source = !(search_from_forward_node && search_from_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_reverse = 0;
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 =
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_reverse;
@ -262,13 +259,11 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
const auto &source_phantom = phantom_node_pair.source_phantom;
const auto &target_phantom = phantom_node_pair.target_phantom;
bool search_to_forward_node = target_phantom.forward_segment_id.enabled;
bool search_to_reverse_node = target_phantom.reverse_segment_id.enabled;
bool search_to_forward_node = target_phantom.IsValidForwardTarget();
bool search_to_reverse_node = target_phantom.IsValidReverseTarget();
BOOST_ASSERT(!search_from_forward_node || source_phantom.forward_segment_id.enabled);
BOOST_ASSERT(!search_from_reverse_node || source_phantom.reverse_segment_id.enabled);
BOOST_ASSERT(search_from_forward_node || search_from_reverse_node);
BOOST_ASSERT(!search_from_forward_node || source_phantom.IsValidForwardSource());
BOOST_ASSERT(!search_from_reverse_node || source_phantom.IsValidReverseSource());
if (search_to_reverse_node || search_to_forward_node)
{
@ -290,9 +285,9 @@ shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
packed_leg_to_forward);
// if only the reverse node is valid (e.g. when using the match plugin) we
// 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;
packed_leg_to_reverse = std::move(packed_leg_to_forward);
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.
// 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;
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)
{
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());
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)
{
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());
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),

View File

@ -3,6 +3,7 @@
#include "extractor/geojson_debug_policies.hpp"
#include "util/geojson_debug_logger.hpp"
#include "util/assert.hpp"
#include "util/bearing.hpp"
#include "util/coordinate_calculation.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
const auto uturn_bearing = [&]() {
// uturn is a pair of {edge id, bearing}
const auto uturn = [&]() {
const auto merge_entry = std::find_if(
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
return entry.merged_eid == uturn_edge_itr->eid;
@ -291,7 +293,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
normalized_intersection.end(),
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
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
{
@ -301,7 +304,9 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
connect_to_previous_node);
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
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(
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 =
@ -369,8 +374,22 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
std::end(intersection_view),
std::mem_fn(&IntersectionViewData::CompareByAngle));
BOOST_ASSERT(intersection_view[0].angle >= 0. &&
intersection_view[0].angle < std::numeric_limits<double>::epsilon());
// Move entering_via_edge to intersection front and place all roads prior entering_via_edge
// 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;
}

View File

@ -1,6 +1,7 @@
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "util/assert.hpp"
#include "util/bearing.hpp"
#include "util/coordinate_calculation.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)
return;
bool past_roundabout_angle = false;
const bool lhs = profile_properties.left_hand_driving;
const int step = lhs ? -1 : 1;
for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size();
++cnt, idx += step)
// Find range in which exits that must be invalidated (shaded areas):
// exit..end exit..end begin..exit for ↺ roundabouts
// *************************************
// * <--. ^ <--. / <--. *
// * | / | /░ | *
// * |/ |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)
{
const auto &edge_data = node_based_graph.GetEdgeData(road->eid);
if (edge_data.roundabout || edge_data.circular)
{
auto &road = intersection[idx];
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
// only check actual outgoing edges
if (edge_data.reversed)
{
// remember whether we have seen the roundabout in-part
if (edge_data.roundabout || edge_data.circular)
past_roundabout_angle = true;
continue;
if (roundabout_entry_first)
{ // invalidate turns in range exit..end
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;
}
}
}
OSRM_ASSERT(invalidate_from <= invalidate_to, coordinates[from_nid]);
// Exiting roundabouts at an entry point is technically a data-modelling issue.
// This workaround handles cases in which an exit precedes and entry. The resulting
// u-turn against the roundabout direction is invalidated.
// The sorting of the angles represents a problem for left-sided driving, though.
if (!edge_data.roundabout && !edge_data.circular &&
node_based_graph.GetTarget(road.eid) != from_nid && past_roundabout_angle)
for (; invalidate_from != invalidate_to; ++invalidate_from)
{
road.entry_allowed = false;
const auto &edge_data = node_based_graph.GetEdgeData(invalidate_from->eid);
if (!edge_data.roundabout && !edge_data.circular &&
node_based_graph.GetTarget(invalidate_from->eid) != from_nid)
{
invalidate_from->entry_allowed = false;
}
}
}

View File

@ -50,43 +50,31 @@ NAN_MODULE_INIT(Engine::Init)
// clang-format off
/**
*
* 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.
* The documentation on `osrm-extract` and `osrm-contract` for more information.
* Once you have a complete `network.osrm` file, you can calculate routes in javascript with this library using the methods below.
* To create an OSRM instance with your network you need to construct an instance like this:
* You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
* profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
*
* node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
* node_modules/osrm/lib/binding/osrm-contract data.osrm
*
* Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
*
* Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
*
* ```javascript
* var osrm = new OSRM('network.osrm');
* ```
*
* #### Methods
*
* | Service | Description |
* |-----------------------------|-----------------------------------------------------------|
* | [`osrm.route`](#route) | shortest path between given coordinates |
* | [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
* | [`osrm.table`](#table) | computes distance tables for given coordinates |
* | [`osrm.match`](#match) | matches given coordinates to the road network |
* | [`osrm.trip`](#trip) | 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` |
* @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'.
* Make sure you prepared the dataset with the correct toolchain.
* @param {Boolean} [options.shared_memory] Connects to the persistent shared memory datastore.
* This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
* @param {String} [options.path] The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
*
* @class OSRM
*
*
*/
// clang-format on
NAN_METHOD(Engine::New)
@ -192,11 +180,15 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
* @name route
* @memberof OSRM
* @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.
* *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} or {Array} [options.annotations=false] Return annotations for each route leg.
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
* @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 {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
* @memberof OSRM
* @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.
* Must be an integer greater than or equal to `1`.
* @param {Function} callback
@ -261,6 +258,11 @@ NAN_METHOD(Engine::nearest) //
* @name table
* @memberof OSRM
* @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
* use
* location with given index as source. Default is to use all.
@ -337,13 +339,16 @@ NAN_METHOD(Engine::tile)
* @name match
* @memberof OSRM
* @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} or {Array} [options.annotations=false] Return annotations for each route leg.
* Can be `false`, `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
* @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 {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
*
* @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
* waypoints. The returned path does not have to be the shortest path, * as TSP is NP-hard it is
* only an approximation.
*
* Note that all input coordinates have to be connected for the trip service to work.
* Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
* Right now, the following combinations are possible:
*
* | roundtrip | source | destination | supported |
* | :-- | :-- | :-- | :-- |
* | true | first | last | **yes** |
* | true | first | any | **yes** |
* | true | any | last | **yes** |
* | true | any | any | **yes** |
* | false | first | last | **yes** |
* | false | first | any | no |
* | false | any | last | no |
* | false | any | any | no |
*
* @name trip
* @memberof OSRM
* @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} or {Array} [options.annotations=false] Return annotations for each route leg. Can be `false`,
* `true` or an array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`.
* @param {Array|Boolean} [options.annotations=false] An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all.
* @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 {Function} callback
@ -398,8 +421,8 @@ NAN_METHOD(Engine::match) //
* @returns {Object} containing `waypoints` and `trips`.
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
* Each Waypoint object has the following additional properties,
* 1) `trips_index`: index to trips of the sub-trip the point was matched to,
* and 2) `waypoint_index`: index of the point in the trip.
* 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.
*
* @example
@ -408,7 +431,10 @@ NAN_METHOD(Engine::match) //
* coordinates: [
* [13.36761474609375, 52.51663871100423],
* [13.374481201171875, 52.506191342034576]
* ]
* ],
* source: "first",
* destination: "last",
* roundtrip: false
* }
* osrm.trip(options, function(err, response) {
* if (err) throw err;

View File

@ -53,10 +53,10 @@ BOOST_AUTO_TEST_CASE(two_item_trace_needs_tidiying_test)
auto result = tidy::tidy(params, thresholds);
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[1], true);
BOOST_CHECK_EQUAL(result.can_be_removed[1], false);
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);
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[1], 3);
BOOST_CHECK_EQUAL(result.tidied_to_original[2], 5);
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[3], false);
BOOST_CHECK_EQUAL(result.can_be_removed[5], false);
}
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);
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[1], 3);
BOOST_CHECK_EQUAL(result.tidied_to_original[2], 5);
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[3], false);
BOOST_CHECK_EQUAL(result.can_be_removed[5], false);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -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()