Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aed7df6173 | |||
| e3b09875c6 | |||
| 52ceea429b | |||
| 3d4d51d6b7 | |||
| 23c69f4c3d | |||
| 9d044bf388 | |||
| 823d7e45e7 | |||
| 6b961dccfc | |||
| 44d4903985 | |||
| 55e05b70ac | |||
| 210908dbe6 | |||
| 6b9006f6e7 | |||
| ca55521c87 | |||
| 67e99c9809 | |||
| 05647adcc6 | |||
| 6c37b71046 | |||
| cb2a46b8d9 | |||
| b1451a7421 | |||
| da1c251144 | |||
| 1eab7b41d1 | |||
| 1dca8ae76a | |||
| 002e86863d | |||
| 1d82b01816 | |||
| 714719c377 | |||
| 77b4fbb69c | |||
| 11fde865f7 | |||
| 717406043a | |||
| 1ef85c57cc | |||
| d0180517a8 | |||
| 520b7ebbb6 | |||
| 2caba96076 | |||
| 81bc2f41a6 | |||
| 06e010b4d0 | |||
| 92d3ce789b | |||
| 01ca32c81c | |||
| 2e17f3010a | |||
| c4238c4ed6 | |||
| 3d781e6f28 | |||
| 4976233cff | |||
| 98ea2a0b09 | |||
| f978900ab0 | |||
| 8b6580128b | |||
| 4dde9c7bbe | |||
| 973837207b | |||
| 364e35af06 | |||
| 985ab58f45 |
@@ -68,6 +68,10 @@ Thumbs.db
|
||||
/*.local.bat
|
||||
/CMakeSettings.json
|
||||
|
||||
# Jetbrains related files #
|
||||
###########################
|
||||
.idea/
|
||||
|
||||
# stxxl related files #
|
||||
#######################
|
||||
.stxxl
|
||||
|
||||
+59
-64
@@ -13,11 +13,12 @@ notifications:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 5.21
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
npm: true
|
||||
ccache: true
|
||||
apt: true
|
||||
directories:
|
||||
@@ -34,7 +35,7 @@ env:
|
||||
- CMAKE_VERSION=3.7.2
|
||||
- MASON="$(pwd)/scripts/mason.sh"
|
||||
- ENABLE_NODE_BINDINGS=On
|
||||
- NODE="4"
|
||||
- NODE="10"
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
@@ -45,7 +46,7 @@ matrix:
|
||||
# Debug Builds
|
||||
- os: linux
|
||||
compiler: "format-taginfo-docs"
|
||||
env: NODE=6
|
||||
env: NODE=10
|
||||
sudo: false
|
||||
before_install:
|
||||
install:
|
||||
@@ -53,8 +54,7 @@ matrix:
|
||||
- nvm install $NODE
|
||||
- nvm use $NODE
|
||||
- npm --version
|
||||
- npm install --ignore-scripts
|
||||
- npm link --ignore-scripts
|
||||
- npm ci --ignore-scripts
|
||||
script:
|
||||
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
- ${MASON} install clang-format 3.8.1
|
||||
@@ -156,17 +156,17 @@ matrix:
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
compiler: "mason-osx-release-node-8"
|
||||
compiler: "mason-osx-release-node-10"
|
||||
# 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 NODE="8"
|
||||
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="10"
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
compiler: "mason-osx-release-node-4"
|
||||
compiler: "mason-osx-release-node-8"
|
||||
# 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 NODE="4"
|
||||
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="8"
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
@@ -180,54 +180,6 @@ matrix:
|
||||
env: CCOMPILER='gcc-7' CXXCOMPILER='g++-7' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
|
||||
# Node build jobs. These skip running the tests.
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-4-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-4.9-dev']
|
||||
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="4"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||
-DENABLE_GLIBC_WORKAROUND=ON
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-4-mason-linux-debug"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-4.9-dev']
|
||||
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="4"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||
-DENABLE_GLIBC_WORKAROUND=ON
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-8-mason-linux-release"
|
||||
@@ -276,6 +228,54 @@ matrix:
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-10-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-4.9-dev']
|
||||
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||
-DENABLE_GLIBC_WORKAROUND=ON
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-10-mason-linux-debug"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-4.9-dev']
|
||||
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
|
||||
-DENABLE_GLIBC_WORKAROUND=ON
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
before_install:
|
||||
- source $NVM_DIR/nvm.sh
|
||||
- nvm install $NODE
|
||||
@@ -294,15 +294,10 @@ before_install:
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
sudo mdutil -i off /
|
||||
fi
|
||||
- |
|
||||
if [[ ! -f $(which yarn) ]]; then
|
||||
npm install -g yarn@1.11.1
|
||||
fi
|
||||
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
||||
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
|
||||
- echo "Using ${JOBS} jobs"
|
||||
- yarn install --ignore-scripts
|
||||
- yarn check --ignore-scripts --integrity
|
||||
- npm ci --ignore-scripts
|
||||
# Bootstrap cmake to be able to run mason
|
||||
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}.tar.gz"
|
||||
- CMAKE_DIR="mason_packages/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}"
|
||||
@@ -381,4 +376,4 @@ script:
|
||||
fi
|
||||
- |
|
||||
- popd
|
||||
- yarn test
|
||||
- npm test
|
||||
|
||||
+26
-1
@@ -1,12 +1,37 @@
|
||||
# UNRELEASED
|
||||
# 5.21.0
|
||||
- Changes from 5.20.0
|
||||
- Features:
|
||||
- ADDED: all waypoints in responses now contain a distance property between the original coordinate and the snapped location. [#5255](https://github.com/Project-OSRM/osrm-backend/pull/5255)
|
||||
- ADDED: if `fallback_speed` is used, a new structure `fallback_speed_cells` will describe which cells contain estimated values [#5259](https://github.com/Project-OSRM/osrm-backend/pull/5259)
|
||||
- REMOVED: we no longer publish Node 4 or 6 binary modules (they are still buildable from source) [#5314](https://github.com/Project-OSRM/osrm-backend/pull/5314)
|
||||
- Table:
|
||||
- ADDED: new parameter `scale_factor` which will scale the cell `duration` values by this factor. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5298)
|
||||
- FIXED: only trigger `scale_factor` code to scan matrix when necessary. [#5303](https://github.com/Project-OSRM/osrm-backend/pull/5303)
|
||||
- FIXED: fix bug in reverse offset calculation that sometimes lead to negative (and other incorrect) values in distance table results [#5315](https://github.com/Project-OSRM/osrm-backend/pull/5315)
|
||||
- Docker:
|
||||
- FIXED: use consistent boost version between build and runtime [#5311](https://github.com/Project-OSRM/osrm-backend/pull/5311)
|
||||
- FIXED: don't override default permissions on /opt [#5311](https://github.com/Project-OSRM/osrm-backend/pull/5311)
|
||||
- Matching:
|
||||
- CHANGED: matching will now consider edges marked with is_startpoint=false, allowing matching over ferries and other previously non-matchable edge types. [#5297](https://github.com/Project-OSRM/osrm-backend/pull/5297)
|
||||
- Profile:
|
||||
- ADDED: Parse `source:maxspeed` and `maxspeed:type` tags to apply maxspeeds and add belgian flanders rural speed limit. [#5217](https://github.com/Project-OSRM/osrm-backend/pull/5217)
|
||||
- CHANGED: Refactor maxspeed parsing to use common library. [#5144](https://github.com/Project-OSRM/osrm-backend/pull/5144)
|
||||
|
||||
# 5.20.0
|
||||
- Changes from 5.19.0:
|
||||
- Table:
|
||||
- CHANGED: switch to pre-calculated distances for table responses for large speedup and 10% memory increase. [#5251](https://github.com/Project-OSRM/osrm-backend/pull/5251)
|
||||
- ADDED: new parameter `fallback_speed` which will fill `null` cells with estimated value [#5257](https://github.com/Project-OSRM/osrm-backend/pull/5257)
|
||||
- CHANGED: Remove API check for matrix sources/destination length to be less than or equal to coordinates length. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5289)
|
||||
- FIXED: Fix crashing bug when using fallback_speed parameter with more sources than destinations. [#5291](https://github.com/Project-OSRM/osrm-backend/pull/5291)
|
||||
- Features:
|
||||
- ADDED: direct mmapping of datafiles is now supported via the `--mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
|
||||
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
|
||||
- ADDED: Now publishing Node 10.x LTS binary modules [#5246](https://github.com/Project-OSRM/osrm-backend/pull/5246)
|
||||
- Windows:
|
||||
- FIXED: Windows builds again. [#5249](https://github.com/Project-OSRM/osrm-backend/pull/5249)
|
||||
- Docker:
|
||||
- CHANGED: switch from Alpine Linux to Debian Buster base images [#5281](https://github.com/Project-OSRM/osrm-backend/pull/5281)
|
||||
|
||||
# 5.19.0
|
||||
- Changes from 5.18.0:
|
||||
|
||||
@@ -50,7 +50,7 @@ If you want to use the CH pipeline instead replace `osrm-partition` and `osrm-cu
|
||||
|
||||
### Using Docker
|
||||
|
||||
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Debian and make sure they are as lightweight as possible.
|
||||
|
||||
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
|
||||
|
||||
|
||||
+12
-13
@@ -1,15 +1,13 @@
|
||||
FROM alpine:3.6 as buildstage
|
||||
|
||||
FROM debian:buster-slim as builder
|
||||
ARG DOCKER_TAG
|
||||
RUN mkdir -p /src && mkdir -p /opt
|
||||
COPY . /src
|
||||
WORKDIR /src
|
||||
|
||||
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
||||
apk update && \
|
||||
apk upgrade && \
|
||||
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.2-dev libtbb@testing libtbb-dev@testing && \
|
||||
apt-get update && \
|
||||
apt-get -y --no-install-recommends install cmake make git gcc g++ libbz2-dev libstxxl-dev libstxxl1v5 libxml2-dev \
|
||||
libzip-dev libboost1.67-all-dev lua5.2 liblua5.2-dev libtbb-dev -o APT::Install-Suggests=0 -o APT::Install-Recommends=0 && \
|
||||
NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
echo "Building OSRM ${DOCKER_TAG}" && \
|
||||
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
|
||||
@@ -26,20 +24,21 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
make -j${NPROC} install && \
|
||||
cd ../profiles && \
|
||||
cp -r * /opt && \
|
||||
\
|
||||
strip /usr/local/bin/* && \
|
||||
rm -rf /src /usr/local/lib/libosrm*
|
||||
|
||||
|
||||
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
|
||||
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
|
||||
FROM alpine:3.6 as runstage
|
||||
FROM debian:buster-slim as runstage
|
||||
RUN mkdir -p /src && mkdir -p /opt
|
||||
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
||||
apk update && \
|
||||
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat libtbb@testing
|
||||
COPY --from=buildstage /usr/local /usr/local
|
||||
COPY --from=buildstage /opt /opt
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends libboost-program-options1.67.0 libboost-regex1.67.0 \
|
||||
libboost-date-time1.67.0 libboost-chrono1.67.0 libboost-filesystem1.67.0 \
|
||||
libboost-iostreams1.67.0 libboost-thread1.67.0 expat liblua5.2-0 libtbb2 &&\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=builder /usr/local /usr/local
|
||||
COPY --from=builder /opt /opt
|
||||
WORKDIR /opt
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
+11
-3
@@ -119,7 +119,6 @@ In addition to the [general options](#general-options) the following options are
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
|
||||
- `distance`: Distance in meters to the supplied input coordinate.
|
||||
- `nodes`: Array of OpenStreetMap node ids.
|
||||
|
||||
#### Example Requests
|
||||
@@ -236,8 +235,10 @@ In addition to the [general options](#general-options) the following options are
|
||||
|------------|--------------------------------------------------|---------------------------------------------|
|
||||
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|
||||
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|
||||
|annotations |`duration` (default), `distance`, or `duration,distance`|Return the requested table or tables in response. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned.
|
||||
|
|
||||
|annotations |`duration` (default), `distance`, or `duration,distance`|Return the requested table or tables in response. |
|
||||
|fallback_speed|`double > 0`| If no route found between a source/destination pair, calculate the as-the-crow-flies distance, then use this speed to estimate duration.|
|
||||
|fallback_coordinate|`input` (default), or `snapped`| When using a `fallback_speed`, use the user-supplied coordinate (`input`), or the snapped location (`snapped`) for calculating distances.|
|
||||
|scale_factor|`double > 0`| Use in conjunction with `annotations=durations`. Scales the table `duration` values by this number.|
|
||||
|
||||
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
|
||||
to number of input locations;
|
||||
@@ -283,6 +284,7 @@ curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397
|
||||
the i-th waypoint to the j-th waypoint. Values are given in meters. Can be `null` if no route between `i` and `j` can be found. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned.
|
||||
- `sources` array of `Waypoint` objects describing all sources in order
|
||||
- `destinations` array of `Waypoint` objects describing all destinations in order
|
||||
- `fallback_speed_cells` (optional) array of arrays containing `i,j` pairs indicating which cells contain estimated values based on `fallback_speed`. Will be absent if `fallback_speed` is not used.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
@@ -383,6 +385,10 @@ All other properties might be undefined.
|
||||
2361.73,
|
||||
0
|
||||
]
|
||||
],
|
||||
"fallback_speed_cells": [
|
||||
[ 0, 1 ],
|
||||
[ 1, 0 ]
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -551,6 +557,7 @@ Vector tiles contain two layers:
|
||||
| `weight ` | `integer` | how long this segment takes to traverse, in units (may differ from `duration` when artificial biasing is applied in the Lua profiles). ACTUAL ROUTING USES THIS VALUE. |
|
||||
| `name` | `string` | the name of the road this segment belongs to |
|
||||
| `rate` | `float` | the value of `length/weight` - analagous to `speed`, but using the `weight` value rather than `duration`, rounded to the nearest integer |
|
||||
| `is_startpoint` | `boolean` | whether this segment can be used as a start/endpoint for routes |
|
||||
|
||||
`turns` layer:
|
||||
|
||||
@@ -905,6 +912,7 @@ Object used to describe waypoint on a route.
|
||||
|
||||
- `name` Name of the street the coordinate snapped to
|
||||
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
|
||||
- `distance` The distance, in metres, from the input coordinate to the snapped coordinate
|
||||
- `hint` Unique internal identifier of the segment (ephemeral, not constant over data updates)
|
||||
This can be used on subsequent request to significantly speed up the query and to connect multiple services.
|
||||
E.g. you can use the `hint` value obtained by the `nearest` query as `hint` values for `route` inputs.
|
||||
|
||||
@@ -129,6 +129,9 @@ tables. Optionally returns distance table.
|
||||
- `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.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
|
||||
- `options.fallback_speed` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Replace `null` responses in result with as-the-crow-flies estimates based on `fallback_speed`. Value is in metres/second.
|
||||
- `options.fallback_coordinate` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Either `input` (default) or `snapped`. If using a `fallback_speed`, use either the user-supplied coordinate (`input`), or the snapped coordinate (`snapped`) for calculating the as-the-crow-flies diestance between two points.
|
||||
- `options.scale_factor` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Multiply the table duration values in the table by this number for more controlled input into a route optimization solver.
|
||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||
|
||||
**Examples**
|
||||
@@ -154,6 +157,7 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
|
||||
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.
|
||||
**`fallback_speed_cells`**: (optional) if `fallback_speed` is used, will be an array of arrays of `row,column` values, indicating which cells contain estimated values.
|
||||
|
||||
### tile
|
||||
|
||||
|
||||
@@ -109,3 +109,12 @@ Feature: Car - Handle ferry routes
|
||||
When I route I should get
|
||||
| from | to | route | modes | time |
|
||||
| c | d | bcde,bcde | ferry,ferry | 600s |
|
||||
|
||||
Given the query options
|
||||
| geometries | geojson |
|
||||
| overview | full |
|
||||
|
||||
# Note that matching *should* work across unsnappable ferries
|
||||
When I match I should get
|
||||
| trace | geometry | duration |
|
||||
| abcdef| 1,1,1.000899,1,1.000899,1,1.002697,1,1.002697,1,1.003596,1,1.003596,1,1.005394,1,1.005394,1,1.006293,1 | 610.9 |
|
||||
|
||||
@@ -137,3 +137,28 @@ OSRM will use 4/5 of the projected free-flow speed.
|
||||
| primary | | | 30 | -1 | | 23 km/h | | 6.7 |
|
||||
| primary | 20 | 30 | | -1 | | 15 km/h | | 4.4 |
|
||||
| primary | 20 | | 30 | -1 | | 23 km/h | | 6.7 |
|
||||
|
||||
|
||||
Scenario: Car - Respect source:maxspeed
|
||||
Given the node map
|
||||
"""
|
||||
a b c d e f g
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | source:maxspeed | maxspeed |
|
||||
| ab | trunk | | |
|
||||
| bc | trunk | | 60 |
|
||||
| cd | trunk | FR:urban | |
|
||||
| de | trunk | CH:rural | |
|
||||
| ef | trunk | CH:trunk | |
|
||||
| fg | trunk | CH:motorway | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 85 km/h |
|
||||
| b | c | bc,bc | 48 km/h |
|
||||
| c | d | cd,cd | 40 km/h |
|
||||
| d | e | de,de | 64 km/h |
|
||||
| e | f | ef,ef | 80 km/h |
|
||||
| f | g | fg,fg | 96 km/h |
|
||||
@@ -35,3 +35,28 @@ Feature: Car - Allowed start/end modes
|
||||
| from | to | route | modes |
|
||||
| 1 | 2 | ab,ab | driving,driving |
|
||||
| 2 | 1 | ab,ab | driving,driving |
|
||||
|
||||
Scenario: Car - URL override of non-startpoints
|
||||
Given the node map
|
||||
"""
|
||||
a 1 b c 2 d
|
||||
"""
|
||||
|
||||
Given the query options
|
||||
| snapping | any |
|
||||
|
||||
And the ways
|
||||
| nodes | highway | access |
|
||||
| ab | service | private |
|
||||
| bc | primary | |
|
||||
| cd | service | private |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | 2 | c |
|
||||
| 1 | 59.1 | 35.1 |
|
||||
| b | 35.1 | 11.1 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 1 | 2 | ab,bc,cd |
|
||||
| 2 | 1 | cd,bc,ab |
|
||||
|
||||
@@ -295,7 +295,7 @@ module.exports = function () {
|
||||
this.reprocess(callback);
|
||||
});
|
||||
|
||||
this.Given(/^osrm\-routed is stopped$/, (callback) => {
|
||||
this.Given(/^osrm-routed is stopped$/, (callback) => {
|
||||
this.OSRMLoader.shutdown(callback);
|
||||
});
|
||||
|
||||
|
||||
@@ -3,22 +3,25 @@ var util = require('util');
|
||||
module.exports = function () {
|
||||
const durationsRegex = new RegExp(/^I request a travel time matrix I should get$/);
|
||||
const distancesRegex = new RegExp(/^I request a travel distance matrix I should get$/);
|
||||
const estimatesRegex = new RegExp(/^I request a travel time matrix I should get estimates for$/);
|
||||
|
||||
const DURATIONS_NO_ROUTE = 2147483647; // MAX_INT
|
||||
const DISTANCES_NO_ROUTE = 3.40282e+38; // MAX_FLOAT
|
||||
|
||||
this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', callback);}.bind(this));
|
||||
this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', callback);}.bind(this));
|
||||
this.When(estimatesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'fallback_speed_cells', callback);}.bind(this));
|
||||
};
|
||||
|
||||
const durationsParse = function(v) { return isNaN(parseInt(v)); };
|
||||
const distancesParse = function(v) { return isNaN(parseFloat(v)); };
|
||||
const estimatesParse = function(v) { return isNaN(parseFloat(v)); };
|
||||
|
||||
function tableParse(table, noRoute, annotation, callback) {
|
||||
|
||||
const parse = annotation == 'distances' ? distancesParse : durationsParse;
|
||||
const parse = annotation == 'distances' ? distancesParse : (annotation == 'durations' ? durationsParse : estimatesParse);
|
||||
const params = this.queryParams;
|
||||
params.annotations = annotation == 'distances' ? 'distance' : 'duration';
|
||||
params.annotations = ['durations','fallback_speed_cells'].indexOf(annotation) !== -1 ? 'duration' : 'distance';
|
||||
|
||||
var tableRows = table.raw();
|
||||
|
||||
@@ -61,11 +64,26 @@ function tableParse(table, noRoute, annotation, callback) {
|
||||
|
||||
var json = JSON.parse(response.body);
|
||||
|
||||
var result = json[annotation].map(row => {
|
||||
var hashes = {};
|
||||
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; });
|
||||
return hashes;
|
||||
});
|
||||
var result = {};
|
||||
if (annotation === 'fallback_speed_cells') {
|
||||
result = table.raw().map(row => row.map(() => ''));
|
||||
json[annotation].forEach(pair => {
|
||||
result[pair[0]+1][pair[1]+1] = 'Y';
|
||||
});
|
||||
result = result.slice(1).map(row => {
|
||||
var hashes = {};
|
||||
row.slice(1).forEach((v,i) => {
|
||||
hashes[tableRows[0][i+1]] = v;
|
||||
});
|
||||
return hashes;
|
||||
});
|
||||
} else {
|
||||
result = json[annotation].map(row => {
|
||||
var hashes = {};
|
||||
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; });
|
||||
return hashes;
|
||||
});
|
||||
}
|
||||
|
||||
var testRow = (row, ri, cb) => {
|
||||
for (var k in result[ri]) {
|
||||
|
||||
@@ -21,11 +21,11 @@ module.exports = function () {
|
||||
});
|
||||
};
|
||||
|
||||
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
|
||||
this.When(/^I run "osrm-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
|
||||
this.runAndSafeOutput('osrm-routed', options, callback);
|
||||
});
|
||||
|
||||
this.When(/^I run "osrm\-(extract|contract|partition|customize)\s?(.*?)"$/, (binary, options, callback) => {
|
||||
this.When(/^I run "osrm-(extract|contract|partition|customize)\s?(.*?)"$/, (binary, options, callback) => {
|
||||
const stamp = this.processedCacheFile + '.stamp_' + binary;
|
||||
this.runAndSafeOutput('osrm-' + binary, options, (err) => {
|
||||
if (err) return callback(err);
|
||||
@@ -33,11 +33,11 @@ module.exports = function () {
|
||||
});
|
||||
});
|
||||
|
||||
this.When(/^I try to run "(osrm\-[a-z]+)\s?(.*?)"$/, (binary, options, callback) => {
|
||||
this.When(/^I try to run "(osrm-[a-z]+)\s?(.*?)"$/, (binary, options, callback) => {
|
||||
this.runAndSafeOutput(binary, options, () => { callback(); });
|
||||
});
|
||||
|
||||
this.When(/^I run "osrm\-datastore\s?(.*?)"(?: with input "([^"]*)")?$/, (options, input, callback) => {
|
||||
this.When(/^I run "osrm-datastore\s?(.*?)"(?: with input "([^"]*)")?$/, (options, input, callback) => {
|
||||
let child = this.runAndSafeOutput('osrm-datastore', options, callback);
|
||||
if (input !== undefined)
|
||||
child.stdin.write(input);
|
||||
@@ -55,13 +55,13 @@ module.exports = function () {
|
||||
this.Then(/^stdout should( not)? contain "(.*?)"$/, (not, str) => {
|
||||
const contains = this.stdout.indexOf(str) > -1;
|
||||
assert.ok(typeof not === 'undefined' ? contains : !contains,
|
||||
'stdout ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
|
||||
'stdout ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
|
||||
});
|
||||
|
||||
this.Then(/^stderr should( not)? contain "(.*?)"$/, (not, str) => {
|
||||
const contains = this.stderr.indexOf(str) > -1;
|
||||
assert.ok(typeof not === 'undefined' ? contains : !contains,
|
||||
'stderr ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
|
||||
'stderr ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
|
||||
});
|
||||
|
||||
this.Then(/^stdout should contain \/(.*)\/$/, (regexStr) => {
|
||||
|
||||
@@ -69,7 +69,7 @@ module.exports = function () {
|
||||
outputRow[direction] = result[direction].status ?
|
||||
'x' : '';
|
||||
break;
|
||||
case /^[\d\.]+ s/.test(want):
|
||||
case /^[\d.]+ s/.test(want):
|
||||
// the result here can come back as a non-number value like
|
||||
// `diff`, but we only want to apply the unit when it comes
|
||||
// back as a number, for tableDiff's literal comparison
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = function() {
|
||||
|
||||
// setup cache for feature data
|
||||
// if OSRM_PROFILE is set to force a specific profile, then
|
||||
// include the profile name in the hash of the profile file
|
||||
// include the profile name in the hash of the profile file
|
||||
hash.hashOfFile(uri, this.OSRM_PROFILE, (err, hash) => {
|
||||
if (err) return callback(err);
|
||||
|
||||
@@ -45,10 +45,10 @@ module.exports = function() {
|
||||
this.featureProcessedCacheDirectories[uri] = featureProcessedCacheDirectory;
|
||||
|
||||
d3.queue(1)
|
||||
.defer(mkdirp, featureProcessedCacheDirectory)
|
||||
.defer(this.cleanupFeatureCache.bind(this), featureCacheDirectory, hash)
|
||||
.defer(this.cleanupProcessedFeatureCache.bind(this), featureProcessedCacheDirectory, this.osrmHash)
|
||||
.awaitAll(callback);
|
||||
.defer(mkdirp, featureProcessedCacheDirectory)
|
||||
.defer(this.cleanupFeatureCache.bind(this), featureCacheDirectory, hash)
|
||||
.defer(this.cleanupProcessedFeatureCache.bind(this), featureProcessedCacheDirectory, this.osrmHash)
|
||||
.awaitAll(callback);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ module.exports = function() {
|
||||
fs.readdir(parentPath, (err, files) => {
|
||||
let q = d3.queue();
|
||||
files.filter(name => { return name !== featureHash;})
|
||||
.map((f) => { q.defer(rimraf, path.join(parentPath, f)); });
|
||||
.map((f) => { q.defer(rimraf, path.join(parentPath, f)); });
|
||||
q.awaitAll(callback);
|
||||
});
|
||||
};
|
||||
@@ -145,7 +145,7 @@ module.exports = function() {
|
||||
|
||||
// converts the scenario titles in file prefixes
|
||||
this.getScenarioID = (scenario) => {
|
||||
let name = scenario.getName().toLowerCase().replace(/[\/\-'=,\(\):\*#]/g, '')
|
||||
let name = scenario.getName().toLowerCase().replace(/[/\-'=,():*#]/g, '')
|
||||
.replace(/\s/g, '_').replace(/__/g, '_').replace(/\.\./g, '.')
|
||||
.substring(0, 64);
|
||||
return util.format('%d_%s', scenario.getLine(), name);
|
||||
|
||||
@@ -17,12 +17,12 @@ module.exports = {
|
||||
return true;
|
||||
|
||||
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
|
||||
matchAbs = want.match(/(.*)\s+\+\-(.+)$/),
|
||||
matchAbs = want.match(/(.*)\s+\+-(.+)$/),
|
||||
matchRe = want.match(/^\/(.*)\/$/),
|
||||
// we use this for matching before/after bearing
|
||||
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
|
||||
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/),
|
||||
matchRangeNumbers = want.match(/\d+\+\-\d+/);
|
||||
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+-(.+)$/),
|
||||
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+-(.+)$/),
|
||||
matchRangeNumbers = want.match(/\d+\+-\d+/);
|
||||
|
||||
function inRange(margin, got, want) {
|
||||
var fromR = parseFloat(want) - margin,
|
||||
@@ -31,12 +31,12 @@ module.exports = {
|
||||
}
|
||||
function parseIntersectionString(str) {
|
||||
return str.split(';')
|
||||
.map((turn_intersections) => turn_intersections
|
||||
.split(',')
|
||||
.map((intersection) => intersection
|
||||
.split(' ')
|
||||
.map((entry_bearing_pair) => entry_bearing_pair
|
||||
.split(':'))));
|
||||
.map((turn_intersections) => turn_intersections
|
||||
.split(',')
|
||||
.map((intersection) => intersection
|
||||
.split(' ')
|
||||
.map((entry_bearing_pair) => entry_bearing_pair
|
||||
.split(':'))));
|
||||
}
|
||||
|
||||
if (got === want) {
|
||||
|
||||
@@ -80,7 +80,7 @@ module.exports = function () {
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(util.format('Node Version', process.version));
|
||||
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
|
||||
if (parseInt(process.version.match(/v(\d+)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
|
||||
|
||||
fs.exists(this.TEST_PATH, (exists) => {
|
||||
if (exists)
|
||||
|
||||
@@ -115,7 +115,7 @@ module.exports = function () {
|
||||
|
||||
if (headers.has('weight')) {
|
||||
if (row.weight.length) {
|
||||
if (!row.weight.match(/[\d\.]+/))
|
||||
if (!row.weight.match(/[\d.]+/))
|
||||
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
|
||||
got.weight = instructions ? util.format('%d', weight) : '';
|
||||
} else {
|
||||
@@ -151,7 +151,7 @@ module.exports = function () {
|
||||
if (headers.has('locations')){
|
||||
got.locations = (locations || '').trim();
|
||||
}
|
||||
/*
|
||||
/*
|
||||
if (headers.has('approaches')){
|
||||
got.approaches = (approaches || '').trim();
|
||||
}*/
|
||||
|
||||
@@ -595,3 +595,131 @@ Feature: Basic Distance Matrix
|
||||
| d | 1478.9 | 1579 | 1779.1 | 0 | 1280.1 | 882.5 |
|
||||
| e | 198.8 | 298.9 | 499 | 710.3 | 0 | 1592.8 |
|
||||
| f | 596.4 | 696.5 | 896.6 | 1107.9 | 397.6 | 0 |
|
||||
|
||||
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| fallback_speed | 5 |
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 300.2 | 900.7 | 1501.1 |
|
||||
| b | 300.2 | 0 | 600.5 | 1200.9 |
|
||||
| f | 900.7 | 600.5 | 0 | 300.2 |
|
||||
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 300.2 | 900.7 | 1501.1 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 300.2 |
|
||||
| f | 900.7 |
|
||||
| 1 | 1501.1 |
|
||||
|
||||
Scenario: Testbot - Fise input coordinate
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| fallback_speed | 5 |
|
||||
| fallback_coordinate | input |
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 300.2 | 900.7 | 1501.1 |
|
||||
| b | 300.2 | 0 | 600.5 | 1200.9 |
|
||||
| f | 900.7 | 600.5 | 0 | 300.2 |
|
||||
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 300.2 | 900.7 | 1501.1 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 300.2 |
|
||||
| f | 900.7 |
|
||||
| 1 | 1501.1 |
|
||||
|
||||
|
||||
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| fallback_speed | 5 |
|
||||
| fallback_coordinate | snapped |
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 300.2 | 900.7 | 1200.9 |
|
||||
| b | 300.2 | 0 | 600.5 | 900.7 |
|
||||
| f | 900.7 | 600.5 | 0 | 300.2 |
|
||||
| 1 | 1200.9 | 900.7 | 300.2 | 0 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 300.2 | 900.7 | 1200.9 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 300.2 |
|
||||
| f | 900.7 |
|
||||
| 1 | 1200.9 |
|
||||
|
||||
Scenario: Ensure consistency with route, and make sure offsets work in both directions
|
||||
Given a grid size of 100 meters
|
||||
Given the node map
|
||||
"""
|
||||
a b c d e f g h i j
|
||||
1 2
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abcdef |
|
||||
| fghij |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | distance |
|
||||
| 1 | 2 | abcdef,fghij,fghij | 999.9m |
|
||||
|
||||
# TODO: this is "correct", but inconsistent with viaroute
|
||||
When I request a travel distance matrix I should get
|
||||
| | 1 | 2 |
|
||||
| 1 | 0 | 1000.7 |
|
||||
| 2 | 1000.7 | 0 |
|
||||
@@ -510,3 +510,268 @@ Feature: Basic Duration Matrix
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 24.1 |
|
||||
|
||||
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| fallback_speed | 5 |
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 30 | 18 | 30 |
|
||||
| b | 30 | 0 | 12 | 24 |
|
||||
| f | 18 | 12 | 0 | 30 |
|
||||
| 1 | 30 | 24 | 30 | 0 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 30 | 18 | 30 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 30 |
|
||||
| f | 18 |
|
||||
| 1 | 30 |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
| b | | | Y | Y |
|
||||
| f | Y | Y | | |
|
||||
| 1 | Y | Y | | |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a |
|
||||
| a | |
|
||||
| b | |
|
||||
| f | Y |
|
||||
| 1 | Y |
|
||||
|
||||
Scenario: Testbot - Filling in noroutes with estimates - use input coordinate
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| fallback_speed | 5 |
|
||||
| fallback_coordinate | input |
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 30 | 18 | 30 |
|
||||
| b | 30 | 0 | 12 | 24 |
|
||||
| f | 18 | 12 | 0 | 30 |
|
||||
| 1 | 30 | 24 | 30 | 0 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 30 | 18 | 30 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 30 |
|
||||
| f | 18 |
|
||||
| 1 | 30 |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
| b | | | Y | Y |
|
||||
| f | Y | Y | | |
|
||||
| 1 | Y | Y | | |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a |
|
||||
| a | |
|
||||
| b | |
|
||||
| f | Y |
|
||||
| 1 | Y |
|
||||
|
||||
|
||||
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| fallback_speed | 5 |
|
||||
| fallback_coordinate | snapped |
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 30 | 18 | 24 |
|
||||
| b | 30 | 0 | 12 | 18 |
|
||||
| f | 18 | 12 | 0 | 30 |
|
||||
| 1 | 24 | 18 | 30 | 0 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 30 | 18 | 24 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 30 |
|
||||
| f | 18 |
|
||||
| 1 | 24 |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
| b | | | Y | Y |
|
||||
| f | Y | Y | | |
|
||||
| 1 | Y | Y | | |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a |
|
||||
| a | |
|
||||
| b | |
|
||||
| f | Y |
|
||||
| 1 | Y |
|
||||
|
||||
Scenario: Testbot - Travel time matrix of minimal network with scale factor
|
||||
Given the query options
|
||||
| scale_factor | 2 |
|
||||
Given the node map
|
||||
"""
|
||||
a b
|
||||
"""
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b |
|
||||
| a | 0 | 20 |
|
||||
| b | 20 | 0 |
|
||||
Scenario: Testbot - Test fallback speeds and scale factor
|
||||
Given a grid size of 300 meters
|
||||
Given the extract extra arguments "--small-component-size 4"
|
||||
Given the query options
|
||||
| scale_factor | 2 |
|
||||
| fallback_speed | 5 |
|
||||
| fallback_coordinate | snapped |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b f h 1
|
||||
d e g i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abeda |
|
||||
| fhigf |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 60 | 36 | 48 |
|
||||
| b | 60 | 0 | 24 | 36 |
|
||||
| f | 36 | 24 | 0 | 60 |
|
||||
| 1 | 48 | 36 | 60 | 0 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b | f | 1 |
|
||||
| a | 0 | 60 | 36 | 48 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| b | 60 |
|
||||
| f | 36 |
|
||||
| 1 | 48 |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
| b | | | Y | Y |
|
||||
| f | Y | Y | | |
|
||||
| 1 | Y | Y | | |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a | b | f | 1 |
|
||||
| a | | | Y | Y |
|
||||
|
||||
When I request a travel time matrix I should get estimates for
|
||||
| | a |
|
||||
| a | |
|
||||
| b | |
|
||||
| f | Y |
|
||||
| 1 | Y |
|
||||
|
||||
|
||||
Scenario: Testbot - Travel time matrix of minimal network with overflow scale factor
|
||||
Given the query options
|
||||
| scale_factor | 2147483647 |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b |
|
||||
| a | 0 | 214748364.6 |
|
||||
| b | 214748364.6 | 0 |
|
||||
|
||||
Scenario: Testbot - Travel time matrix of minimal network with fraction scale factor
|
||||
Given the query options
|
||||
| scale_factor | 0.5 |
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | b |
|
||||
| a | 0 | 5 |
|
||||
| b | 5 | 0 |
|
||||
|
||||
@@ -111,9 +111,9 @@ Feature: Multi level routing
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | f | l | o |
|
||||
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
|
||||
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
|
||||
| l | 1618.3 | 1293.3 | 0 | 800.5 |
|
||||
| o | 1418.2 | 1617.3 | 800.5 | 0 |
|
||||
| f | 2383.7 | 0 | 1293.3 | 1617.3 |
|
||||
| l | 1566.9 | 1293.3 | 0 | 800.5 |
|
||||
| o | 1366.8 | 1617.3 | 800.5 | 0 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | f | l | o |
|
||||
@@ -122,21 +122,21 @@ Feature: Multi level routing
|
||||
When I request a travel distance matrix I should get
|
||||
| | a |
|
||||
| a | 0 |
|
||||
| f | 2339.9 |
|
||||
| l | 1618.3 |
|
||||
| o | 1418.2 |
|
||||
| f | 2383.7 |
|
||||
| l | 1566.9 |
|
||||
| o | 1366.8 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | f | l | o |
|
||||
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
|
||||
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
|
||||
| f | 2383.7 | 0 | 1293.3 | 1617.3 |
|
||||
|
||||
When I request a travel distance matrix I should get
|
||||
| | a | o |
|
||||
| a | 0 | 1366.8 |
|
||||
| f | 2339.9 | 1522.1 |
|
||||
| l | 1618.3 | 800.5 |
|
||||
| o | 1418.2 | 0 |
|
||||
| f | 2383.7 | 1617.3 |
|
||||
| l | 1566.9 | 800.5 |
|
||||
| o | 1366.8 | 0 |
|
||||
|
||||
Scenario: Testbot - Multi level routing: horizontal road
|
||||
Given the node map
|
||||
|
||||
@@ -182,4 +182,4 @@ Feature: Snap start/end point to the nearest way
|
||||
| x | m | xe,xe |
|
||||
| x | n | xf,xf |
|
||||
| x | o | xg,xg |
|
||||
| x | p | xh,xh |
|
||||
| x | p | xh,xh |
|
||||
@@ -0,0 +1,168 @@
|
||||
@routing @maxspeed @testbot
|
||||
Feature: Testbot - Acceleration profiles
|
||||
|
||||
Background: Use specific speeds
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Testbot - No stoppage penalties
|
||||
Given a grid size of 10 meters
|
||||
Given the node map
|
||||
"""
|
||||
a 1 2 3 4 5 b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||
| ab | trunk | 60 | 45 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time | distance |
|
||||
| a | b | ab,ab | 3.6s | 59.9m |
|
||||
| a | 1 | ab,ab | 0.6s | 10m |
|
||||
| a | 2 | ab,ab | 1.2s | 20m |
|
||||
| a | 3 | ab,ab | 1.8s | 30m |
|
||||
| a | 4 | ab,ab | 2.4s | 40m |
|
||||
| a | 5 | ab,ab | 3s | 50m |
|
||||
| 5 | b | ab,ab | 0.6s | 9.9m |
|
||||
| 4 | b | ab,ab | 1.2s | 19.9m |
|
||||
| 3 | b | ab,ab | 1.8s | 29.9m |
|
||||
| 2 | b | ab,ab | 2.4s | 39.9m |
|
||||
| 1 | b | ab,ab | 3s | 49.9m |
|
||||
| 1 | 2 | ab,ab | 0.6s | 10m |
|
||||
| 1 | 3 | ab,ab | 1.2s | 20m |
|
||||
| 1 | 4 | ab,ab | 1.8s | 30m |
|
||||
| 1 | 5 | ab,ab | 2.4s | 40m |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||
| a | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 | 3.6 |
|
||||
| 1 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 |
|
||||
| 2 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 |
|
||||
| 3 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 |
|
||||
| 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 |
|
||||
| 5 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 |
|
||||
| b | 4.8 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 |
|
||||
|
||||
Scenario: Testbot - No stoppage points, tiny grid size
|
||||
Given a grid size of 1 meters
|
||||
Given the node map
|
||||
"""
|
||||
a 1 2 3 4 5 6 7 8 9 b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||
| ab | trunk | 60 | 45 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
|
||||
| a | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
|
||||
| 1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
|
||||
| 2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
|
||||
| 3 | 0.2 | 0.2 | 0.1 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
|
||||
| 4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 | 0.1 | 0.2 | 0.2 | 0.3 | 0.4 |
|
||||
| 5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
|
||||
| 6 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
|
||||
| 7 | 0.5 | 0.5 | 0.4 | 0.3 | 0.2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 |
|
||||
| 8 | 0.6 | 0.6 | 0.5 | 0.4 | 0.3 | 0.2 | 0.2 | 0.1 | 0 | 0.1 | 0.2 |
|
||||
| 9 | 0.7 | 0.7 | 0.6 | 0.5 | 0.4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 |
|
||||
| b | 0.8 | 0.8 | 0.7 | 0.6 | 0.5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 |
|
||||
|
||||
Scenario: Testbot - With stoppage points, tiny grid size
|
||||
Given a grid size of 1 meters
|
||||
Given the node map
|
||||
"""
|
||||
a 1 2 3 4 5 6 7 8 9 b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||
| ab | trunk | 60 | 45 |
|
||||
|
||||
And the query options
|
||||
| acceleration_profile | car |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
|
||||
| a | 0 | 1.1 | 1.7 | 2.1 | 2.4 | 2.6 | 2.9 | 3.1 | 3.4 | 3.5 | 3.7 |
|
||||
| 1 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.3 | 2.6 | 2.8 | 3.1 | 3.3 | 3.5 |
|
||||
| 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.4 | 2.6 | 2.9 | 3.1 | 3.3 |
|
||||
| 3 | 2 | 1.5 | 1.1 | 0 | 1.1 | 1.5 | 2 | 2.3 | 2.6 | 2.8 | 3 |
|
||||
| 4 | 2.3 | 1.9 | 1.5 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.4 | 2.6 | 2.8 |
|
||||
| 5 | 2.5 | 2.2 | 1.9 | 1.5 | 1.1 | 0 | 1.1 | 1.7 | 2.1 | 2.4 | 2.6 |
|
||||
| 6 | 2.8 | 2.5 | 2.3 | 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.3 |
|
||||
| 7 | 3 | 2.8 | 2.5 | 2.3 | 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 |
|
||||
| 8 | 3.2 | 3 | 2.8 | 2.5 | 2.3 | 2 | 1.5 | 1.1 | 0 | 1.1 | 1.5 |
|
||||
| 9 | 3.4 | 3.2 | 3 | 2.8 | 2.5 | 2.3 | 1.9 | 1.5 | 1.1 | 0 | 1.1 |
|
||||
| b | 3.6 | 3.4 | 3.2 | 3 | 2.8 | 2.5 | 2.2 | 1.9 | 1.5 | 1.1 | 0 |
|
||||
|
||||
|
||||
Scenario: Testbot - Use stoppage penalty at waypoints
|
||||
Given a grid size of 10 meters
|
||||
Given the node map
|
||||
"""
|
||||
a 1 2 3 4 5 b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||
| ab | trunk | 60 | 45 |
|
||||
|
||||
And the query options
|
||||
| acceleration_profile | car |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||
| a | 0 | 3.7 | 5.3 | 6.5 | 7.5 | 8.4 | 9.1 |
|
||||
| 1 | 3.6 | 0 | 3.7 | 5.3 | 6.5 | 7.5 | 8.3 |
|
||||
| 2 | 5.1 | 3.6 | 0 | 3.7 | 5.3 | 6.5 | 7.5 |
|
||||
| 3 | 6.3 | 5.1 | 3.6 | 0 | 3.7 | 5.3 | 6.4 |
|
||||
| 4 | 7.2 | 6.3 | 5.1 | 3.6 | 0 | 3.7 | 5.2 |
|
||||
| 5 | 8.1 | 7.2 | 6.3 | 5.1 | 3.6 | 0 | 3.7 |
|
||||
| b | 8.9 | 8.1 | 7.2 | 6.2 | 5.1 | 3.6 | 0 |
|
||||
|
||||
|
||||
Scenario: Long distance grid with no penalty
|
||||
Given a grid size of 1000 meters
|
||||
Given the node map
|
||||
"""
|
||||
a 1 2 3 4 5 b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||
| ab | trunk | 60 | 45 |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||
| a | 0 | 59.9 | 119.9 | 179.9 | 239.9 | 299.9 | 359.9 |
|
||||
| 1 | 79.9 | 0 | 60 | 120 | 180 | 240 | 300 |
|
||||
| 2 | 159.9 | 80 | 0 | 60 | 120 | 180 | 240 |
|
||||
| 3 | 239.9 | 160 | 80 | 0 | 60 | 120 | 180 |
|
||||
| 4 | 319.9 | 240 | 160 | 80 | 0 | 60 | 120 |
|
||||
| 5 | 399.9 | 320 | 240 | 160 | 80 | 0 | 60 |
|
||||
| b | 479.9 | 400 | 320 | 240 | 160 | 80 | 0 |
|
||||
|
||||
Scenario: Long distance grid
|
||||
Given a grid size of 1000 meters
|
||||
Given the node map
|
||||
"""
|
||||
a 1 2 3 4 5 b
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||
| ab | trunk | 60 | 45 |
|
||||
|
||||
And the query options
|
||||
| acceleration_profile | car |
|
||||
|
||||
When I request a travel time matrix I should get
|
||||
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||
| a | 0 | 65.1 | 125.1 | 185.1 | 245.1 | 305.1 | 365.1 |
|
||||
| 1 | 83.7 | 0 | 65.2 | 125.2 | 185.2 | 245.2 | 305.2 |
|
||||
| 2 | 163.7 | 83.8 | 0 | 65.2 | 125.2 | 185.2 | 245.2 |
|
||||
| 3 | 243.7 | 163.8 | 83.8 | 0 | 65.2 | 125.2 | 185.2 |
|
||||
| 4 | 323.7 | 243.8 | 163.8 | 83.8 | 0 | 65.2 | 125.2 |
|
||||
| 5 | 403.7 | 323.8 | 243.8 | 163.8 | 83.8 | 0 | 65.2 |
|
||||
| b | 483.7 | 403.8 | 323.8 | 243.8 | 163.8 | 83.8 | 0 |
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "engine/api/json_factory.hpp"
|
||||
#include "engine/hint.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/range/algorithm/transform.hpp>
|
||||
@@ -53,6 +54,8 @@ class BaseAPI
|
||||
// TODO: check forward/reverse
|
||||
return json::makeWaypoint(
|
||||
phantom.location,
|
||||
util::coordinate_calculation::fccApproximateDistance(phantom.location,
|
||||
phantom.input_location),
|
||||
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string(),
|
||||
Hint{phantom, facade.GetCheckSum()});
|
||||
}
|
||||
@@ -61,6 +64,8 @@ class BaseAPI
|
||||
// TODO: check forward/reverse
|
||||
return json::makeWaypoint(
|
||||
phantom.location,
|
||||
util::coordinate_calculation::fccApproximateDistance(phantom.location,
|
||||
phantom.input_location),
|
||||
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))
|
||||
.to_string());
|
||||
}
|
||||
|
||||
@@ -63,6 +63,13 @@ namespace api
|
||||
*/
|
||||
struct BaseParameters
|
||||
{
|
||||
|
||||
enum class SnappingType
|
||||
{
|
||||
Default,
|
||||
Any
|
||||
};
|
||||
|
||||
std::vector<util::Coordinate> coordinates;
|
||||
std::vector<boost::optional<Hint>> hints;
|
||||
std::vector<boost::optional<double>> radiuses;
|
||||
@@ -73,15 +80,22 @@ struct BaseParameters
|
||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||
bool generate_hints = true;
|
||||
|
||||
SnappingType snapping = SnappingType::Default;
|
||||
// Whether or not to add acceleration/decelleration penalties at waypoints
|
||||
double waypoint_acceleration_factor = 0.;
|
||||
|
||||
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
|
||||
const std::vector<boost::optional<Hint>> hints_ = {},
|
||||
std::vector<boost::optional<double>> radiuses_ = {},
|
||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||
bool generate_hints_ = true,
|
||||
std::vector<std::string> exclude = {})
|
||||
std::vector<std::string> exclude = {},
|
||||
const SnappingType snapping_ = SnappingType::Default,
|
||||
bool waypoint_acceleration_factor_ = 0.)
|
||||
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
||||
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
|
||||
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_),
|
||||
snapping(snapping_), waypoint_acceleration_factor(waypoint_acceleration_factor_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace json
|
||||
namespace detail
|
||||
{
|
||||
|
||||
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
|
||||
util::json::Array coordinateToLonLat(const util::Coordinate &coordinate);
|
||||
|
||||
/**
|
||||
* Ensures that a bearing value is a whole number, and clamped to the range 0-359
|
||||
@@ -86,11 +86,14 @@ util::json::Object makeRoute(const guidance::Route &route,
|
||||
const char *weight_name);
|
||||
|
||||
// Creates a Waypoint without Hint, see the Hint overload below
|
||||
util::json::Object makeWaypoint(const util::Coordinate location, std::string name);
|
||||
util::json::Object
|
||||
makeWaypoint(const util::Coordinate &location, const double &distance, std::string name);
|
||||
|
||||
// Creates a Waypoint with Hint, see the overload above when Hint is not needed
|
||||
util::json::Object
|
||||
makeWaypoint(const util::Coordinate location, std::string name, const Hint &hint);
|
||||
util::json::Object makeWaypoint(const util::Coordinate &location,
|
||||
const double &distance,
|
||||
std::string name,
|
||||
const Hint &hint);
|
||||
|
||||
util::json::Object makeRouteLeg(guidance::RouteLeg leg, util::json::Array steps);
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ class NearestAPI final : public BaseAPI
|
||||
[this](const PhantomNodeWithDistance &phantom_with_distance) {
|
||||
auto &phantom_node = phantom_with_distance.phantom_node;
|
||||
auto waypoint = MakeWaypoint(phantom_node);
|
||||
waypoint.values["distance"] = phantom_with_distance.distance;
|
||||
|
||||
util::json::Array nodes;
|
||||
|
||||
|
||||
@@ -31,6 +31,15 @@ namespace api
|
||||
class TableAPI final : public BaseAPI
|
||||
{
|
||||
public:
|
||||
struct TableCellRef
|
||||
{
|
||||
TableCellRef(const std::size_t &row, const std::size_t &column) : row{row}, column{column}
|
||||
{
|
||||
}
|
||||
std::size_t row;
|
||||
std::size_t column;
|
||||
};
|
||||
|
||||
TableAPI(const datafacade::BaseDataFacade &facade_, const TableParameters ¶meters_)
|
||||
: BaseAPI(facade_, parameters_), parameters(parameters_)
|
||||
{
|
||||
@@ -39,6 +48,7 @@ class TableAPI final : public BaseAPI
|
||||
virtual void
|
||||
MakeResponse(const std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> &tables,
|
||||
const std::vector<PhantomNode> &phantoms,
|
||||
const std::vector<TableCellRef> &fallback_speed_cells,
|
||||
util::json::Object &response) const
|
||||
{
|
||||
auto number_of_sources = parameters.sources.size();
|
||||
@@ -77,6 +87,11 @@ class TableAPI final : public BaseAPI
|
||||
MakeDistanceTable(tables.second, number_of_sources, number_of_destinations);
|
||||
}
|
||||
|
||||
if (parameters.fallback_speed != INVALID_FALLBACK_SPEED && parameters.fallback_speed > 0)
|
||||
{
|
||||
response.values["fallback_speed_cells"] = MakeEstimatesTable(fallback_speed_cells);
|
||||
}
|
||||
|
||||
response.values["code"] = "Ok";
|
||||
}
|
||||
|
||||
@@ -163,6 +178,20 @@ class TableAPI final : public BaseAPI
|
||||
return json_table;
|
||||
}
|
||||
|
||||
virtual util::json::Array
|
||||
MakeEstimatesTable(const std::vector<TableCellRef> &fallback_speed_cells) const
|
||||
{
|
||||
util::json::Array json_table;
|
||||
std::for_each(
|
||||
fallback_speed_cells.begin(), fallback_speed_cells.end(), [&](const auto &cell) {
|
||||
util::json::Array row;
|
||||
row.values.push_back(util::json::Number(cell.row));
|
||||
row.values.push_back(util::json::Number(cell.column));
|
||||
json_table.values.push_back(std::move(row));
|
||||
});
|
||||
return json_table;
|
||||
}
|
||||
|
||||
const TableParameters ¶meters;
|
||||
};
|
||||
|
||||
|
||||
@@ -59,6 +59,15 @@ struct TableParameters : public BaseParameters
|
||||
{
|
||||
std::vector<std::size_t> sources;
|
||||
std::vector<std::size_t> destinations;
|
||||
double fallback_speed = INVALID_FALLBACK_SPEED;
|
||||
|
||||
enum class FallbackCoordinateType
|
||||
{
|
||||
Input = 0,
|
||||
Snapped = 1
|
||||
};
|
||||
|
||||
FallbackCoordinateType fallback_coordinate_type = FallbackCoordinateType::Input;
|
||||
|
||||
enum class AnnotationsType
|
||||
{
|
||||
@@ -70,6 +79,8 @@ struct TableParameters : public BaseParameters
|
||||
|
||||
AnnotationsType annotations = AnnotationsType::Duration;
|
||||
|
||||
double scale_factor = 1;
|
||||
|
||||
TableParameters() = default;
|
||||
template <typename... Args>
|
||||
TableParameters(std::vector<std::size_t> sources_,
|
||||
@@ -90,6 +101,22 @@ struct TableParameters : public BaseParameters
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
TableParameters(std::vector<std::size_t> sources_,
|
||||
std::vector<std::size_t> destinations_,
|
||||
const AnnotationsType annotations_,
|
||||
double fallback_speed_,
|
||||
FallbackCoordinateType fallback_coordinate_type_,
|
||||
double scale_factor_,
|
||||
Args... args_)
|
||||
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
|
||||
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
|
||||
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
|
||||
scale_factor{scale_factor_}
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
if (!BaseParameters::IsValid())
|
||||
@@ -101,14 +128,7 @@ struct TableParameters : public BaseParameters
|
||||
|
||||
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's their fault
|
||||
|
||||
// 2/ len(srcs) and len(dsts) smaller or equal to len(locations)
|
||||
if (sources.size() > coordinates.size())
|
||||
return false;
|
||||
|
||||
if (destinations.size() > coordinates.size())
|
||||
return false;
|
||||
|
||||
// 3/ 0 <= index < len(locations)
|
||||
// 2/ 0 <= index < len(locations)
|
||||
const auto not_in_range = [this](const std::size_t x) { return x >= coordinates.size(); };
|
||||
|
||||
if (std::any_of(begin(sources), end(sources), not_in_range))
|
||||
@@ -117,6 +137,12 @@ struct TableParameters : public BaseParameters
|
||||
if (std::any_of(begin(destinations), end(destinations), not_in_range))
|
||||
return false;
|
||||
|
||||
if (fallback_speed <= 0)
|
||||
return false;
|
||||
|
||||
if (scale_factor <= 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -312,12 +312,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(
|
||||
input_coordinate, max_distance, approach);
|
||||
input_coordinate, max_distance, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
@@ -325,12 +326,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
@@ -384,23 +386,25 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, approach);
|
||||
input_coordinate, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, approach);
|
||||
input_coordinate, max_distance, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
@@ -408,24 +412,26 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, bearing, bearing_range, approach);
|
||||
input_coordinate, bearing, bearing_range, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
||||
|
||||
@@ -126,11 +126,13 @@ class BaseDataFacade
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
@@ -157,22 +159,26 @@ class BaseDataFacade
|
||||
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges = false) const = 0;
|
||||
|
||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||
|
||||
@@ -53,13 +53,15 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||
return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)),
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
[this, approach, &input_coordinate, use_all_edges](const CandidateSegment &segment) {
|
||||
return boolPairAnd(
|
||||
boolPairAnd(HasValidEdge(segment, use_all_edges), CheckSegmentExclude(segment)),
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
},
|
||||
[this, max_distance, input_coordinate](const std::size_t,
|
||||
const CandidateSegment &segment) {
|
||||
@@ -76,15 +78,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, bearing, bearing_range](
|
||||
[this, approach, &input_coordinate, bearing, bearing_range, use_all_edges](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_direction =
|
||||
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||
boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)));
|
||||
boolPairAnd(HasValidEdge(segment, use_all_edges),
|
||||
CheckSegmentExclude(segment)));
|
||||
use_direction =
|
||||
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
|
||||
return use_direction;
|
||||
@@ -201,18 +205,23 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
[this,
|
||||
approach,
|
||||
&input_coordinate,
|
||||
&has_big_component,
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto valid_edges = HasValidEdge(segment);
|
||||
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
@@ -247,19 +256,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
[this,
|
||||
approach,
|
||||
&input_coordinate,
|
||||
&has_big_component,
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
|
||||
const auto valid_edges = HasValidEdge(segment);
|
||||
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
@@ -294,7 +308,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -306,12 +321,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
bearing,
|
||||
bearing_range,
|
||||
&has_big_component,
|
||||
&has_small_component](const CandidateSegment &segment) {
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||
|
||||
if (use_segment)
|
||||
{
|
||||
@@ -352,7 +368,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -364,12 +381,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
bearing,
|
||||
bearing_range,
|
||||
&has_big_component,
|
||||
&has_small_component](const CandidateSegment &segment) {
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||
|
||||
if (use_segment)
|
||||
{
|
||||
@@ -461,6 +479,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
EdgeDuration{0});
|
||||
|
||||
EdgeDistance forward_distance_offset = 0;
|
||||
// Sum up the distance from the start to the fwd_segment_position
|
||||
for (auto current = forward_geometry.begin();
|
||||
current < forward_geometry.begin() + data.fwd_segment_position;
|
||||
++current)
|
||||
@@ -490,8 +509,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
EdgeDuration{0});
|
||||
|
||||
EdgeDistance reverse_distance_offset = 0;
|
||||
for (auto current = forward_geometry.begin();
|
||||
current < forward_geometry.end() - data.fwd_segment_position - 2;
|
||||
// Sum up the distance from just after the fwd_segment_position to the end
|
||||
for (auto current = forward_geometry.begin() + data.fwd_segment_position + 1;
|
||||
current != std::prev(forward_geometry.end());
|
||||
++current)
|
||||
{
|
||||
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
||||
@@ -628,7 +648,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
* which means that this edge is not currently traversible. If this is the case,
|
||||
* then we shouldn't snap to this edge.
|
||||
*/
|
||||
std::pair<bool, bool> HasValidEdge(const CandidateSegment &segment) const
|
||||
std::pair<bool, bool> HasValidEdge(const CandidateSegment &segment,
|
||||
const bool use_all_edges = false) const
|
||||
{
|
||||
|
||||
bool forward_edge_valid = false;
|
||||
@@ -652,6 +673,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
reverse_edge_valid = data.reverse_segment_id.enabled;
|
||||
}
|
||||
|
||||
forward_edge_valid = forward_edge_valid && (data.is_startpoint || use_all_edges);
|
||||
reverse_edge_valid = reverse_edge_valid && (data.is_startpoint || use_all_edges);
|
||||
|
||||
return std::make_pair(forward_edge_valid, reverse_edge_valid);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,8 @@ class BasePlugin
|
||||
std::vector<std::vector<PhantomNodeWithDistance>>
|
||||
GetPhantomNodesInRange(const datafacade::BaseDataFacade &facade,
|
||||
const api::BaseParameters ¶meters,
|
||||
const std::vector<double> radiuses) const
|
||||
const std::vector<double> radiuses,
|
||||
bool use_all_edges = false) const
|
||||
{
|
||||
std::vector<std::vector<PhantomNodeWithDistance>> phantom_nodes(
|
||||
parameters.coordinates.size());
|
||||
@@ -171,12 +172,13 @@ class BasePlugin
|
||||
radiuses[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_nodes[i] = facade.NearestPhantomNodesInRange(
|
||||
parameters.coordinates[i], radiuses[i], approach);
|
||||
parameters.coordinates[i], radiuses[i], approach, use_all_edges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +270,7 @@ class BasePlugin
|
||||
const bool use_bearings = !parameters.bearings.empty();
|
||||
const bool use_radiuses = !parameters.radiuses.empty();
|
||||
const bool use_approaches = !parameters.approaches.empty();
|
||||
const bool use_all_edges = parameters.snapping == api::BaseParameters::SnappingType::Any;
|
||||
|
||||
BOOST_ASSERT(parameters.IsValid());
|
||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
@@ -294,7 +297,8 @@ class BasePlugin
|
||||
*parameters.radiuses[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -303,7 +307,8 @@ class BasePlugin
|
||||
parameters.coordinates[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -312,13 +317,16 @@ class BasePlugin
|
||||
{
|
||||
phantom_node_pairs[i] =
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i], *parameters.radiuses[i], approach);
|
||||
parameters.coordinates[i],
|
||||
*parameters.radiuses[i],
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_node_pairs[i] =
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i], approach);
|
||||
parameters.coordinates[i], approach, use_all_edges);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,6 @@ class EdgeBasedGraphFactory
|
||||
// The following get access functions destroy the content in the factory
|
||||
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
|
||||
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
|
||||
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
||||
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
||||
void GetEdgeBasedNodeDurations(std::vector<EdgeWeight> &output_node_durations);
|
||||
void GetEdgeBasedNodeDistances(std::vector<EdgeDistance> &output_node_distances);
|
||||
@@ -112,10 +111,6 @@ class EdgeBasedGraphFactory
|
||||
std::vector<ConditionalTurnPenalty>
|
||||
IndexConditionals(std::vector<Conditional> &&conditionals) const;
|
||||
|
||||
//! maps index from m_edge_based_node_list to ture/false if the node is an entry point to the
|
||||
//! graph
|
||||
std::vector<bool> m_edge_based_node_is_startpoint;
|
||||
|
||||
//! node weights that indicate the length of the segment (node based) represented by the
|
||||
//! edge-based node
|
||||
std::vector<EdgeWeight> m_edge_based_node_weights;
|
||||
|
||||
@@ -22,7 +22,9 @@ struct EdgeBasedNodeSegment
|
||||
EdgeBasedNodeSegment()
|
||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
|
||||
fwd_segment_position(std::numeric_limits<unsigned short>::max())
|
||||
fwd_segment_position(std::numeric_limits<unsigned short>::max() >>
|
||||
1), // >> 1 because we've only got 15 bits
|
||||
is_startpoint(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -30,9 +32,10 @@ struct EdgeBasedNodeSegment
|
||||
const SegmentID reverse_segment_id_,
|
||||
NodeID u,
|
||||
NodeID v,
|
||||
unsigned short fwd_segment_position)
|
||||
unsigned short fwd_segment_position,
|
||||
bool is_startpoint_)
|
||||
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
|
||||
v(v), fwd_segment_position(fwd_segment_position)
|
||||
v(v), fwd_segment_position(fwd_segment_position), is_startpoint(is_startpoint_)
|
||||
{
|
||||
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
|
||||
}
|
||||
@@ -41,7 +44,8 @@ struct EdgeBasedNodeSegment
|
||||
SegmentID reverse_segment_id; // edge-based graph node ID in reverse direction (v->u if exists)
|
||||
NodeID u; // node-based graph node ID of the start node
|
||||
NodeID v; // node-based graph node ID of the target node
|
||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||
unsigned short fwd_segment_position : 15; // segment id in a compressed geometry
|
||||
bool is_startpoint : 1;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ class Extractor
|
||||
// output data
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
std::vector<EdgeDuration> &edge_based_node_durations,
|
||||
std::vector<EdgeDistance> &edge_based_node_distances,
|
||||
@@ -97,7 +96,6 @@ class Extractor
|
||||
const std::vector<EdgeBasedNodeSegment> &input_node_segments,
|
||||
EdgeBasedNodeDataContainer &nodes_container) const;
|
||||
void BuildRTree(std::vector<EdgeBasedNodeSegment> edge_based_node_segments,
|
||||
std::vector<bool> node_is_startpoint,
|
||||
const std::vector<util::Coordinate> &coordinates);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
|
||||
|
||||
@@ -692,6 +692,77 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("snapping").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> snapping = obj->Get(Nan::New("snapping").ToLocalChecked());
|
||||
if (snapping.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!snapping->IsString())
|
||||
{
|
||||
Nan::ThrowError("Snapping must be a string: [default, any]");
|
||||
return false;
|
||||
}
|
||||
const Nan::Utf8String snapping_utf8str(snapping);
|
||||
std::string snapping_str{*snapping_utf8str, *snapping_utf8str + snapping_utf8str.length()};
|
||||
|
||||
if (snapping_str == "default")
|
||||
{
|
||||
params->snapping = osrm::RouteParameters::SnappingType::Default;
|
||||
}
|
||||
else if (snapping_str == "any")
|
||||
{
|
||||
params->snapping = osrm::RouteParameters::SnappingType::Any;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nan::ThrowError("'snapping' param must be one of [default, any]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("acceleration_profile").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> acceleration_profile =
|
||||
obj->Get(Nan::New("acceleration_profile").ToLocalChecked());
|
||||
if (acceleration_profile.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!acceleration_profile->IsNumber() || !acceleration_profile->IsString())
|
||||
{
|
||||
Nan::ThrowError("acceleration_profile must be a decimal number or one of 'car', 'fast_car', 'slow_car', 'truck', or 'tractor_trailer'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (acceleration_profile->IsString()) {
|
||||
std::string ssaf = *v8::String::Utf8Value(acceleration_profile);
|
||||
// If they say 'yes', they get the default
|
||||
if (ssaf == "car") {
|
||||
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_CAR;
|
||||
} else if (ssaf == "fast_car") {
|
||||
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_FAST_CAR;
|
||||
} else if (ssaf == "slow_car") {
|
||||
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_SLOW_CAR;
|
||||
} else if (ssaf == "truck") {
|
||||
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_TRUCK;
|
||||
} else if (ssaf == "tractor_trailer") {
|
||||
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_TRACTOR_TRAILER;
|
||||
} else {
|
||||
Nan::ThrowError("acceleration_profile must be a decimal number or one of 'car', 'fast_car', 'slow_car', 'truck', or 'tractor_trailer'");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto value = acceleration_profile->NumberValue();
|
||||
if (value < 0) {
|
||||
Nan::ThrowError("acceleration_profile cannot be negative");
|
||||
return false;
|
||||
}
|
||||
|
||||
params->waypoint_acceleration_factor = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1183,6 +1254,70 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("fallback_speed").ToLocalChecked()))
|
||||
{
|
||||
auto fallback_speed = obj->Get(Nan::New("fallback_speed").ToLocalChecked());
|
||||
|
||||
if (!fallback_speed->IsNumber())
|
||||
{
|
||||
Nan::ThrowError("fallback_speed must be a number");
|
||||
return table_parameters_ptr();
|
||||
}
|
||||
else if (fallback_speed->NumberValue() <= 0)
|
||||
{
|
||||
Nan::ThrowError("fallback_speed must be > 0");
|
||||
return table_parameters_ptr();
|
||||
}
|
||||
|
||||
params->fallback_speed = static_cast<double>(fallback_speed->NumberValue());
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("fallback_coordinate").ToLocalChecked()))
|
||||
{
|
||||
auto fallback_coordinate = obj->Get(Nan::New("fallback_coordinate").ToLocalChecked());
|
||||
|
||||
if (!fallback_coordinate->IsString())
|
||||
{
|
||||
Nan::ThrowError("fallback_coordinate must be a string: [input, snapped]");
|
||||
return table_parameters_ptr();
|
||||
}
|
||||
|
||||
std::string fallback_coordinate_str = *v8::String::Utf8Value(fallback_coordinate);
|
||||
|
||||
if (fallback_coordinate_str == "snapped")
|
||||
{
|
||||
params->fallback_coordinate_type =
|
||||
osrm::TableParameters::FallbackCoordinateType::Snapped;
|
||||
}
|
||||
else if (fallback_coordinate_str == "input")
|
||||
{
|
||||
params->fallback_coordinate_type = osrm::TableParameters::FallbackCoordinateType::Input;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nan::ThrowError("'fallback_coordinate' param must be one of [input, snapped]");
|
||||
return table_parameters_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("scale_factor").ToLocalChecked()))
|
||||
{
|
||||
auto scale_factor = obj->Get(Nan::New("scale_factor").ToLocalChecked());
|
||||
|
||||
if (!scale_factor->IsNumber())
|
||||
{
|
||||
Nan::ThrowError("scale_factor must be a number");
|
||||
return table_parameters_ptr();
|
||||
}
|
||||
else if (scale_factor->NumberValue() <= 0)
|
||||
{
|
||||
Nan::ThrowError("scale_factor must be > 0");
|
||||
return table_parameters_ptr();
|
||||
}
|
||||
|
||||
params->scale_factor = static_cast<double>(scale_factor->NumberValue());
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,19 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
},
|
||||
qi::_1)];
|
||||
|
||||
acceleration_alpha_defaults_rule =
|
||||
qi::lit("car")[qi::_val = ACCELERATION_ALPHA_CAR] |
|
||||
qi::lit("fast_car")[qi::_val = ACCELERATION_ALPHA_FAST_CAR] |
|
||||
qi::lit("slow_car")[qi::_val = ACCELERATION_ALPHA_SLOW_CAR] |
|
||||
qi::lit("truck")[qi::_val = ACCELERATION_ALPHA_TRUCK] |
|
||||
qi::lit("tractor_trailer")[qi::_val = ACCELERATION_ALPHA_TRACTOR_TRAILER];
|
||||
|
||||
acceleration_profile_rule =
|
||||
qi::lit("acceleration_profile=") >
|
||||
(qi::double_ | acceleration_alpha_defaults_rule)
|
||||
[ph::bind(&engine::api::BaseParameters::waypoint_acceleration_factor, qi::_r1) =
|
||||
qi::_1];
|
||||
|
||||
query_rule =
|
||||
((location_rule % ';') | polyline_rule |
|
||||
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
|
||||
@@ -162,6 +175,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
(-approach_type %
|
||||
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
||||
|
||||
snapping_type.add("default", engine::api::BaseParameters::SnappingType::Default)(
|
||||
"any", engine::api::BaseParameters::SnappingType::Any);
|
||||
|
||||
snapping_rule =
|
||||
qi::lit("snapping=") >
|
||||
snapping_type[ph::bind(&engine::api::BaseParameters::snapping, qi::_r1) = qi::_1];
|
||||
|
||||
exclude_rule = qi::lit("exclude=") >
|
||||
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
|
||||
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
|
||||
@@ -171,13 +191,17 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
| bearings_rule(qi::_r1) //
|
||||
| generate_hints_rule(qi::_r1) //
|
||||
| approach_rule(qi::_r1) //
|
||||
| exclude_rule(qi::_r1);
|
||||
| exclude_rule(qi::_r1) //
|
||||
| snapping_rule(qi::_r1) //
|
||||
| acceleration_profile_rule(qi::_r1);//
|
||||
}
|
||||
|
||||
protected:
|
||||
qi::rule<Iterator, Signature> base_rule;
|
||||
qi::rule<Iterator, Signature> query_rule;
|
||||
|
||||
qi::real_parser<double, json_policy> double_;
|
||||
|
||||
private:
|
||||
qi::rule<Iterator, Signature> bearings_rule;
|
||||
qi::rule<Iterator, Signature> radiuses_rule;
|
||||
@@ -186,6 +210,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::rule<Iterator, Signature> generate_hints_rule;
|
||||
qi::rule<Iterator, Signature> approach_rule;
|
||||
qi::rule<Iterator, Signature> exclude_rule;
|
||||
qi::rule<Iterator, Signature> acceleration_profile_rule;
|
||||
|
||||
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
|
||||
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
|
||||
@@ -195,9 +220,12 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::rule<Iterator, unsigned char()> base64_char;
|
||||
qi::rule<Iterator, std::string()> polyline_chars;
|
||||
qi::rule<Iterator, double()> unlimited_rule;
|
||||
qi::real_parser<double, json_policy> double_;
|
||||
qi::rule<Iterator, Signature> snapping_rule;
|
||||
|
||||
qi::rule<Iterator, double()> acceleration_alpha_defaults_rule;
|
||||
|
||||
qi::symbols<char, engine::Approach> approach_type;
|
||||
qi::symbols<char, engine::api::BaseParameters::SnappingType> snapping_type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +48,28 @@ struct TableParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
||||
(qi::lit("all") |
|
||||
(size_t_ % ';')[ph::bind(&engine::api::TableParameters::sources, qi::_r1) = qi::_1]);
|
||||
|
||||
fallback_speed_rule =
|
||||
qi::lit("fallback_speed=") >
|
||||
(double_)[ph::bind(&engine::api::TableParameters::fallback_speed, qi::_r1) = qi::_1];
|
||||
|
||||
fallback_coordinate_type.add("input",
|
||||
engine::api::TableParameters::FallbackCoordinateType::Input)(
|
||||
"snapped", engine::api::TableParameters::FallbackCoordinateType::Snapped);
|
||||
|
||||
scale_factor_rule =
|
||||
qi::lit("scale_factor=") >
|
||||
(double_)[ph::bind(&engine::api::TableParameters::scale_factor, qi::_r1) = qi::_1];
|
||||
|
||||
table_rule = destinations_rule(qi::_r1) | sources_rule(qi::_r1);
|
||||
|
||||
root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
|
||||
-('?' > (table_rule(qi::_r1) | base_rule(qi::_r1)) % '&');
|
||||
-('?' > (table_rule(qi::_r1) | base_rule(qi::_r1) | scale_factor_rule(qi::_r1) |
|
||||
fallback_speed_rule(qi::_r1) |
|
||||
(qi::lit("fallback_coordinate=") >
|
||||
fallback_coordinate_type
|
||||
[ph::bind(&engine::api::TableParameters::fallback_coordinate_type,
|
||||
qi::_r1) = qi::_1])) %
|
||||
'&');
|
||||
}
|
||||
|
||||
TableParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
|
||||
@@ -73,13 +91,20 @@ struct TableParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
||||
qi::rule<Iterator, Signature> base_rule;
|
||||
|
||||
private:
|
||||
using json_policy = no_trailing_dot_policy<double, 'j', 's', 'o', 'n'>;
|
||||
|
||||
qi::rule<Iterator, Signature> root_rule;
|
||||
qi::rule<Iterator, Signature> table_rule;
|
||||
qi::rule<Iterator, Signature> sources_rule;
|
||||
qi::rule<Iterator, Signature> destinations_rule;
|
||||
qi::rule<Iterator, Signature> fallback_speed_rule;
|
||||
qi::rule<Iterator, Signature> scale_factor_rule;
|
||||
qi::rule<Iterator, std::size_t()> size_t_;
|
||||
qi::symbols<char, engine::api::TableParameters::AnnotationsType> annotations;
|
||||
qi::rule<Iterator, engine::api::TableParameters::AnnotationsType()> annotations_list;
|
||||
qi::symbols<char, engine::api::TableParameters::FallbackCoordinateType>
|
||||
fallback_coordinate_type;
|
||||
qi::real_parser<double, json_policy> double_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,8 +488,8 @@ inline void Prettify(char *buffer, int length, int k)
|
||||
inline void dtoa_milo(double value, char *buffer)
|
||||
{
|
||||
// Not handling NaN and inf
|
||||
assert(!isnan(value));
|
||||
assert(!isinf(value));
|
||||
assert(!std::isnan(value));
|
||||
assert(!std::isinf(value));
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
|
||||
@@ -116,6 +116,15 @@ static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDurati
|
||||
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
||||
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max();
|
||||
|
||||
// Recommended value for passenger vehicles from
|
||||
// https://fdotwww.blob.core.windows.net/sitefinity/docs/default-source/content/rail/publications/studies/safety/accelerationresearch.pdf?sfvrsn=716a4bb1_0
|
||||
static const double ACCELERATION_ALPHA_CAR = 6.0;
|
||||
static const double ACCELERATION_ALPHA_FAST_CAR = 18;
|
||||
static const double ACCELERATION_ALPHA_SLOW_CAR = 2;
|
||||
static const double ACCELERATION_ALPHA_TRUCK = 1.5;
|
||||
static const double ACCELERATION_ALPHA_TRACTOR_TRAILER = 0.5;
|
||||
|
||||
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
|
||||
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
|
||||
|
||||
Generated
+6732
-2897
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "osrm",
|
||||
"version": "5.20.0-latest.1",
|
||||
"version": "5.21.0-customsnapping.8",
|
||||
"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": {
|
||||
"mkdirp": "^0.5.1",
|
||||
"nan": "^2.6.2",
|
||||
"nan": "^2.11.1",
|
||||
"node-cmake": "^2.3.2",
|
||||
"node-pre-gyp": "^0.6.36",
|
||||
"node-pre-gyp": "^0.12.0",
|
||||
"rimraf": "^2.5.4"
|
||||
},
|
||||
"browserify": {
|
||||
@@ -47,14 +47,14 @@
|
||||
"csv-stringify": "^3.0.0",
|
||||
"cucumber": "^1.2.1",
|
||||
"d3-queue": "^2.0.3",
|
||||
"docbox": "^1.0.6",
|
||||
"docbox": "^1.0.11",
|
||||
"documentation": "^4.0.0-rc.1",
|
||||
"eslint": "^2.4.0",
|
||||
"eslint": "^5.10.0",
|
||||
"faucet": "^0.0.1",
|
||||
"jsonpath": "^1.0.0",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.69.0",
|
||||
"request": "^2.88.0",
|
||||
"tape": "^4.7.0",
|
||||
"turf": "^3.0.14",
|
||||
"xmlbuilder": "^4.2.1"
|
||||
|
||||
+4
-17
@@ -7,6 +7,7 @@ Sequence = require('lib/sequence')
|
||||
Handlers = require("lib/way_handlers")
|
||||
find_access_tag = require("lib/access").find_access_tag
|
||||
limit = require("lib/maxspeed").limit
|
||||
Measure = require("lib/measure")
|
||||
|
||||
function setup()
|
||||
local default_speed = 15
|
||||
@@ -206,20 +207,6 @@ function setup()
|
||||
}
|
||||
end
|
||||
|
||||
local function parse_maxspeed(source)
|
||||
if not source then
|
||||
return 0
|
||||
end
|
||||
local n = tonumber(source:match("%d*"))
|
||||
if not n then
|
||||
n = 0
|
||||
end
|
||||
if string.match(source, "mph") or string.match(source, "mp/h") then
|
||||
n = (n*1609)/1000
|
||||
end
|
||||
return n
|
||||
end
|
||||
|
||||
function process_node(profile, node, result)
|
||||
-- parse access and barrier tags
|
||||
local highway = node:get_value_by_key("highway")
|
||||
@@ -276,9 +263,9 @@ function handle_bicycle_tags(profile,way,result,data)
|
||||
|
||||
-- other tags
|
||||
data.junction = way:get_value_by_key("junction")
|
||||
data.maxspeed = parse_maxspeed(way:get_value_by_key ( "maxspeed") )
|
||||
data.maxspeed_forward = parse_maxspeed(way:get_value_by_key( "maxspeed:forward"))
|
||||
data.maxspeed_backward = parse_maxspeed(way:get_value_by_key( "maxspeed:backward"))
|
||||
data.maxspeed = Measure.get_max_speed(way:get_value_by_key ("maxspeed")) or 0
|
||||
data.maxspeed_forward = Measure.get_max_speed(way:get_value_by_key("maxspeed:forward")) or 0
|
||||
data.maxspeed_backward = Measure.get_max_speed(way:get_value_by_key("maxspeed:backward")) or 0
|
||||
data.barrier = way:get_value_by_key("barrier")
|
||||
data.oneway = way:get_value_by_key("oneway")
|
||||
data.oneway_bicycle = way:get_value_by_key("oneway:bicycle")
|
||||
|
||||
@@ -269,6 +269,7 @@ function setup()
|
||||
["at:rural"] = 100,
|
||||
["at:trunk"] = 100,
|
||||
["be:motorway"] = 120,
|
||||
["be-vlg:rural"] = 70,
|
||||
["by:urban"] = 60,
|
||||
["by:motorway"] = 110,
|
||||
["ch:rural"] = 80,
|
||||
|
||||
@@ -6,6 +6,18 @@ Measure = {}
|
||||
local inch_to_meters = 0.0254
|
||||
local feet_to_inches = 12
|
||||
local pound_to_kilograms = 0.45359237
|
||||
local miles_to_kilometers = 1.609
|
||||
|
||||
-- Parse speed value as kilometers by hours.
|
||||
function Measure.parse_value_speed(source)
|
||||
local n = tonumber(source:match("%d*"))
|
||||
if n then
|
||||
if string.match(source, "mph") or string.match(source, "mp/h") then
|
||||
n = n * miles_to_kilometers
|
||||
end
|
||||
return n
|
||||
end
|
||||
end
|
||||
|
||||
--- Parse string as a height in meters.
|
||||
--- according to http://wiki.openstreetmap.org/wiki/Key:maxheight
|
||||
@@ -42,6 +54,13 @@ function Measure.parse_value_kilograms(value)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get maxspeed of specified way in kilometers by hours.
|
||||
function Measure.get_max_speed(raw_value)
|
||||
if raw_value then
|
||||
return Measure.parse_value_speed(raw_value)
|
||||
end
|
||||
end
|
||||
|
||||
-- default maxheight value defined in https://wiki.openstreetmap.org/wiki/Key:maxheight#Non-numerical_values
|
||||
local default_maxheight = 4.5
|
||||
-- Available Non numerical values equal to 4.5; below_default and no_indications are not considered
|
||||
|
||||
@@ -432,7 +432,7 @@ end
|
||||
|
||||
-- maxspeed and advisory maxspeed
|
||||
function WayHandlers.maxspeed(profile,way,result,data)
|
||||
local keys = Sequence { 'maxspeed:advisory', 'maxspeed' }
|
||||
local keys = Sequence { 'maxspeed:advisory', 'maxspeed', 'source:maxspeed', 'maxspeed:type' }
|
||||
local forward, backward = Tags.get_forward_backward_by_set(way,data,keys)
|
||||
forward = WayHandlers.parse_maxspeed(forward,profile)
|
||||
backward = WayHandlers.parse_maxspeed(backward,profile)
|
||||
@@ -450,12 +450,9 @@ function WayHandlers.parse_maxspeed(source,profile)
|
||||
if not source then
|
||||
return 0
|
||||
end
|
||||
local n = tonumber(source:match("%d*"))
|
||||
if n then
|
||||
if string.match(source, "mph") or string.match(source, "mp/h") then
|
||||
n = (n*1609)/1000
|
||||
end
|
||||
else
|
||||
|
||||
local n = Measure.get_max_speed(source)
|
||||
if not n then
|
||||
-- parse maxspeed like FR:urban
|
||||
source = string.lower(source)
|
||||
n = profile.maxspeed_table[source]
|
||||
|
||||
@@ -94,7 +94,7 @@ std::string waypointTypeToString(const guidance::WaypointType waypoint_type)
|
||||
return waypoint_type_names[static_cast<std::size_t>(waypoint_type)];
|
||||
}
|
||||
|
||||
util::json::Array coordinateToLonLat(const util::Coordinate coordinate)
|
||||
util::json::Array coordinateToLonLat(const util::Coordinate &coordinate)
|
||||
{
|
||||
util::json::Array array;
|
||||
array.values.push_back(static_cast<double>(util::toFloating(coordinate.lon)));
|
||||
@@ -240,17 +240,22 @@ util::json::Object makeRoute(const guidance::Route &route,
|
||||
return json_route;
|
||||
}
|
||||
|
||||
util::json::Object makeWaypoint(const util::Coordinate location, std::string name)
|
||||
util::json::Object
|
||||
makeWaypoint(const util::Coordinate &location, const double &distance, std::string name)
|
||||
{
|
||||
util::json::Object waypoint;
|
||||
waypoint.values["location"] = detail::coordinateToLonLat(location);
|
||||
waypoint.values["name"] = std::move(name);
|
||||
waypoint.values["distance"] = distance;
|
||||
return waypoint;
|
||||
}
|
||||
|
||||
util::json::Object makeWaypoint(const util::Coordinate location, std::string name, const Hint &hint)
|
||||
util::json::Object makeWaypoint(const util::Coordinate &location,
|
||||
const double &distance,
|
||||
std::string name,
|
||||
const Hint &hint)
|
||||
{
|
||||
auto waypoint = makeWaypoint(location, name);
|
||||
auto waypoint = makeWaypoint(location, distance, name);
|
||||
waypoint.values["hint"] = hint.ToBase64();
|
||||
return waypoint;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,8 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
});
|
||||
}
|
||||
|
||||
auto candidates_lists = GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses);
|
||||
auto candidates_lists =
|
||||
GetPhantomNodesInRange(facade, tidied.parameters, search_radiuses, true);
|
||||
|
||||
filterCandidates(tidied.parameters.coordinates, candidates_lists);
|
||||
if (std::all_of(candidates_lists.begin(),
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "engine/api/table_parameters.hpp"
|
||||
#include "engine/routing_algorithms/many_to_many.hpp"
|
||||
#include "engine/search_engine_data.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/json_container.hpp"
|
||||
#include "util/string_util.hpp"
|
||||
|
||||
@@ -85,8 +86,11 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
bool request_distance = params.annotations & api::TableParameters::AnnotationsType::Distance;
|
||||
bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration;
|
||||
|
||||
// Because of the Short Trip ETA adjustments below, we need distances every time
|
||||
const bool distances_required = request_distance || params.waypoint_acceleration_factor > 0.;
|
||||
|
||||
auto result_tables_pair = algorithms.ManyToManySearch(
|
||||
snapped_phantoms, params.sources, params.destinations, request_distance);
|
||||
snapped_phantoms, params.sources, params.destinations, distances_required);
|
||||
|
||||
if ((request_duration && result_tables_pair.first.empty()) ||
|
||||
(request_distance && result_tables_pair.second.empty()))
|
||||
@@ -94,8 +98,148 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
return Error("NoTable", "No table found", result);
|
||||
}
|
||||
|
||||
std::vector<api::TableAPI::TableCellRef> estimated_pairs;
|
||||
|
||||
// Adds some time to adjust for getting up to speed and slowing down to a stop
|
||||
// Returns a new `duration`
|
||||
auto adjust_for_startstop = [&](const double &acceleration_alpha,
|
||||
const EdgeDuration &duration,
|
||||
const EdgeDistance &distance) -> EdgeDuration {
|
||||
|
||||
// Very short paths can end up with 0 duration. That'll lead to a divide
|
||||
// by zero, so instead, we'll assume the travel speed is 10m/s (36km/h).
|
||||
// Typically, the distance is also short, so we're quibbling at tiny numbers
|
||||
// here, but tiny numbers is what this adjustment lambda is all about,
|
||||
// so we do try to be reasonable.
|
||||
const auto average_speed =
|
||||
duration == 0 ? 10 : distance /
|
||||
(duration / 10.); // duration is in deciseconds, we need m/sec
|
||||
|
||||
// The following reference has a nice model (equations 9 through 12)
|
||||
// for vehicle acceleration
|
||||
// https://fdotwww.blob.core.windows.net/sitefinity/docs/default-source/content/rail/publications/studies/safety/accelerationresearch.pdf?sfvrsn=716a4bb1_0
|
||||
// We solve euqation 10 for time to figure out how long it'll take
|
||||
// to get up to the desired speed
|
||||
|
||||
// Because Equation 10 is asymptotic on v_des, we need to pick a target speed
|
||||
// that's slighly less so the equation can actually get there. 1m/s less than
|
||||
// target seems like a reasonable value to aim for
|
||||
const auto target_speed = std::max(average_speed - 1, 0.1);
|
||||
const auto initial_speed = 0.;
|
||||
|
||||
// Equation 9
|
||||
const auto beta = acceleration_alpha / average_speed;
|
||||
|
||||
// Equation 10 solved for time
|
||||
const auto time_to_full_speed = std::log( (average_speed - initial_speed) / (average_speed - target_speed) ) / beta;
|
||||
BOOST_ASSERT(time_to_full_speed >= 0);
|
||||
|
||||
// Equation 11
|
||||
const auto distance_to_full_speed =
|
||||
average_speed * time_to_full_speed -
|
||||
average_speed * (1 - std::exp(-1 * beta * time_to_full_speed)) / beta;
|
||||
|
||||
BOOST_ASSERT(distance_to_full_speed >= 0);
|
||||
|
||||
if (distance_to_full_speed > distance / 2)
|
||||
{
|
||||
// Because equation 12 requires velocity at halfway, and
|
||||
// solving equation 11 for t requires a Lambert W function,
|
||||
// we'll approximate here by assuming constant acceleration
|
||||
// over distance_to_full_speed using s = ut + 1/2at^2
|
||||
const auto average_acceleration =
|
||||
2 * distance_to_full_speed / (time_to_full_speed * time_to_full_speed);
|
||||
const auto time_to_halfway = std::sqrt(distance / average_acceleration);
|
||||
BOOST_ASSERT(time_to_halfway >= 0);
|
||||
return (2 * time_to_halfway) * 10; // result is in deciseconds
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto cruising_distance = distance - 2 * distance_to_full_speed;
|
||||
const auto cruising_time = cruising_distance / average_speed;
|
||||
BOOST_ASSERT(cruising_time >= 0);
|
||||
return (cruising_time + 2 * time_to_full_speed) * 10; // result is in deciseconds
|
||||
}
|
||||
};
|
||||
|
||||
// Scan table for null results - if any exist, replace with distance estimates
|
||||
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1 ||
|
||||
params.waypoint_acceleration_factor != 0.)
|
||||
{
|
||||
for (std::size_t row = 0; row < num_sources; row++)
|
||||
{
|
||||
for (std::size_t column = 0; column < num_destinations; column++)
|
||||
{
|
||||
const auto &table_index = row * num_destinations + column;
|
||||
BOOST_ASSERT(table_index < result_tables_pair.first.size());
|
||||
// apply an accel/deceleration penalty to the duration
|
||||
if (result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
||||
row != column && params.waypoint_acceleration_factor != 0.)
|
||||
{
|
||||
result_tables_pair.first[table_index] =
|
||||
adjust_for_startstop(params.waypoint_acceleration_factor,
|
||||
result_tables_pair.first[table_index],
|
||||
result_tables_pair.second[table_index]);
|
||||
}
|
||||
// Estimate null results based on fallback_speed (if valid) and distance
|
||||
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
|
||||
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
|
||||
{
|
||||
const auto &source =
|
||||
snapped_phantoms[params.sources.empty() ? row : params.sources[row]];
|
||||
const auto &destination =
|
||||
snapped_phantoms[params.destinations.empty() ? column
|
||||
: params.destinations[column]];
|
||||
|
||||
auto distance_estimate =
|
||||
params.fallback_coordinate_type ==
|
||||
api::TableParameters::FallbackCoordinateType::Input
|
||||
? util::coordinate_calculation::fccApproximateDistance(
|
||||
source.input_location, destination.input_location)
|
||||
: util::coordinate_calculation::fccApproximateDistance(
|
||||
source.location, destination.location);
|
||||
|
||||
result_tables_pair.first[table_index] =
|
||||
distance_estimate / (double)params.fallback_speed;
|
||||
if (!result_tables_pair.second.empty())
|
||||
{
|
||||
result_tables_pair.second[table_index] = distance_estimate;
|
||||
}
|
||||
|
||||
estimated_pairs.emplace_back(row, column);
|
||||
}
|
||||
// Apply a scale factor to non-null result if requested
|
||||
if (params.scale_factor > 0 && params.scale_factor != 1 &&
|
||||
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
||||
result_tables_pair.first[table_index] != 0)
|
||||
{
|
||||
EdgeDuration diff =
|
||||
MAXIMAL_EDGE_DURATION / result_tables_pair.first[table_index];
|
||||
|
||||
if (params.scale_factor >= diff)
|
||||
{
|
||||
result_tables_pair.first[table_index] = MAXIMAL_EDGE_DURATION - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_tables_pair.first[table_index] = std::lround(
|
||||
result_tables_pair.first[table_index] * params.scale_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If distances weren't requested, delete them from the result so they don't
|
||||
// get rendered.
|
||||
if (!request_distance)
|
||||
{
|
||||
std::vector<EdgeDistance> empty;
|
||||
result_tables_pair.second.swap(empty);
|
||||
}
|
||||
|
||||
api::TableAPI table_api{facade, params};
|
||||
table_api.MakeResponse(result_tables_pair, snapped_phantoms, result);
|
||||
table_api.MakeResponse(result_tables_pair, snapped_phantoms, estimated_pairs, result);
|
||||
|
||||
return Status::Ok;
|
||||
}
|
||||
|
||||
@@ -294,6 +294,7 @@ struct SpeedLayer : public vtzero::layer_builder
|
||||
vtzero::index_value key_duration;
|
||||
vtzero::index_value key_name;
|
||||
vtzero::index_value key_rate;
|
||||
vtzero::index_value key_is_startpoint;
|
||||
|
||||
SpeedLayer(vtzero::tile_builder &tile)
|
||||
: layer_builder(tile, "speeds"), uint_index(*this), double_index(*this),
|
||||
@@ -302,7 +303,8 @@ struct SpeedLayer : public vtzero::layer_builder
|
||||
key_datasource(add_key_without_dup_check("datasource")),
|
||||
key_weight(add_key_without_dup_check("weight")),
|
||||
key_duration(add_key_without_dup_check("duration")),
|
||||
key_name(add_key_without_dup_check("name")), key_rate(add_key_without_dup_check("rate"))
|
||||
key_name(add_key_without_dup_check("name")), key_rate(add_key_without_dup_check("rate")),
|
||||
key_is_startpoint(add_key_without_dup_check("is_startpoint"))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -349,6 +351,11 @@ class SpeedLayerFeatureBuilder : public vtzero::linestring_feature_builder
|
||||
|
||||
void set_rate(double value) { add_property(m_layer.key_rate, m_layer.double_index(value)); }
|
||||
|
||||
void set_is_startpoint(bool value)
|
||||
{
|
||||
add_property(m_layer.key_is_startpoint, m_layer.bool_index(value));
|
||||
}
|
||||
|
||||
}; // class SpeedLayerFeatureBuilder
|
||||
|
||||
struct TurnsLayer : public vtzero::layer_builder
|
||||
@@ -485,6 +492,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
const auto reverse_datasource_idx = reverse_datasource_range(
|
||||
reverse_datasource_range.size() - edge.fwd_segment_position - 1);
|
||||
|
||||
const auto is_startpoint = edge.is_startpoint;
|
||||
|
||||
const auto component_id = facade.GetComponentID(edge.forward_segment_id.id);
|
||||
const auto name_id = facade.GetNameIndex(edge.forward_segment_id.id);
|
||||
auto name = facade.GetNameForID(name_id);
|
||||
@@ -516,6 +525,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
fbuilder.set_duration(forward_duration / 10.0);
|
||||
fbuilder.set_name(name);
|
||||
fbuilder.set_rate(forward_rate / 10.0);
|
||||
fbuilder.set_is_startpoint(is_startpoint);
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
@@ -549,6 +559,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
fbuilder.set_duration(reverse_duration / 10.0);
|
||||
fbuilder.set_name(name);
|
||||
fbuilder.set_rate(reverse_rate / 10.0);
|
||||
fbuilder.set_is_startpoint(is_startpoint);
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
@@ -143,7 +143,8 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
||||
}
|
||||
}
|
||||
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
|
||||
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration) &&
|
||||
new_distance >= 0)
|
||||
{
|
||||
current_weight = new_weight;
|
||||
current_duration = new_duration;
|
||||
|
||||
@@ -95,12 +95,6 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSe
|
||||
swap(nodes, m_edge_based_node_segments);
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetStartPointMarkers(std::vector<bool> &node_is_startpoint)
|
||||
{
|
||||
using std::swap; // Koenig swap
|
||||
swap(m_edge_based_node_is_startpoint, node_is_startpoint);
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights)
|
||||
{
|
||||
using std::swap; // Koenig swap
|
||||
@@ -229,10 +223,9 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
|
||||
edge_id_to_segment_id(nbe_to_ebn_mapping[edge_id_2]),
|
||||
current_edge_source_coordinate_id,
|
||||
current_edge_target_coordinate_id,
|
||||
i);
|
||||
i,
|
||||
forward_data.flags.startpoint || reverse_data.flags.startpoint);
|
||||
|
||||
m_edge_based_node_is_startpoint.push_back(forward_data.flags.startpoint ||
|
||||
reverse_data.flags.startpoint);
|
||||
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
|
||||
}
|
||||
|
||||
@@ -427,7 +420,6 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(m_edge_based_node_segments.size() == m_edge_based_node_is_startpoint.size());
|
||||
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_weights.size());
|
||||
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_durations.size());
|
||||
BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_distances.size());
|
||||
|
||||
@@ -239,7 +239,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
EdgeBasedNodeDataContainer edge_based_nodes_container;
|
||||
std::vector<EdgeBasedNodeSegment> edge_based_node_segments;
|
||||
util::DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
|
||||
std::vector<bool> node_is_startpoint;
|
||||
std::vector<EdgeWeight> edge_based_node_weights;
|
||||
std::vector<EdgeDuration> edge_based_node_durations;
|
||||
std::vector<EdgeDistance> edge_based_node_distances;
|
||||
@@ -320,7 +319,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
scripting_environment,
|
||||
edge_based_nodes_container,
|
||||
edge_based_node_segments,
|
||||
node_is_startpoint,
|
||||
edge_based_node_weights,
|
||||
edge_based_node_durations,
|
||||
edge_based_node_distances,
|
||||
@@ -362,7 +360,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
|
||||
util::Log() << "Building r-tree ...";
|
||||
TIMER_START(rtree);
|
||||
BuildRTree(std::move(edge_based_node_segments), std::move(node_is_startpoint), coordinates);
|
||||
BuildRTree(std::move(edge_based_node_segments), coordinates);
|
||||
|
||||
TIMER_STOP(rtree);
|
||||
|
||||
@@ -737,7 +735,6 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
||||
// output data
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
std::vector<EdgeDuration> &edge_based_node_durations,
|
||||
std::vector<EdgeDistance> &edge_based_node_distances,
|
||||
@@ -788,7 +785,6 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
||||
|
||||
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
||||
edge_based_graph_factory.GetEdgeBasedNodeSegments(edge_based_node_segments);
|
||||
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
||||
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
|
||||
edge_based_graph_factory.GetEdgeBasedNodeDurations(edge_based_node_durations);
|
||||
edge_based_graph_factory.GetEdgeBasedNodeDistances(edge_based_node_distances);
|
||||
@@ -803,35 +799,24 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
||||
Saves tree into '.ramIndex' and leaves into '.fileIndex'.
|
||||
*/
|
||||
void Extractor::BuildRTree(std::vector<EdgeBasedNodeSegment> edge_based_node_segments,
|
||||
std::vector<bool> node_is_startpoint,
|
||||
const std::vector<util::Coordinate> &coordinates)
|
||||
{
|
||||
util::Log() << "Constructing r-tree of " << edge_based_node_segments.size()
|
||||
<< " segments build on-top of " << coordinates.size() << " coordinates";
|
||||
|
||||
BOOST_ASSERT(node_is_startpoint.size() == edge_based_node_segments.size());
|
||||
|
||||
// Filter node based edges based on startpoint
|
||||
auto out_iter = edge_based_node_segments.begin();
|
||||
auto in_iter = edge_based_node_segments.begin();
|
||||
for (auto index : util::irange<std::size_t>(0UL, node_is_startpoint.size()))
|
||||
{
|
||||
BOOST_ASSERT(in_iter != edge_based_node_segments.end());
|
||||
if (node_is_startpoint[index])
|
||||
{
|
||||
*out_iter = *in_iter;
|
||||
out_iter++;
|
||||
}
|
||||
in_iter++;
|
||||
}
|
||||
auto new_size = out_iter - edge_based_node_segments.begin();
|
||||
if (new_size == 0)
|
||||
auto start_point_count = std::accumulate(edge_based_node_segments.begin(),
|
||||
edge_based_node_segments.end(),
|
||||
0,
|
||||
[](const size_t so_far, const auto &segment) {
|
||||
return so_far + (segment.is_startpoint ? 1 : 0);
|
||||
});
|
||||
if (start_point_count == 0)
|
||||
{
|
||||
throw util::exception("There are no snappable edges left after processing. Are you "
|
||||
"setting travel modes correctly in the profile? Cannot continue." +
|
||||
SOURCE_REF);
|
||||
}
|
||||
edge_based_node_segments.resize(new_size);
|
||||
|
||||
TIMER_START(construction);
|
||||
util::StaticRTree<EdgeBasedNodeSegment> rtree(
|
||||
|
||||
@@ -56,6 +56,16 @@ std::string getWrongOptionHelp(const engine::api::TableParameters ¶meters)
|
||||
help = "Number of coordinates needs to be at least two.";
|
||||
}
|
||||
|
||||
if (parameters.fallback_speed <= 0)
|
||||
{
|
||||
help = "fallback_speed must be > 0";
|
||||
}
|
||||
|
||||
if (parameters.scale_factor <= 0)
|
||||
{
|
||||
help = "scale_factor must be > 0";
|
||||
}
|
||||
|
||||
return help;
|
||||
}
|
||||
} // anon. ns
|
||||
|
||||
@@ -153,7 +153,7 @@ double perpendicularDistance(const Coordinate segment_source,
|
||||
web_mercator::fromWGS84(query_location));
|
||||
nearest_location = web_mercator::toWGS84(projected_nearest);
|
||||
|
||||
const double approximate_distance = greatCircleDistance(query_location, nearest_location);
|
||||
const double approximate_distance = fccApproximateDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0.0 <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
{"key": "maxspeed", "value": "AT:rural"},
|
||||
{"key": "maxspeed", "value": "AT:trunk"},
|
||||
{"key": "maxspeed", "value": "BE:motorway"},
|
||||
{"key": "maxspeed", "value": "BE-VLG:rural"},
|
||||
{"key": "maxspeed", "value": "BY:urban"},
|
||||
{"key": "maxspeed", "value": "BY:motorway"},
|
||||
{"key": "maxspeed", "value": "CH:rural"},
|
||||
|
||||
@@ -10,7 +10,7 @@ exports.three_test_coordinates = [[7.41337, 43.72956],
|
||||
|
||||
exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2)
|
||||
|
||||
exports.test_tile = {'at': [17059, 11948, 15], 'size': 148750};
|
||||
exports.test_tile = {'at': [17059, 11948, 15], 'size': 156624};
|
||||
|
||||
// Test files generated by the routing engine; check test/data
|
||||
if (process.env.OSRM_DATA_PATH !== undefined) {
|
||||
|
||||
@@ -606,3 +606,23 @@ test('route: route in Monaco without motorways', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('route: throws on invalid snapping values', function (assert) {
|
||||
assert.plan(1);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
var options = {
|
||||
steps: true,
|
||||
coordinates: three_test_coordinates.concat(three_test_coordinates),
|
||||
snapping: "zing"
|
||||
};
|
||||
assert.throws(function () { osrm.route(options, function (err, response) { console.error(`response: ${response}`); console.error(`error: ${err}`); }); },
|
||||
/'snapping' param must be one of \[default, any\]/);
|
||||
});
|
||||
|
||||
test('route: snapping parameter passed through OK', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(monaco_path);
|
||||
osrm.route({snapping: "any", coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]]}, function(err, route) {
|
||||
assert.ifError(err);
|
||||
assert.equal(Math.round(route.routes[0].distance * 10), 1314); // Round it to nearest 0.1m to eliminate floating point comparison error
|
||||
});
|
||||
});
|
||||
+115
-1
@@ -48,6 +48,21 @@ test('table: test annotations paramater combination', function(assert) {
|
||||
});
|
||||
});
|
||||
|
||||
test('table: snapping parameter passed through OK', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM(data_path);
|
||||
var options = {
|
||||
coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]],
|
||||
annotations: ['duration', 'distance'],
|
||||
snapping: 'any'
|
||||
};
|
||||
console.log(options);
|
||||
osrm.table(options, function(err, result) {
|
||||
assert.ifError(err);
|
||||
assert.equal(Math.round(result.distances[0][1] * 10), 1315); // Round it to nearest 0.1m to eliminate floating point comparison error
|
||||
});
|
||||
});
|
||||
|
||||
test('table: returns buffer', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM(data_path);
|
||||
@@ -234,7 +249,7 @@ tables.forEach(function(annotation) {
|
||||
});
|
||||
|
||||
test('table: ' + annotation + ' table in Monaco without motorways', function(assert) {
|
||||
assert.plan(1);
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||
var options = {
|
||||
coordinates: two_test_coordinates,
|
||||
@@ -243,7 +258,106 @@ tables.forEach(function(annotation) {
|
||||
};
|
||||
osrm.table(options, function(err, response) {
|
||||
assert.equal(response[annotation].length, 2);
|
||||
assert.strictEqual(response.fallback_speed_cells, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('table: ' + annotation + ' table in Monaco with fallback speeds', function(assert) {
|
||||
assert.plan(2);
|
||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||
var options = {
|
||||
coordinates: two_test_coordinates,
|
||||
annotations: [annotation.slice(0,-1)],
|
||||
fallback_speed: 1,
|
||||
fallback_coordinate: 'input'
|
||||
};
|
||||
osrm.table(options, function(err, response) {
|
||||
assert.equal(response[annotation].length, 2);
|
||||
assert.equal(response['fallback_speed_cells'].length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('table: ' + annotation + ' table in Monaco with invalid fallback speeds and fallback coordinates', function(assert) {
|
||||
assert.plan(4);
|
||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||
var options = {
|
||||
coordinates: two_test_coordinates,
|
||||
annotations: [annotation.slice(0,-1)],
|
||||
fallback_speed: -1
|
||||
};
|
||||
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /fallback_speed must be > 0/, "should throw on invalid fallback_speeds");
|
||||
|
||||
options.fallback_speed = '10';
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /fallback_speed must be a number/, "should throw on invalid fallback_speeds");
|
||||
|
||||
options.fallback_speed = 10;
|
||||
options.fallback_coordinate = 'bla';
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /fallback_coordinate' param must be one of \[input, snapped\]/, "should throw on invalid fallback_coordinate");
|
||||
|
||||
options.fallback_coordinate = 10;
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /fallback_coordinate must be a string: \[input, snapped\]/, "should throw on invalid fallback_coordinate");
|
||||
|
||||
});
|
||||
|
||||
test('table: ' + annotation + ' table in Monaco with invalid scale factor', function(assert) {
|
||||
assert.plan(3);
|
||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||
var options = {
|
||||
coordinates: two_test_coordinates,
|
||||
annotations: [annotation.slice(0,-1)],
|
||||
scale_factor: -1
|
||||
};
|
||||
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be > 0/, "should throw on invalid scale_factor value");
|
||||
|
||||
options.scale_factor = '-1';
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be a number/, "should throw on invalid scale_factor value");
|
||||
|
||||
options.scale_factor = 0;
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be > 0/, "should throw on invalid scale_factor value");
|
||||
|
||||
});
|
||||
|
||||
test('table: ' + annotation + ' table in Monaco with start_stop_acceleration_factor values', function(assert) {
|
||||
assert.plan(12);
|
||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||
var options = {
|
||||
coordinates: two_test_coordinates,
|
||||
annotations: [annotation.slice(0,-1)],
|
||||
acceleration_profile: []
|
||||
};
|
||||
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on empty array");
|
||||
|
||||
options.start_stop_acceleration_factor = 'a';
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-numeric value");
|
||||
|
||||
options.start_stop_acceleration_factor = [1];
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-numeric value");
|
||||
|
||||
options.start_stop_acceleration_factor = -0.1;
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-numeric value");
|
||||
|
||||
options.start_stop_acceleration_factor = 0.;
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "should work with zero");
|
||||
|
||||
options.start_stop_acceleration_factor = 2.0;
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with positive numeric values");
|
||||
options.start_stop_acceleration_factor = 'car';
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with car defaults");
|
||||
options.start_stop_acceleration_factor = 'fast_car';
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with fast car defaults");
|
||||
options.start_stop_acceleration_factor = 'slow_car';
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with slow car defaults");
|
||||
options.start_stop_acceleration_factor = 'truck';
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with truck defaults");
|
||||
options.start_stop_acceleration_factor = 'tractor_trailer';
|
||||
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with tractor trailer defaults");
|
||||
|
||||
options.start_stop_acceleration_factor = 'yes';
|
||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-recognized string");
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -229,7 +229,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
const float /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/) const override
|
||||
const Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -237,7 +238,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
|
||||
const float /*max_distance*/,
|
||||
const Approach /*approach*/) const override
|
||||
const Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -282,7 +284,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const Approach /*approach*/) const override
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -290,7 +293,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const Approach /*approach*/) const override
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -300,7 +304,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
const double /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/) const override
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -309,7 +314,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/) const override
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "coordinates.hpp"
|
||||
#include "equal_json.hpp"
|
||||
#include "fixture.hpp"
|
||||
@@ -32,18 +34,28 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
|
||||
|
||||
// unset snapping dependent hint
|
||||
for (auto &itr : result.values["waypoints"].get<json::Array>().values)
|
||||
{
|
||||
// Hint values aren't stable, so blank it out
|
||||
itr.get<json::Object>().values["hint"] = "";
|
||||
|
||||
// Round value to 6 decimal places for double comparison later
|
||||
itr.get<json::Object>().values["distance"] =
|
||||
round(itr.get<json::Object>().values["distance"].get<json::Number>().value * 1000000);
|
||||
}
|
||||
|
||||
const auto location = json::Array{{{7.437070}, {43.749248}}};
|
||||
|
||||
json::Object reference{
|
||||
{{"code", "Ok"},
|
||||
{"waypoints",
|
||||
json::Array{
|
||||
{json::Object{
|
||||
{{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}},
|
||||
json::Object{
|
||||
{{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}}}}},
|
||||
json::Array{{json::Object{{{"name", "Boulevard du Larvotto"},
|
||||
{"location", location},
|
||||
{"distance", round(0.137249 * 1000000)},
|
||||
{"hint", ""}}},
|
||||
json::Object{{{"name", "Boulevard du Larvotto"},
|
||||
{"location", location},
|
||||
{"distance", round(0.137249 * 1000000)},
|
||||
{"hint", ""}}}}}},
|
||||
{"routes",
|
||||
json::Array{{json::Object{
|
||||
{{"distance", 0.},
|
||||
|
||||
@@ -36,7 +36,7 @@ void validate_feature_layer(vtzero::layer layer)
|
||||
BOOST_CHECK_EQUAL(layer.version(), 2);
|
||||
BOOST_CHECK_EQUAL(to_string(layer.name()), "speeds");
|
||||
BOOST_CHECK_EQUAL(layer.extent(), osrm::util::vector_tile::EXTENT);
|
||||
BOOST_CHECK_EQUAL(layer.key_table().size(), 7);
|
||||
BOOST_CHECK_EQUAL(layer.key_table().size(), 8);
|
||||
BOOST_CHECK(layer.num_features() > 2500);
|
||||
|
||||
while (auto feature = layer.next_feature())
|
||||
@@ -62,6 +62,9 @@ void validate_feature_layer(vtzero::layer layer)
|
||||
BOOST_CHECK(props.find("is_small") != props.end());
|
||||
BOOST_CHECK(props["is_small"].type() == typeid(bool));
|
||||
|
||||
BOOST_CHECK(props.find("is_startpoint") != props.end());
|
||||
BOOST_CHECK(props["is_startpoint"].type() == typeid(bool));
|
||||
|
||||
BOOST_CHECK(props.find("datasource") != props.end());
|
||||
BOOST_CHECK(props["datasource"].type() == typeid(std::string));
|
||||
|
||||
@@ -73,7 +76,7 @@ void validate_feature_layer(vtzero::layer layer)
|
||||
std::count_if(layer.value_table().begin(), layer.value_table().end(), [](auto v) {
|
||||
return v.type() == vtzero::property_value_type::uint_value;
|
||||
});
|
||||
BOOST_CHECK_EQUAL(number_of_uint_values, 77);
|
||||
BOOST_CHECK_EQUAL(number_of_uint_values, 78);
|
||||
}
|
||||
|
||||
void validate_turn_layer(vtzero::layer layer)
|
||||
@@ -125,7 +128,7 @@ void validate_node_layer(vtzero::layer layer)
|
||||
BOOST_CHECK_EQUAL(to_string(layer.name()), "osmnodes");
|
||||
BOOST_CHECK_EQUAL(layer.extent(), osrm::util::vector_tile::EXTENT);
|
||||
BOOST_CHECK_EQUAL(layer.key_table().size(), 0);
|
||||
BOOST_CHECK_EQUAL(layer.num_features(), 1791);
|
||||
BOOST_CHECK_EQUAL(layer.num_features(), 1810);
|
||||
|
||||
while (auto feature = layer.next_feature())
|
||||
{
|
||||
|
||||
@@ -113,7 +113,8 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
||||
const float /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -121,7 +122,8 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
||||
std::vector<engine::PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
|
||||
const float /*max_distance*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -165,39 +167,39 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
||||
}
|
||||
|
||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate /*input_coordinate*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate /*input_coordinate*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -89,6 +89,25 @@ BOOST_AUTO_TEST_CASE(invalid_table_urls)
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?sources=all&destinations=all&annotations=bla"),
|
||||
49UL);
|
||||
BOOST_CHECK_EQUAL(testInvalidOptions<TableParameters>("1,2;3,4?fallback_coordinate=asdf"),
|
||||
28UL);
|
||||
BOOST_CHECK_EQUAL(testInvalidOptions<TableParameters>("1,2;3,4?fallback_coordinate=10"), 28UL);
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?annotations=durations&scale_factor=-1"), 28UL);
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?annotations=durations&scale_factor=0"), 28UL);
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?annotations=durations&fallback_speed=0"),
|
||||
28UL);
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?annotations=durations&fallback_speed=-1"),
|
||||
28UL);
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?annotations=durations&fallback_speed=0"),
|
||||
28UL);
|
||||
BOOST_CHECK_EQUAL(
|
||||
testInvalidOptions<TableParameters>("1,2;3,4?annotations=durations&fallback_speed=-1"),
|
||||
28UL);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(valid_route_hint)
|
||||
@@ -563,6 +582,44 @@ BOOST_AUTO_TEST_CASE(valid_table_urls)
|
||||
BOOST_CHECK_EQUAL(result_7->annotations & TableParameters::AnnotationsType::Distance, true);
|
||||
CHECK_EQUAL_RANGE(reference_7.sources, result_7->sources);
|
||||
CHECK_EQUAL_RANGE(reference_7.destinations, result_7->destinations);
|
||||
|
||||
TableParameters reference_8{};
|
||||
reference_8.coordinates = coords_1;
|
||||
auto result_8 =
|
||||
parseParameters<TableParameters>("1,2;3,4?annotations=distance&fallback_speed=2.5");
|
||||
BOOST_CHECK(result_8);
|
||||
BOOST_CHECK_EQUAL(result_8->annotations & TableParameters::AnnotationsType::Distance, true);
|
||||
CHECK_EQUAL_RANGE(reference_8.sources, result_8->sources);
|
||||
CHECK_EQUAL_RANGE(reference_8.destinations, result_8->destinations);
|
||||
|
||||
TableParameters reference_9{};
|
||||
reference_9.coordinates = coords_1;
|
||||
auto result_9 = parseParameters<TableParameters>(
|
||||
"1,2;3,4?annotations=distance&fallback_speed=2.5&fallback_coordinate=input");
|
||||
BOOST_CHECK(result_9);
|
||||
BOOST_CHECK_EQUAL(result_9->annotations & TableParameters::AnnotationsType::Distance, true);
|
||||
CHECK_EQUAL_RANGE(reference_9.sources, result_9->sources);
|
||||
CHECK_EQUAL_RANGE(reference_9.destinations, result_9->destinations);
|
||||
|
||||
TableParameters reference_10{};
|
||||
reference_10.coordinates = coords_1;
|
||||
auto result_10 = parseParameters<TableParameters>(
|
||||
"1,2;3,4?annotations=distance&fallback_speed=20&fallback_coordinate=snapped");
|
||||
BOOST_CHECK(result_10);
|
||||
BOOST_CHECK_EQUAL(result_10->annotations & TableParameters::AnnotationsType::Distance, true);
|
||||
CHECK_EQUAL_RANGE(reference_10.sources, result_10->sources);
|
||||
CHECK_EQUAL_RANGE(reference_10.destinations, result_10->destinations);
|
||||
|
||||
auto result_11 = parseParameters<TableParameters>("1,2;3,4?sources=all&destinations=all&"
|
||||
"annotations=duration&fallback_speed=1&"
|
||||
"fallback_coordinate=snapped&scale_factor=2");
|
||||
BOOST_CHECK(result_11);
|
||||
CHECK_EQUAL_RANGE(reference_1.sources, result_11->sources);
|
||||
CHECK_EQUAL_RANGE(reference_1.destinations, result_11->destinations);
|
||||
CHECK_EQUAL_RANGE(reference_1.bearings, result_11->bearings);
|
||||
CHECK_EQUAL_RANGE(reference_1.radiuses, result_11->radiuses);
|
||||
CHECK_EQUAL_RANGE(reference_1.approaches, result_11->approaches);
|
||||
CHECK_EQUAL_RANGE(reference_1.coordinates, result_11->coordinates);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(valid_match_urls)
|
||||
|
||||
@@ -135,6 +135,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
|
||||
TestData data;
|
||||
data.u = edge_udist(g);
|
||||
data.v = edge_udist(g);
|
||||
data.is_startpoint = true;
|
||||
if (used_edges.find(std::pair<unsigned, unsigned>(
|
||||
std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
|
||||
{
|
||||
@@ -151,7 +152,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
|
||||
struct GraphFixture
|
||||
{
|
||||
GraphFixture(const std::vector<std::pair<FloatLongitude, FloatLatitude>> &input_coords,
|
||||
const std::vector<std::pair<unsigned, unsigned>> &input_edges)
|
||||
const std::vector<std::tuple<unsigned, unsigned, bool>> &input_edges)
|
||||
{
|
||||
|
||||
for (unsigned i = 0; i < input_coords.size(); i++)
|
||||
@@ -162,15 +163,16 @@ struct GraphFixture
|
||||
for (const auto &pair : input_edges)
|
||||
{
|
||||
TestData d;
|
||||
d.u = pair.first;
|
||||
d.v = pair.second;
|
||||
d.u = std::get<0>(pair);
|
||||
d.v = std::get<1>(pair);
|
||||
// We set the forward nodes to the target node-based-node IDs, just
|
||||
// so we have something to test against. Because this isn't a real
|
||||
// graph, the actual values aren't important, we just need something
|
||||
// to examine during tests.
|
||||
d.forward_segment_id = {pair.second, true};
|
||||
d.reverse_segment_id = {pair.first, true};
|
||||
d.forward_segment_id = {std::get<1>(pair), true};
|
||||
d.reverse_segment_id = {std::get<0>(pair), true};
|
||||
d.fwd_segment_position = 0;
|
||||
d.is_startpoint = std::get<2>(pair);
|
||||
edges.emplace_back(d);
|
||||
}
|
||||
}
|
||||
@@ -299,7 +301,7 @@ BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_M
|
||||
BOOST_AUTO_TEST_CASE(regression_test)
|
||||
{
|
||||
using Coord = std::pair<FloatLongitude, FloatLatitude>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
using Edge = std::tuple<unsigned, unsigned, bool>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord{FloatLongitude{0.0}, FloatLatitude{40.0}}, //
|
||||
@@ -313,7 +315,7 @@ BOOST_AUTO_TEST_CASE(regression_test)
|
||||
Coord{FloatLongitude{105.0}, FloatLatitude{5.0}}, //
|
||||
Coord{FloatLongitude{110.0}, FloatLatitude{0.0}}, //
|
||||
},
|
||||
{Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)});
|
||||
{Edge(0, 1, true), Edge(2, 3, true), Edge(4, 5, true), Edge(6, 7, true), Edge(8, 9, true)});
|
||||
|
||||
TemporaryFile tmp;
|
||||
auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
|
||||
@@ -335,13 +337,13 @@ BOOST_AUTO_TEST_CASE(regression_test)
|
||||
BOOST_AUTO_TEST_CASE(radius_regression_test)
|
||||
{
|
||||
using Coord = std::pair<FloatLongitude, FloatLatitude>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
using Edge = std::tuple<unsigned, unsigned, bool>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
|
||||
Coord(FloatLongitude{10.0}, FloatLatitude{10.0}),
|
||||
},
|
||||
{Edge(0, 1), Edge(1, 0)});
|
||||
{Edge(0, 1, true), Edge(1, 0, true)});
|
||||
|
||||
TemporaryFile tmp;
|
||||
auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
|
||||
@@ -352,22 +354,54 @@ BOOST_AUTO_TEST_CASE(radius_regression_test)
|
||||
Coordinate input(FloatLongitude{5.2}, FloatLatitude{5.0});
|
||||
|
||||
{
|
||||
auto results =
|
||||
query.NearestPhantomNodesInRange(input, 0.01, osrm::engine::Approach::UNRESTRICTED);
|
||||
auto results = query.NearestPhantomNodesInRange(
|
||||
input, 0.01, osrm::engine::Approach::UNRESTRICTED, true);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(permissive_edge_snapping)
|
||||
{
|
||||
using Coord = std::pair<FloatLongitude, FloatLatitude>;
|
||||
using Edge = std::tuple<unsigned, unsigned, bool>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
|
||||
Coord(FloatLongitude{0.001}, FloatLatitude{0.001}),
|
||||
},
|
||||
{Edge(0, 1, true), Edge(1, 0, false)});
|
||||
|
||||
TemporaryFile tmp;
|
||||
auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
|
||||
TestDataFacade mockfacade;
|
||||
engine::GeospatialQuery<MiniStaticRTree, TestDataFacade> query(
|
||||
rtree, fixture.coords, mockfacade);
|
||||
|
||||
Coordinate input(FloatLongitude{0.0005}, FloatLatitude{0.0005});
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(
|
||||
input, 1000, osrm::engine::Approach::UNRESTRICTED, false);
|
||||
BOOST_CHECK_EQUAL(results.size(), 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(
|
||||
input, 1000, osrm::engine::Approach::UNRESTRICTED, true);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bearing_tests)
|
||||
{
|
||||
using Coord = std::pair<FloatLongitude, FloatLatitude>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
using Edge = std::tuple<unsigned, unsigned, bool>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(FloatLongitude{0.0}, FloatLatitude{0.0}),
|
||||
Coord(FloatLongitude{10.0}, FloatLatitude{10.0}),
|
||||
},
|
||||
{Edge(0, 1), Edge(1, 0)});
|
||||
{Edge(0, 1, true), Edge(1, 0, true)});
|
||||
|
||||
TemporaryFile tmp;
|
||||
auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
|
||||
@@ -405,20 +439,20 @@ BOOST_AUTO_TEST_CASE(bearing_tests)
|
||||
}
|
||||
|
||||
{
|
||||
auto results =
|
||||
query.NearestPhantomNodesInRange(input, 11000, osrm::engine::Approach::UNRESTRICTED);
|
||||
auto results = query.NearestPhantomNodesInRange(
|
||||
input, 11000, osrm::engine::Approach::UNRESTRICTED, true);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(
|
||||
input, 11000, 270, 10, osrm::engine::Approach::UNRESTRICTED);
|
||||
input, 11000, 270, 10, osrm::engine::Approach::UNRESTRICTED, true);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(
|
||||
input, 11000, 45, 10, osrm::engine::Approach::UNRESTRICTED);
|
||||
input, 11000, 45, 10, osrm::engine::Approach::UNRESTRICTED, true);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
|
||||
BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled);
|
||||
@@ -434,7 +468,7 @@ BOOST_AUTO_TEST_CASE(bearing_tests)
|
||||
BOOST_AUTO_TEST_CASE(bbox_search_tests)
|
||||
{
|
||||
using Coord = std::pair<FloatLongitude, FloatLatitude>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
using Edge = std::tuple<unsigned, unsigned, bool>;
|
||||
|
||||
GraphFixture fixture(
|
||||
{
|
||||
@@ -444,7 +478,7 @@ BOOST_AUTO_TEST_CASE(bbox_search_tests)
|
||||
Coord(FloatLongitude{3.0}, FloatLatitude{3.0}),
|
||||
Coord(FloatLongitude{4.0}, FloatLatitude{4.0}),
|
||||
},
|
||||
{Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(3, 4)});
|
||||
{Edge(0, 1, true), Edge(1, 2, true), Edge(2, 3, true), Edge(3, 4, true)});
|
||||
|
||||
TemporaryFile tmp;
|
||||
auto rtree = make_rtree<MiniStaticRTree>(tmp.path, fixture);
|
||||
|
||||
Reference in New Issue
Block a user