Compare commits
143 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dc26f7d8b9 | |||
| 791f6d02e1 | |||
| 7b7871d5aa | |||
| f7613d77d5 | |||
| c80edef46c | |||
| cfae4a1923 | |||
| fd9d5af7e0 | |||
| c81942c167 | |||
| c5c4a1b4fe | |||
| eb13041784 | |||
| fa1f121b02 | |||
| c26642de6e | |||
| ef1fc8a757 | |||
| 168e313f73 | |||
| 30f910e861 | |||
| e998c1193d | |||
| a8f3474996 | |||
| 55cc06fd8b | |||
| 8883d8cc56 | |||
| 5b2af6ef09 | |||
| 6d801e7086 | |||
| 17eb7052ba | |||
| 330f25eddb | |||
| 08b88bad63 | |||
| 153f9b02a5 | |||
| 0568dca4a3 | |||
| 60ef179d18 | |||
| c64904f5ea | |||
| 4b9e3a8068 | |||
| db7c76d04d | |||
| cc1a5ea78d | |||
| 9c033ff461 | |||
| 3c3322173c | |||
| e805f85407 | |||
| 4d54456f66 | |||
| 7359d0542f | |||
| da4fb13aa3 | |||
| 3649ab4d31 | |||
| 9e9e3fb1e4 | |||
| e73aa01725 | |||
| a5353c7179 | |||
| a5e0d7011b | |||
| 742c32d936 | |||
| 3dec680058 | |||
| 9237430be2 | |||
| 12d1d84b11 | |||
| 6dd029e6ea | |||
| e45d44cb8e | |||
| 84b6ef4340 | |||
| 5af776d963 | |||
| ddf11cc2cc | |||
| c7b1d0c131 | |||
| 423a4ef326 | |||
| ccfbce5300 | |||
| b99d3a0a69 | |||
| 659b470320 | |||
| 9a8ed30e95 | |||
| 4166b1ebbf | |||
| 89080fb2b0 | |||
| 56459d37d1 | |||
| d5232d5f5c | |||
| 3f7b5da683 | |||
| 24562acd30 | |||
| 8bce061691 | |||
| 701c5f853d | |||
| d1e4ba373a | |||
| 8cf8f0d7d6 | |||
| 978350c388 | |||
| 2e97c78181 | |||
| 979ec7fa78 | |||
| 1d7f179374 | |||
| 994fae0ef6 | |||
| 88ee51ba2e | |||
| 25ee26de3b | |||
| 353829a4cc | |||
| 6fd0b56e32 | |||
| c1efefae27 | |||
| 0c96f093ff | |||
| 6f835d57b4 | |||
| e1e53d274b | |||
| d9a03f8365 | |||
| ce5f284ec6 | |||
| 02a2d25a3f | |||
| 9fca6987c9 | |||
| 7361558c19 | |||
| 834890cf0b | |||
| a53794f864 | |||
| 8fa98ed27d | |||
| 111030864c | |||
| 90e361c3dc | |||
| 32e6ccb037 | |||
| 258fcd8626 | |||
| 92c4a228e1 | |||
| 9eae1de9bc | |||
| 76f793533a | |||
| ec7e58e10e | |||
| ac5e095d17 | |||
| ee7912f882 | |||
| f460a9f17e | |||
| 37685dae73 | |||
| 5b58445535 | |||
| 5b79640b44 | |||
| 921471a153 | |||
| 3a1bf2c85d | |||
| 9b83649a03 | |||
| 2224389fb3 | |||
| aed7bd852d | |||
| c5b48e3506 | |||
| 73f4e1d45a | |||
| 002da129c8 | |||
| 1b545fee8a | |||
| cbc96ec492 | |||
| c95d845876 | |||
| ac7705e9a0 | |||
| 0b6eb85106 | |||
| e197dae54d | |||
| 4bf3c97476 | |||
| 19d2e82d15 | |||
| eb48945807 | |||
| a68db86dc8 | |||
| 948025440f | |||
| 8365e20d4f | |||
| 0fc6903d7e | |||
| 23fd27422b | |||
| e965cf12f8 | |||
| 523be8f7e5 | |||
| c2a605a70d | |||
| 910ee0829f | |||
| 704cf314d4 | |||
| b8651bfac9 | |||
| bf28e40ba6 | |||
| a8de007d98 | |||
| 4684d2e35c | |||
| 27a9603b98 | |||
| 1610ea8dee | |||
| 171ff1191f | |||
| b5f9ba63d5 | |||
| a3c0f6a4e2 | |||
| 963c042b2a | |||
| 1be7dedda7 | |||
| 493a9a1cb2 | |||
| e1149bd4b7 | |||
| 895f072425 |
@@ -0,0 +1,2 @@
|
||||
test
|
||||
build
|
||||
@@ -4,6 +4,7 @@ What issue is this PR targeting? If there is no issue that addresses the problem
|
||||
|
||||
## Tasklist
|
||||
- [ ] ADD OWN TASKS HERE
|
||||
- [ ] CHANGELOG.md entry ([How to write a changelog entry](http://keepachangelog.com/en/1.0.0/#how))
|
||||
- [ ] update relevant [Wiki pages](https://github.com/Project-OSRM/osrm-backend/wiki)
|
||||
- [ ] add regression / cucumber cases (see docs/testing.md)
|
||||
- [ ] review
|
||||
|
||||
+50
-3
@@ -12,8 +12,7 @@ notifications:
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- "5.13"
|
||||
- 5.15
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
@@ -286,6 +285,54 @@ matrix:
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-8-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-4.9-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="8"
|
||||
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-6-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-4.9-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="8"
|
||||
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
|
||||
@@ -375,7 +422,7 @@ install:
|
||||
script:
|
||||
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
|
||||
- make -C test/data benchmark
|
||||
- ./example/build/osrm-example test/data/ch/monaco.osrm
|
||||
- ./example/build/osrm-example test/data/mld/monaco.osrm
|
||||
# All tests assume to be run from the build directory
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- ./unit_tests/library-tests
|
||||
|
||||
+71
-1
@@ -1,4 +1,74 @@
|
||||
# 5.13.0 RC4
|
||||
# 5.15.0
|
||||
- Changes from 5.14.3:
|
||||
- Bugfixes:
|
||||
- FIXED #4704: Fixed regression in bearings reordering introduced in 5.13 [#4704](https://github.com/Project-OSRM/osrm-backend/issues/4704)
|
||||
- FIXED #4781: Fixed overflow exceptions in percent-encoding parsing
|
||||
- FIXED #4770: Fixed exclude flags for single toll road scenario
|
||||
- FIXED #4283: Fix overflow on zero duration segments
|
||||
- FIXED #4804: Ignore no_*_on_red turn restrictions
|
||||
- Guidance:
|
||||
- CHANGED #4706: Guidance refactoring step to decouple intersection connectivity analysis and turn instructions generation [#4706](https://github.com/Project-OSRM/osrm-backend/pull/4706)
|
||||
- CHANGED #3491: Refactor `isThroughStreet`/Intersection options
|
||||
- Profile:
|
||||
- ADDED: `tunnel` as a new class in car profile so that sections of the route with tunnel tags will be marked as such
|
||||
|
||||
# 5.14.3
|
||||
- Changes from 5.14.2:
|
||||
- Features:
|
||||
- Added a `waypoints` parameter to the match service plugin that accepts indices to input coordinates and treats only those points as waypoints in the response format.
|
||||
- Bugfixes:
|
||||
- FIXED #4754: U-Turn penalties are applied to straight turns.
|
||||
- FIXED #4756: Removed too restrictive road name check in the sliproad handler
|
||||
- FIXED #4731: Use correct weights for edge-based graph duplicated via nodes.
|
||||
- Profile:
|
||||
- CHANGED: added Belarus speed limits
|
||||
- CHANGED: set default urban speed in Ukraine to 50kmh
|
||||
|
||||
# 5.14.2
|
||||
- Changes from 5.14.1:
|
||||
- Bugfixes:
|
||||
- FIXED #4727: Erroring when a old .core file is present.
|
||||
- FIXED #4642: Update checks for EMPTY_NAMEID to check for empty name strings
|
||||
- FIXED #4738: Fix potential segmentation fault
|
||||
- Node.js Bindings:
|
||||
- ADDED: Exposed new `max_radiuses_map_matching` option from `EngingConfig` options
|
||||
- Tools:
|
||||
- ADDED: New osrm-routed `max_radiuses_map_matching` command line flag to optionally set a maximum radius for map matching
|
||||
|
||||
# 5.14.1
|
||||
- Changes from 5.14.0
|
||||
- Bugfixes:
|
||||
- FIXED: don't use removed alternative candidates in `filterPackedPathsByCellSharing`
|
||||
|
||||
# 5.14.0
|
||||
- Changes from 5.13
|
||||
- API:
|
||||
- ADDED: new RouteStep property `driving_side` that has either "left" or "right" for that step
|
||||
- Misc:
|
||||
- ADDED: Bundles a rough (please improve!) driving-side GeoJSON file for use with `osrm-extract --location-dependent-data data/driving_side.geojson`
|
||||
- CHANGED: Conditional turn parsing is disabled by default now
|
||||
- ADDED: Adds a tool to analyze turn instruction generation in a dataset. Useful for tracking turn-by-turn heuristic changes over time.
|
||||
- CHANGED: Internal refactoring of guidance code as a first step towards a re-runnable guidance pipeline
|
||||
- ADDED: Now publishing Node 8.x LTS binary modules
|
||||
- Profile:
|
||||
- CHANGED: Remove dependency on turn types and turn modifier in the process_turn function in the `car.lua` profile. Guidance instruction types are not used to influence turn penalty anymore so this will break backward compatibility between profile version 3 and 4.
|
||||
- Guidance:
|
||||
- ADDED: New internal flag on "segregated intersections" - in the future, will should allow collapsing of instructions across complex intersection geometry where humans only perceive a single maneuver
|
||||
- CHANGED: Decrease roundabout turn radius threshold from 25m to 15m - adds some "exit the roundabout" instructions for moderately sized roundabouts that were being missed previously
|
||||
- Docker:
|
||||
- CHANGED: switch to alpine 3.6, and use a multistage build to reduce image size
|
||||
- Build:
|
||||
- FIX: use LUA_LIBRARY_DIRS to propertly detect Lua on all platforms
|
||||
- Docs:
|
||||
- FIX: clarify description of roundabout exit instructions
|
||||
- Bugfixes:
|
||||
- FIXED: Fix bug where merge instructions got the wrong direction modifier ([PR #4670](https://github.com/Project-OSRM/osrm-backend/pull/4670))
|
||||
- FIXED: Properly use the `profile.properties.left_hand_driving` property, there was a typo that meant it had no effect
|
||||
- FIXED: undefined behaviour when alternative candidate via node is same as source node ([#4691](https://github.com/Project-OSRM/osrm-backend/issues/4691))
|
||||
- FIXED: ensure libosrm.pc is pushed to the correct location for pkgconfig to find it on all platforms
|
||||
- FIXED: don't consider empty names + empty refs as a valid name for u-turns
|
||||
|
||||
# 5.13.0
|
||||
- Changes from 5.12:
|
||||
- Profile:
|
||||
- Append cardinal directions from route relations to ref fields to improve instructions; off by default see `profile.cardinal_directions`
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ if (POLICY CMP0048)
|
||||
endif()
|
||||
project(OSRM C CXX)
|
||||
set(OSRM_VERSION_MAJOR 5)
|
||||
set(OSRM_VERSION_MINOR 13)
|
||||
set(OSRM_VERSION_MINOR 15)
|
||||
set(OSRM_VERSION_PATCH 0)
|
||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||
|
||||
@@ -796,7 +796,7 @@ JOIN("-I${DEPENDENCIES_INCLUDE_DIRS}" " -I" PKGCONFIG_OSRM_INCLUDE_FLAGS)
|
||||
JOIN("${ENGINE_LIBRARIES}" " " PKGCONFIG_OSRM_DEPENDENT_LIBRARIES)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION ${PKGCONFIG_LIBRARY_DIR}/pkgconfig)
|
||||
|
||||
# uninstall target
|
||||
configure_file(
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Code of conduct
|
||||
|
||||
Everyone is invited to participate in Project OSRM’s open source projects and public discussions: we want to create a welcoming and friendly environment. Harassment of participants or other unethical and unprofessional behavior will not be tolerated in our spaces. The [Contributor Covenant](http://contributor-covenant.org) applies to all projects under the Project-OSRM organization and we ask that you please read [the full text](http://contributor-covenant.org/version/1/2/0/).
|
||||
+5
-1
@@ -1,8 +1,12 @@
|
||||
# Everyone
|
||||
|
||||
Please take some time to review our [code of conduct](CODE-OF-CONDUCT.md) to help guide your interactions with others on this project.
|
||||
|
||||
# User
|
||||
|
||||
Before you open a new issue, please search for older ones that cover the same issue.
|
||||
In general "me too" comments/issues are frowned upon.
|
||||
You can add a :+1: emoji to the issue if you want to express interest in this.
|
||||
You can add a :+1: emoji reaction to the issue if you want to express interest in this.
|
||||
|
||||
# Developer
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ To quickly try OSRM use our [demo server](http://map.project-osrm.org) which com
|
||||
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [this guide about mapping for navigation](https://www.mapbox.com/mapping/mapping-for-navigation/).
|
||||
|
||||
Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
|
||||
- [node-osrm](https://www.npmjs.com/package/osrm) - Production-ready NodeJs bindings for the routing engine
|
||||
- [osrm-frontend](https://github.com/Project-OSRM/osrm-frontend) - User-facing frontend with map. The demo server runs this on top of the backend
|
||||
- [osrm-text-instructions](https://github.com/Project-OSRM/osrm-text-instructions) - Text instructions from OSRM route response
|
||||
- [osrm-backend-docker](https://hub.docker.com/r/osrm/osrm-backend/) - Ready to use Docker images
|
||||
@@ -115,7 +114,8 @@ sudo cmake --build . --target install
|
||||
|
||||
### Request Against the Demo Server
|
||||
|
||||
Read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy).
|
||||
Read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Demo-server).
|
||||
|
||||
Simple query with instructions and alternatives on Berlin:
|
||||
|
||||
```
|
||||
|
||||
@@ -84,11 +84,15 @@ function(_lua_set_version_vars)
|
||||
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
|
||||
)
|
||||
pkg_check_modules(LUA QUIET "lua${ver}")
|
||||
list(APPEND _lua_include_subdirs ${LUA_INCLUDE_DIRS})
|
||||
list(APPEND _lua_library_names ${LUA_LIBRARIES})
|
||||
list(APPEND _lua_library_dirs ${LUA_LIBRARY_DIRS})
|
||||
endforeach ()
|
||||
|
||||
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
|
||||
set(_lua_library_names "${_lua_library_names}" PARENT_SCOPE)
|
||||
set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE)
|
||||
set(_lua_library_dirs "${_lua_library_dirs}" PARENT_SCOPE)
|
||||
endfunction(_lua_set_version_vars)
|
||||
|
||||
function(_lua_check_header_version _hdr_file)
|
||||
@@ -161,6 +165,7 @@ find_library(LUA_LIBRARY
|
||||
ENV LUA_DIR
|
||||
PATH_SUFFIXES lib
|
||||
PATHS
|
||||
${_lua_library_dirs}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
default: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions',
|
||||
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
||||
default: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only --require features/support --require features/step_definitions',
|
||||
verify: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only -f progress --require features/support --require features/step_definitions',
|
||||
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||
all: '--strict --require features/support --require features/step_definitions',
|
||||
mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+20
-28
@@ -1,34 +1,20 @@
|
||||
FROM alpine:3.5
|
||||
FROM alpine:3.6 as buildstage
|
||||
|
||||
RUN mkdir /opt
|
||||
WORKDIR /opt
|
||||
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 && \
|
||||
\
|
||||
echo "Building libstxxl" && \
|
||||
cd /opt && \
|
||||
git clone --depth 1 --branch 1.4.1 https://github.com/stxxl/stxxl.git && \
|
||||
cd stxxl && \
|
||||
mkdir build && \
|
||||
cd build && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .. && \
|
||||
make -j${NPROC} && \
|
||||
make install
|
||||
|
||||
ARG DOCKER_TAG
|
||||
RUN mkdir /src
|
||||
COPY . /src
|
||||
WORKDIR /src
|
||||
|
||||
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
echo "Building OSRM ${DOCKER_TAG}" && \
|
||||
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
|
||||
echo "Building OSRM gitsha $(cat /opt/OSRM_GITSHA)" && \
|
||||
mkdir build && \
|
||||
mkdir -p build && \
|
||||
cd build && \
|
||||
BUILD_TYPE="Release" && \
|
||||
ENABLE_ASSERTIONS="Off" && \
|
||||
@@ -41,13 +27,19 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
cd ../profiles && \
|
||||
cp -r * /opt && \
|
||||
\
|
||||
echo "Cleaning up" && \
|
||||
strip /usr/local/bin/* && \
|
||||
rm /usr/local/lib/libstxxl* && \
|
||||
cd /opt && \
|
||||
apk del boost-dev && \
|
||||
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.2-dev git make gcc && \
|
||||
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat && \
|
||||
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
|
||||
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
|
||||
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
|
||||
WORKDIR /opt
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
+4
-2
@@ -288,6 +288,7 @@ In addition to the [general options](#general-options) the following options are
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
||||
|gaps |`split` (default), `ignore` |Allows the input track splitting based on huge timestamp gaps between points. |
|
||||
|tidy |`true`, `false` (default) |Allows the input track modification to obtain better matching quality for noisy tracks. |
|
||||
|waypoints | `{index};{index};{index}...` |Treats input coordinates indicated by given indices as waypoints in returned Match object. Default is to treat all input coordinates as waypoints. |
|
||||
|
||||
|Parameter |Values |
|
||||
|------------|-----------------------------------|
|
||||
@@ -586,7 +587,7 @@ step.
|
||||
|
||||
- `name`: The name of the way along which travel proceeds.
|
||||
- `ref`: A reference number or code for the way. Optionally included, if ref data is available for the given way.
|
||||
- `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit.
|
||||
- `pronunciation`: A string containing an [IPA](https://en.wikipedia.org/wiki/International_Phonetic_Alphabet) phonetic transcription indicating how to pronounce the name in the `name` property. This property is omitted if pronunciation data is unavailable for the step.
|
||||
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
|
||||
- `exits`: The exit numbers or names of the way. Will be `undefined` if there are no exit numbers or names.
|
||||
- `mode`: A string signifying the mode of transportation.
|
||||
@@ -594,6 +595,7 @@ step.
|
||||
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
|
||||
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
|
||||
- `rotary_pronunciation`: The pronunciation hint of the rotary name. Optionally included, if the step is a rotary and a rotary pronunciation is available.
|
||||
- `driving_side`: The legal driving side at the location for this step. Either `left` or `right`.
|
||||
|
||||
#### Example
|
||||
|
||||
@@ -664,7 +666,7 @@ step.
|
||||
| `end of road` | road ends in a T intersection turn in direction of `modifier`|
|
||||
| `use lane` | **Deprecated** replaced by lanes on all intersection entries |
|
||||
| `continue` | Turn in direction of `modifier` to stay on the same road |
|
||||
| `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. The modifier specifies the direction of entering the roundabout. |
|
||||
| `roundabout` | traverse roundabout, if the route leaves the roundabout there will be an additional property `exit` for exit counting. The modifier specifies the direction of entering the roundabout. |
|
||||
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
|
||||
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
|
||||
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode or classes. If the road takes a turn itself, the `modifier` describes the direction |
|
||||
|
||||
+50
-48
@@ -6,7 +6,7 @@ OSRM supports "profiles". Profiles representing routing behavior for different t
|
||||
## Available profiles
|
||||
Out-of-the-box OSRM comes with profiles for car, bicycle and foot. You can easily modify these or create new ones if you like.
|
||||
|
||||
Profiles have a 'lua' extension, and are places in 'profiles' directory.
|
||||
Profiles have a 'lua' extension, and are placed in 'profiles' directory.
|
||||
|
||||
When running OSRM preprocessing commands you specify the profile with the --profile (or the shorthand -p) option, for example:
|
||||
|
||||
@@ -17,8 +17,8 @@ It's important to understand that profiles are used when preprocessing the OSM d
|
||||
|
||||
This means that after modifying a profile **you will need to extract, contract and reload the data again** and to see changes in the routing results. See [Processing Flow](https://github.com/Project-OSRM/osrm-backend/wiki/Processing-Flow) for more.
|
||||
|
||||
## Profiles are written in LUA
|
||||
Profiles are not just configuration files. They are scripts written in the [LUA scripting language](http://www.lua.org). The reason for this is that OpenStreetMap data is complex, and it's not possible to simply define tag mappings. LUA scripting offers a powerful way to handle all the possible tag combinations found in OpenStreetMap nodes and ways.
|
||||
## Profiles are written in Lua
|
||||
Profiles are not just configuration files. They are scripts written in the [Lua scripting language](http://www.lua.org). The reason for this is that OpenStreetMap data is complex, and it's not possible to simply define tag mappings. Lua scripting offers a powerful way to handle all the possible tag combinations found in OpenStreetMap nodes and ways.
|
||||
|
||||
## Basic structure of profiles
|
||||
A profile will process every node and way in the OSM input data to determine what ways are routable in which direction, at what speed, etc.
|
||||
@@ -35,40 +35,40 @@ A profile can also define various local functions it needs.
|
||||
|
||||
Looking at [car.lua](../profiles/car.lua) as an example, at the top of the file the api version is defined and then required library files are included.
|
||||
|
||||
Then follows the `setup` functions, which is called once when the profile is loaded. It returns a big hash table of configurations, specifying things like what speed to use for different way types. The configurations are used later in the various processing functions. Many adjustments can be done just be modifying this configuration table.
|
||||
Then follows the `setup` function, which is called once when the profile is loaded. It returns a big hash table of configurations, specifying things like what speed to use for different way types. The configurations are used later in the various processing functions. Many adjustments can be done just by modifying this configuration table.
|
||||
|
||||
The setup function is also where you can do other setup, like loading elevation data source if you want to consider that when processing ways.
|
||||
The setup function is also where you can do other setup, like loading an elevation data source if you want to consider that when processing ways.
|
||||
|
||||
Then comes the `process_node` and `process_way` functions, which are called for each OSM node and way when extracting OpenStreetMap data with `osrm-extract`.
|
||||
Then come the `process_node` and `process_way` functions, which are called for each OSM node and way when extracting OpenStreetMap data with `osrm-extract`.
|
||||
|
||||
The `process_turn` function processes every possible turn in the network, and sets a penalty depending on the angle and turn of the movement.
|
||||
|
||||
Profiles can also define a `process_segment` function to handle differences in speed along an OSM way, for example to handle elevation. As you can see, this is not currently used in the car profile.
|
||||
|
||||
At the end of the file, a table if returned with references to the setup and processing functions the profile has defined.
|
||||
At the end of the file, a table is returned with references to the setup and processing functions the profile has defined.
|
||||
|
||||
## Understanding speed, weight and rate
|
||||
When computing a route from A to B there can be different measure of what is the best route. That's why there's a need for different profiles.
|
||||
When computing a route from A to B there can be different measures of what is the best route. That's why there's a need for different profiles.
|
||||
|
||||
Because speeds very on different types of roads, the shortest and the fastest route are typically different. But there are many other possible preferences. For example a user might prefer a bicycle route that follow parks or other green areas, even though both duration and distance are a bit longer.
|
||||
Because speeds vary on different types of roads, the shortest and the fastest route are typically different. But there are many other possible preferences. For example a user might prefer a bicycle route that follow parks or other green areas, even though both duration and distance are a bit longer.
|
||||
|
||||
To handle this, OSRM doesn't simply choose the ways with the highest speed. Instead it uses the concept of `weight` and `rate`. The rate is an abstract measure that you can assign to ways as you like to make some ways preferable to others. Routing will prefer ways with high rate.
|
||||
To handle this, OSRM doesn't simply choose the ways with the highest speed. Instead it uses the concepts of `weight` and `rate`. The rate is an abstract measure that you can assign to ways as you like to make some ways preferable to others. Routing will prefer ways with high rate.
|
||||
|
||||
The weight of a way normally computed as length / rate. The weight can be thought of as the resistance or cost when passing the way. Routing will prefer ways with low weight.
|
||||
The weight of a way is normally computed as length / rate. The weight can be thought of as the resistance or cost when passing the way. Routing will prefer ways with low weight.
|
||||
|
||||
You can also set the weight of a way to a fixed value, In this case it's not calculated based on the length or rate, and the rate is ignored.
|
||||
You can also set the weight of a way to a fixed value. In this case it's not calculated based on the length or rate, and the rate is ignored.
|
||||
|
||||
You should set the speed to you best estimate of the actual speed that will be used on a particular way. This will result in the best estimated travel times.
|
||||
You should set the speed to your best estimate of the actual speed that will be used on a particular way. This will result in the best estimated travel times.
|
||||
|
||||
If you want to prefer certain ways due to other factors than the speed, adjust the rate accordingly. If you adjust the speed, the time time estimation will be skewed.
|
||||
If you want to prefer certain ways due to other factors than the speed, adjust the rate accordingly. If you adjust the speed, the time estimation will be skewed.
|
||||
|
||||
If you set the same rate on all ways, the result will be shortest path routing.
|
||||
If you set rate = speed on all ways, the result will be fastest path routing.
|
||||
If you want to prioritize certain street, increase the rate on these.
|
||||
If you want to prioritize certain streets, increase the rate on these.
|
||||
|
||||
## Elements
|
||||
### api_version
|
||||
A profile should set api_version at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If api_version is not defined, 0 will be assumed. The current api version is 2.
|
||||
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 2.
|
||||
|
||||
### Library files
|
||||
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
|
||||
@@ -81,15 +81,15 @@ set.lua | Defines the Set helper for handling sets of values
|
||||
sequence.lua | Defines the Sequence helper for handling sequences of values
|
||||
access.lua | Function for finding relevant access tags
|
||||
destination.lua | Function for finding relevant destination tags
|
||||
destination.lua | Function for determining maximum speed
|
||||
maxspeed.lua | Function for determining maximum speed
|
||||
guidance.lua | Function for processing guidance attributes
|
||||
|
||||
They all return a table of functions when you use `require` to load them. You can either store this table and reference it's functions later, of if you need only a single you can store that directly.
|
||||
They all return a table of functions when you use `require` to load them. You can either store this table and reference its functions later, or if you need only a single function you can store that directly.
|
||||
|
||||
### setup()
|
||||
The `setup` function is called once when the profile is loaded and must return a table of configurations. It's also where you can do other global setup, like loading data sources that are used during processing.
|
||||
|
||||
Note that processing of data is parallelized and several unconnected LUA interpreters will be running at the same time. The `setup` function will be called once for each. Each LUA iinterpreter will have it's own set of globals.
|
||||
Note that processing of data is parallelized and several unconnected LUA interpreters will be running at the same time. The `setup` function will be called once for each. Each LUA iinterpreter will have its own set of globals.
|
||||
|
||||
The following global properties can be set under `properties` in the hash you return in the `setup` function:
|
||||
|
||||
@@ -109,8 +109,7 @@ The following additional global properties can be set in the hash you return in
|
||||
|
||||
Attribute | Type | Notes
|
||||
-------------------------------------|------------------|----------------------------------------------------------------------------
|
||||
excludable | Sequence of Sets | Determines which class-combinations are supported by the `exclude` option at query time.
|
||||
| | E.g. `Sequence{Set{"ferry", "motorway"}, Set{"motorway"}}` will allow you to exclude ferries and motorways, or only motorways.
|
||||
excludable | Sequence of Sets | Determines which class-combinations are supported by the `exclude` option at query time. E.g. `Sequence{Set{"ferry", "motorway"}, Set{"motorway"}}` will allow you to exclude ferries and motorways, or only motorways.
|
||||
classes | Sequence | Determines the allowed classes that can be referenced using `{forward,backward}_classes` on the way in the `process_way` function.
|
||||
restrictions | Sequence | Determines which turn restrictions will be used for this profile.
|
||||
suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES".
|
||||
@@ -147,26 +146,26 @@ Importantly it will set `result.forward_mode` and `result.backward_mode` to indi
|
||||
|
||||
It will also set a number of other attributes on `result`.
|
||||
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `process_way` function. Instead `process_way` will examine the tag set on the way, process this information in various ways, calling other local functions and referencing the configuration in `profile`, etc, before arriving at the result.
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `process_way` function. Instead `process_way` will examine the tag set on the way, process this information in various ways, calling other local functions and referencing the configuration in `profile`, etc., before arriving at the result.
|
||||
|
||||
The following attributes can be set on the result in `process_way`:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------------------------------|----------|--------------------------------------------------------------------------
|
||||
forward_speed | Float | Speed on this way in km/h. Mandatory.
|
||||
backward_speed | Float | " "
|
||||
backward_speed | Float | ""
|
||||
forward_rate | Float | Routing weight, expressed as meters/*weight* (e.g. for a fastest-route weighting, you would want this to be meters/second, so set it to forward_speed/3.6)
|
||||
backward_rate | Float | " "
|
||||
backward_rate | Float | ""
|
||||
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
|
||||
backward_mode | Enum | " "
|
||||
backward_mode | Enum | ""
|
||||
forward_classes | Table | Mark this way as being of a specific class, e.g. `result.classes["toll"] = true`. This will be exposed in the API as `classes` on each `RouteStep`.
|
||||
backward_classes | Table | " "
|
||||
backward_classes | Table | ""
|
||||
duration | Float | Alternative setter for duration of the whole way in both directions
|
||||
weight | Float | Alternative setter for weight of the whole way in both directions
|
||||
turn_lanes_forward | String | Directions for individual lanes (normalized OSM `turn:lanes` value)
|
||||
turn_lanes_backward | String | " "
|
||||
turn_lanes_backward | String | ""
|
||||
forward_restricted | Boolean | Is this a restricted access road? (e.g. private, or deliveries only; used to enable high turn penalty, so that way is only chosen for start/end of route)
|
||||
backward_restricted | Boolean | " "
|
||||
backward_restricted | Boolean | ""
|
||||
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if `false`, prevents snapping the start point to this way)
|
||||
roundabout | Boolean | Is this part of a roundabout?
|
||||
circular | Boolean | Is this part of a non-roundabout circular junction?
|
||||
@@ -188,18 +187,18 @@ The `process_segment` function is called for every segment of OSM ways. A segmen
|
||||
|
||||
On OpenStreetMap way cannot have different tags on different parts of a way. Instead you would split the way into several smaller ways. However many ways are long. For example, many ways pass hills without any change in tags.
|
||||
|
||||
Processing each segment of an OSM way makes it possible to have different speeds on different parts of a way based on external data like data about elevation, pollution, noise or scenic value and adjust weight and duration of the segment.
|
||||
Processing each segment of an OSM way makes it possible to have different speeds on different parts of a way based on external data like data about elevation, pollution, noise or scenic value and adjust weight and duration of the segment accordingly.
|
||||
|
||||
In the `process_segment` you don't have access to OSM tags. Instead you use the geographical location of the start and end point of the way to lookup other data source, like elevation data. See [rasterbot.lua](../profiles/rasterbot.lua) for an example.
|
||||
In the `process_segment` function you don't have access to OSM tags. Instead you use the geographical location of the start and end point of the way to look up information from another data source, like elevation data. See [rasterbot.lua](../profiles/rasterbot.lua) for an example.
|
||||
|
||||
The following attributes can be read and set on the result in `process_segment`:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|----------------------------------------
|
||||
source.lon | Read | Float | Co-ordinates of segment start
|
||||
source.lat | Read | Float | " "
|
||||
source.lat | Read | Float | ""
|
||||
target.lon | Read | Float | Co-ordinates of segment end
|
||||
target.lat | Read | Float | " "
|
||||
target.lat | Read | Float | ""
|
||||
target.distance | Read | Float | Length of segment
|
||||
weight | Read/write | Float | Routing weight for this segment
|
||||
duration | Read/write | Float | Duration for this segment
|
||||
@@ -209,16 +208,19 @@ The `process_turn` function is called for every possible turn in the network. Ba
|
||||
|
||||
The following attributes can be read and set on the result in `process_turn`:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
direction_modifier | Read | Enum | Geometry of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
||||
turn_type | Read | Enum | Priority of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
||||
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
|
||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in `process_way`)
|
||||
angle | Read | Float | Angle of turn in degrees (`0-360`: `0`=u-turn, `180`=straight on)
|
||||
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
||||
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
||||
Attribute | Read/write? | Type | Notes
|
||||
---------------------|-------------|---------|------------------------------------------------------
|
||||
angle | Read | Float | Angle of turn in degrees (`0-360`: `0`=u-turn, `180`=straight on)
|
||||
number_of_roads | Read | Integer | Number of ways at the intersection of the turn
|
||||
is_u_turn | Read | Boolean | Is the turn a u-turn?
|
||||
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
|
||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in `process_way`)
|
||||
is_left_hand_driving | Read | Boolean | Is left-hand traffic?
|
||||
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
||||
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
||||
source_mode | Read | Enum | Travel mode before the turn. Defined in `include/extractor/travel_mode.hpp`
|
||||
target_mode | Read | Enum | Travel mode after the turn. Defined in `include/extractor/travel_mode.hpp`
|
||||
|
||||
## Guidance
|
||||
The guidance parameters in profiles are currently a work in progress. They can and will change.
|
||||
@@ -231,7 +233,7 @@ The priority-category influences the decision which road is considered the obvio
|
||||
Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large.
|
||||
|
||||
### Using raster data
|
||||
OSRM has build-in support for loading an interpolating raster data in ASCII format. This can be used e.g. for factoring in elevation when computing routes.
|
||||
OSRM has built-in support for loading an interpolating raster data in ASCII format. This can be used e.g. for factoring in elevation when computing routes.
|
||||
|
||||
Use `raster:load()` in your `setup` function to load data and store the source in your configuration hash:
|
||||
|
||||
@@ -284,8 +286,8 @@ See [rasterbot.lua](../profiles/rasterbot.lua) and [rasterbotinterp.lua](../prof
|
||||
### Helper functions
|
||||
There are a few helper functions defined in the global scope that profiles can use:
|
||||
|
||||
durationIsValid
|
||||
parseDuration
|
||||
trimLaneString
|
||||
applyAccessTokens
|
||||
canonicalizeStringList
|
||||
- `durationIsValid`
|
||||
- `parseDuration`
|
||||
- `trimLaneString`
|
||||
- `applyAccessTokens`
|
||||
- `canonicalizeStringList`
|
||||
|
||||
@@ -30,9 +30,17 @@ int main(int argc, const char *argv[])
|
||||
|
||||
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
|
||||
EngineConfig config;
|
||||
|
||||
config.storage_config = {argv[1]};
|
||||
config.use_shared_memory = false;
|
||||
|
||||
// We support two routing speed up techniques:
|
||||
// - Contraction Hierarchies (CH): requires extract+contract pre-processing
|
||||
// - Multi-Level Dijkstra (MLD): requires extract+partition+customize pre-processing
|
||||
//
|
||||
// config.algorithm = EngineConfig::Algorithm::CH;
|
||||
config.algorithm = EngineConfig::Algorithm::MLD;
|
||||
|
||||
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
|
||||
const OSRM osrm{config};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ Feature: Barriers
|
||||
| | x |
|
||||
| bollard | x |
|
||||
| gate | x |
|
||||
| lift_gate | x |
|
||||
| cycle_barrier | x |
|
||||
| cattle_grid | x |
|
||||
| border_control | x |
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
@routing @car @way
|
||||
Feature: Car - Avoid defined areas
|
||||
|
||||
Background:
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.avoid = Set { 'motorway', 'motorway_link' }
|
||||
profile.speeds = Sequence {
|
||||
highway = {
|
||||
motorway = 90,
|
||||
motorway_link = 45,
|
||||
primary = 50
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
Scenario: Car - Avoid motorways
|
||||
Then routability should be
|
||||
| highway | bothw |
|
||||
| motorway | |
|
||||
| motorway_link | |
|
||||
| primary | x |
|
||||
|
||||
+10
-10
@@ -20,9 +20,9 @@ Feature: Car - Handle driving
|
||||
| efg | primary | | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving |
|
||||
| e | a | cde,abc,abc | driving,driving,driving |
|
||||
| from | to | route | modes | turns |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | depart,new name right,new name left,arrive |
|
||||
| e | a | cde,abc,abc | driving,driving,driving | depart,new name left,arrive |
|
||||
|
||||
Scenario: Car - Control test without durations, osrm uses movable bridge speed to calculate duration
|
||||
Given the node map
|
||||
@@ -39,9 +39,9 @@ Feature: Car - Handle driving
|
||||
| efg | primary | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes | speed | time |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 13 km/h | 340s +-1 |
|
||||
| e | c | cde,cde | driving,driving | 5 km/h | 295s +-1 |
|
||||
| from | to | route | modes | speed | time | turns |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 13 km/h | 332s +-1 | depart,new name right,new name left,arrive |
|
||||
| e | c | cde,cde | driving,driving | 5 km/h | 288s +-1 | depart,arrive |
|
||||
|
||||
Scenario: Car - Properly handle durations
|
||||
Given the node map
|
||||
@@ -58,7 +58,7 @@ Feature: Car - Handle driving
|
||||
| efg | primary | | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | modes | speed |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h |
|
||||
| c | e | cde,cde | driving,driving | 2 km/h |
|
||||
| e | c | cde,cde | driving,driving | 2 km/h |
|
||||
| from | to | route | modes | speed | turns |
|
||||
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h | depart,new name right,new name left,arrive |
|
||||
| c | e | cde,cde | driving,driving | 2 km/h | depart,arrive |
|
||||
| e | c | cde,cde | driving,driving | 2 km/h | depart,arrive |
|
||||
|
||||
@@ -82,7 +82,7 @@ Feature: Car - Mode flag
|
||||
| from | to | route | turns | classes |
|
||||
| a | d | ab,cd | depart,arrive| [(restricted),(motorway,restricted),()],[()] |
|
||||
|
||||
Scenario: Car - We toll restricted with a class
|
||||
Scenario: Car - We tag toll with a class
|
||||
Given the node map
|
||||
"""
|
||||
a b
|
||||
@@ -99,6 +99,26 @@ Feature: Car - Mode flag
|
||||
| from | to | route | turns | classes |
|
||||
| a | d | ab,cd | depart,arrive | [(toll),(motorway,toll),()],[()] |
|
||||
|
||||
Scenario: Car - We tag tunnel with a class
|
||||
Background:
|
||||
Given a grid size of 200 meters
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a b
|
||||
c d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | tunnel |
|
||||
| ab | no |
|
||||
| bc | yes |
|
||||
| cd | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns | classes |
|
||||
| a | d | ab,bc,cd,cd | depart,new name right,new name left,arrive | [()],[(tunnel)],[()],[()] |
|
||||
|
||||
Scenario: Car - From roundabout on toll road
|
||||
Given the node map
|
||||
"""
|
||||
|
||||
@@ -884,7 +884,7 @@ Feature: Car - Turn restrictions
|
||||
| a | c | albic,dobe,dobe,albic,albic | depart,turn left,continue uturn,turn left,arrive |
|
||||
| a | e | albic,dobe,dobe | depart,turn left,arrive |
|
||||
|
||||
@no_turning @conditionals
|
||||
@no_turning @conditionals @restriction-way
|
||||
Scenario: Car - Conditional restriction with multiple time windows
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
@@ -1054,4 +1054,3 @@ Feature: Car - Turn restrictions
|
||||
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
|
||||
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
@routing @car
|
||||
Feature: Car - Handle physical limitation
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
|
||||
Scenario: Car - Use a narrow way
|
||||
Then routability should be
|
||||
| highway | width | narrow | bothw |
|
||||
| primary | | | x |
|
||||
| primary | narrow | | x |
|
||||
| primary | | yes | x |
|
||||
| primary | 1.8 | | |
|
||||
| primary | 1.9 | | |
|
||||
| primary | 2.0 | | x |
|
||||
| primary | 2.1 | | x |
|
||||
| primary | 1m | | |
|
||||
| primary | 1 m | | |
|
||||
| primary | 3 m | | x |
|
||||
| primary | 6' | | |
|
||||
| primary | 6'0" | | |
|
||||
| primary | 6'2" | | |
|
||||
| primary | 6'3" | | x |
|
||||
| primary | 7' | | x |
|
||||
| primary | 7'0" | | x |
|
||||
|
||||
Scenario: Car - Limited by width
|
||||
Then routability should be
|
||||
| highway | maxwidth:physical | maxwidth | width | est_width | bothw |
|
||||
| primary | 1 | | | | |
|
||||
| primary | 3 | | | | x |
|
||||
| primary | | 1 | | | |
|
||||
| primary | | 3 | | | x |
|
||||
| primary | | | 1 | | |
|
||||
| primary | | | 3 | | x |
|
||||
| primary | | | | 1 | |
|
||||
| primary | | | | 3 | x |
|
||||
|
||||
Scenario: Car - Limited by height
|
||||
Then routability should be
|
||||
| highway | maxheight:physical | maxheight | bothw |
|
||||
| primary | 1 | | |
|
||||
| primary | 3 | | x |
|
||||
| primary | | 1 | |
|
||||
| primary | | 3 | x |
|
||||
@@ -141,6 +141,33 @@ Feature: Car - Turn restrictions
|
||||
| c | a | cj,aj,aj |
|
||||
| c | b | cj,bj,bj |
|
||||
|
||||
@no_turning
|
||||
Scenario: Car - Ignore no_*_on_red relations
|
||||
Given the node map
|
||||
"""
|
||||
a
|
||||
d j b
|
||||
c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| cj | yes |
|
||||
| aj | -1 |
|
||||
| dj | -1 |
|
||||
| bj | -1 |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction |
|
||||
| restriction | cj | dj | j | no_turn_on_red |
|
||||
| restriction | cj | bj | j | no_right_turn_on_red |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| c | d | cj,dj,dj |
|
||||
| c | a | cj,aj,aj |
|
||||
| c | b | cj,bj,bj |
|
||||
|
||||
@only_turning
|
||||
Scenario: Car - Only left turn
|
||||
Given the node map
|
||||
@@ -575,7 +602,7 @@ Feature: Car - Turn restrictions
|
||||
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
@restriction @overlap
|
||||
@restriction-way @overlap
|
||||
Scenario: Car - prohibit turn
|
||||
Given the node map
|
||||
"""
|
||||
@@ -710,7 +737,7 @@ Feature: Car - Turn restrictions
|
||||
| a | j | left,first,right,right |
|
||||
| f | e | right,third,left,left |
|
||||
|
||||
@restriction
|
||||
@restriction-way
|
||||
Scenario: Car - allow only turn
|
||||
Given the node map
|
||||
"""
|
||||
@@ -742,7 +769,7 @@ Feature: Car - Turn restrictions
|
||||
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
@restriction
|
||||
@restriction-way
|
||||
Scenario: Car - allow only turn
|
||||
Given the node map
|
||||
"""
|
||||
@@ -771,7 +798,7 @@ Feature: Car - Turn restrictions
|
||||
| from | to | route |
|
||||
| a | d | ab,be,de,de |
|
||||
|
||||
@restriction
|
||||
@restriction-way
|
||||
Scenario: Multi Way restriction
|
||||
Given the node map
|
||||
"""
|
||||
@@ -808,7 +835,7 @@ Feature: Car - Turn restrictions
|
||||
| from | to | route |
|
||||
| a | h | horiz,vert,horiz,horiz |
|
||||
|
||||
@restriction
|
||||
@restriction-way
|
||||
Scenario: Multi-Way overlapping single-way
|
||||
Given the node map
|
||||
"""
|
||||
@@ -847,7 +874,7 @@ Feature: Car - Turn restrictions
|
||||
| h | d | hfb,abcd,abcd | depart,end of road right,arrive | h,b,d |
|
||||
|
||||
|
||||
@restriction
|
||||
@restriction-way
|
||||
Scenario: Car - prohibit turn, traffic lights
|
||||
Given the node map
|
||||
"""
|
||||
@@ -890,7 +917,7 @@ Feature: Car - Turn restrictions
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
|
||||
@restriction @overlap @geometry
|
||||
@restriction-way @overlap @geometry
|
||||
Scenario: Geometry
|
||||
Given the node map
|
||||
"""
|
||||
@@ -925,7 +952,7 @@ Feature: Car - Turn restrictions
|
||||
| c | d | bc,bge,de,de |
|
||||
| c | f | bc,bge,de,de,ef,ef |
|
||||
|
||||
@restriction @overlap @geometry @traffic-signals
|
||||
@restriction-way @overlap @geometry @traffic-signals
|
||||
Scenario: Geometry
|
||||
Given the node map
|
||||
"""
|
||||
@@ -967,7 +994,7 @@ Feature: Car - Turn restrictions
|
||||
| c | f | bc,bge,de,de,ef,ef |
|
||||
|
||||
# don't crash hard on invalid restrictions
|
||||
@restriction @invalid
|
||||
@restriction-way @invalid
|
||||
Scenario: Geometry
|
||||
Given the node map
|
||||
"""
|
||||
@@ -999,7 +1026,7 @@ Feature: Car - Turn restrictions
|
||||
| a | f | ab,be,ef,ef |
|
||||
|
||||
|
||||
@restriction @overlap @geometry
|
||||
@restriction @restriction-way @overlap @geometry
|
||||
Scenario: Duplicated restriction
|
||||
Given the node map
|
||||
"""
|
||||
|
||||
@@ -4,7 +4,7 @@ Feature: Testbot - side bias
|
||||
Scenario: Left-hand bias
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.left_hand_driving = true
|
||||
profile.properties.left_hand_driving = true
|
||||
profile.turn_bias = 1.075
|
||||
"""
|
||||
And the node map
|
||||
@@ -20,14 +20,14 @@ Feature: Testbot - side bias
|
||||
| bd |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
| d | a | bd,ab,ab | 24s +-1 |
|
||||
| d | c | bd,bc,bc | 27s +-1 |
|
||||
| from | to | route | time | driving_side |
|
||||
| d | a | bd,ab,ab | 24s +-1 | left,left,left |
|
||||
| d | c | bd,bc,bc | 27s +-1 | left,left,left |
|
||||
|
||||
Scenario: Right-hand bias
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.left_hand_driving = true
|
||||
profile.properties.left_hand_driving = true
|
||||
profile.turn_bias = 1 / 1.075
|
||||
"""
|
||||
And the node map
|
||||
@@ -43,14 +43,14 @@ Feature: Testbot - side bias
|
||||
| bd |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time | # |
|
||||
| d | a | bd,ab,ab | 27s +-1 | should be inverse of left hand bias |
|
||||
| d | c | bd,bc,bc | 24s +-1 | |
|
||||
| from | to | route | time | driving_side | # |
|
||||
| d | a | bd,ab,ab | 27s +-1 | left,left,left | should be inverse of left hand bias |
|
||||
| d | c | bd,bc,bc | 24s +-1 | left,left,left | |
|
||||
|
||||
Scenario: Roundabout exit counting for left sided driving
|
||||
Given the profile file "testbot" initialized with
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.left_hand_driving = true
|
||||
profile.properties.left_hand_driving = true
|
||||
"""
|
||||
And a grid size of 10 meters
|
||||
And the node map
|
||||
@@ -70,10 +70,10 @@ Feature: Testbot - side bias
|
||||
| bcegb | roundabout |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
|
||||
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
|
||||
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
|
||||
| waypoints | route | driving_side | turns |
|
||||
| a,d | ab,cd,cd | left,left,left | depart,roundabout turn left exit-1,arrive |
|
||||
| a,f | ab,ef,ef | left,left,left | depart,roundabout turn straight exit-2,arrive |
|
||||
| a,h | ab,gh,gh | left,left,left | depart,roundabout turn right exit-3,arrive |
|
||||
|
||||
|
||||
Scenario: Left-hand bias via location-dependent tags
|
||||
@@ -92,9 +92,9 @@ Feature: Testbot - side bias
|
||||
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
| d | a | bd,ab,ab | 24s +-1 |
|
||||
| d | c | bd,bc,bc | 27s +-1 |
|
||||
| from | to | route | driving_side | time |
|
||||
| d | a | bd,ab,ab | left,left,left | 24s +-1 |
|
||||
| d | c | bd,bc,bc | left,left,left | 27s +-1 |
|
||||
|
||||
|
||||
Scenario: Left-hand bias via OSM tags
|
||||
@@ -113,6 +113,31 @@ Feature: Testbot - side bias
|
||||
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
| d | a | bd,ab,ab | 27s +-1 |
|
||||
| d | c | bd,bc,bc | 24s +-1 |
|
||||
| from | to | route | driving_side | time |
|
||||
| d | a | bd,ab,ab | right,right,right | 27s +-1 |
|
||||
| d | c | bd,bc,bc | right,right,right | 24s +-1 |
|
||||
|
||||
Scenario: changing sides
|
||||
Given the profile "car"
|
||||
|
||||
# Note - the boundary in null-island.geojson is at lon = 2.0,
|
||||
# and we use the "last node of the way" as the heuristic to detect
|
||||
# whether the way is in our out of the driving_side polygon
|
||||
And the node locations
|
||||
| node | lat | lon |
|
||||
| a | 0 | 0.5 |
|
||||
| b | 0 | 1.5 |
|
||||
| c | 0 | 2.5 |
|
||||
| d | 0 | 3.5 |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| cd |
|
||||
|
||||
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
|
||||
When I route I should get
|
||||
| from | to | route | driving_side |
|
||||
| d | a | cd,bc,ab,ab | right,right,left,left |
|
||||
| a | d | ab,bc,cd,cd | left,right,right,right |
|
||||
|
||||
@@ -6,9 +6,9 @@ Feature: Car - weights
|
||||
And the node map
|
||||
"""
|
||||
a--b--c
|
||||
|
|
||||
d
|
||||
|
|
||||
| |
|
||||
d |
|
||||
| |
|
||||
e--f--g
|
||||
"""
|
||||
And the ways
|
||||
@@ -19,7 +19,7 @@ Feature: Car - weights
|
||||
| bdf | service |
|
||||
When I route I should get
|
||||
| from | to | route | speed | weight |
|
||||
| a | e | abc,cg,efg,efg | 28 km/h | 126.6 |
|
||||
| a | e | abc,cg,efg,efg | 29 km/h | 122.4 |
|
||||
| a | d | abc,bdf,bdf | 18 km/h | 71.7 |
|
||||
|
||||
Scenario: Does not jump off the highway to go down service road
|
||||
@@ -59,7 +59,7 @@ Feature: Car - weights
|
||||
When I route I should get
|
||||
| from | to | route | speed | weight |
|
||||
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
|
||||
| a | e | ab,be,be | 14 km/h | 112 |
|
||||
| a | e | ab,be,be | 14 km/h | 111.8 |
|
||||
|
||||
Scenario: Distance weights
|
||||
Given the profile file "car" initialized with
|
||||
|
||||
@@ -10,6 +10,7 @@ Feature: Barriers
|
||||
| | x |
|
||||
| bollard | x |
|
||||
| gate | x |
|
||||
| lift_gate | x |
|
||||
| cycle_barrier | x |
|
||||
| cattle_grid | x |
|
||||
| border_control | x |
|
||||
|
||||
@@ -47,7 +47,7 @@ Feature: Turn Lane Guidance
|
||||
e
|
||||
a . . b . . . c g
|
||||
` .
|
||||
` .
|
||||
` .
|
||||
` d
|
||||
f
|
||||
"""
|
||||
|
||||
@@ -50,6 +50,32 @@ Feature: Collapse
|
||||
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
|
||||
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Single Street
|
||||
Given the node map
|
||||
"""
|
||||
g
|
||||
|
||||
c b a
|
||||
d e f
|
||||
|
||||
h i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway |
|
||||
| ab | primary | first | yes |
|
||||
| bc | primary | first | yes |
|
||||
| de | primary | first | yes |
|
||||
| ef | primary | first | yes |
|
||||
| gb | primary | second | no |
|
||||
| be | primary | second | no |
|
||||
| eh | primary | second | yes |
|
||||
| ei | primary | third | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| a,i | first,second,third,third | depart,turn left,turn slight left,arrive | a,b,e,i |
|
||||
|
||||
Scenario: Segregated Intersection, Cross Belonging to Correct Street
|
||||
Given the node map
|
||||
"""
|
||||
@@ -1074,3 +1100,27 @@ Feature: Collapse
|
||||
When I route I should get
|
||||
| waypoints | bearings | route | turns | locations |
|
||||
| 1,2 | 90 270 | ab,bd,bd,ab,ab | depart,turn left,continue uturn,turn right,arrive | _,b,d,b,_ |
|
||||
|
||||
|
||||
# https://www.openstreetmap.org/#map=18/37.74844/-122.40275
|
||||
Scenario: Don't use destinations as names
|
||||
Given the node map
|
||||
"""
|
||||
f - - - - e - - - - d
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
a - - - - b - - - - c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | oneway | destination:ref |
|
||||
| abc | residential | road | yes | |
|
||||
| def | motorway_link | | yes | US 101 |
|
||||
| be | residential | cross | no | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,f | road,cross,, | depart,turn left,on ramp left,arrive |
|
||||
|
||||
@@ -992,7 +992,6 @@ Feature: Slipways and Dedicated Turn Lanes
|
||||
| dbef | primary | dbef | |
|
||||
| ae | primary_link | ae | yes |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
|
||||
@@ -1019,7 +1018,6 @@ Feature: Slipways and Dedicated Turn Lanes
|
||||
| dbcf | primary | dbcf | |
|
||||
| ac | primary_link | ae | yes |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | sab,dbcf,dbcf | depart,turn right,arrive | s,a,f |
|
||||
@@ -1047,7 +1045,55 @@ Feature: Slipways and Dedicated Turn Lanes
|
||||
| ae | primary_link | sab | yes |
|
||||
| cg | primary | cg | |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | sab,dbcef,dbcef | depart,turn right,arrive | s,a,f |
|
||||
|
||||
|
||||
@sliproads
|
||||
Scenario: Sliproad converted from a fork
|
||||
Given the node map
|
||||
"""
|
||||
d
|
||||
.
|
||||
b
|
||||
s . a '.
|
||||
`c
|
||||
.
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | ref | oneway |
|
||||
| sa | tertiary | | D 60A | yes |
|
||||
| ab | tertiary | ab | D 60A | yes |
|
||||
| ac | tertiary | | D 60A | yes |
|
||||
| dbcf | tertiary | dbcf | D 543 | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | ,dbcf,dbcf | depart,turn right,arrive | s,a,f |
|
||||
|
||||
|
||||
@sliproads
|
||||
Scenario: Sliproad to a road with a reference only
|
||||
Given the node map
|
||||
"""
|
||||
s . a . b . d
|
||||
` .
|
||||
' .
|
||||
..
|
||||
c
|
||||
.
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | name | ref | oneway |
|
||||
| sabd | primary | road | | |
|
||||
| bcf | primary | | K108 | |
|
||||
| ac | primary_link | | | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | locations |
|
||||
| s,f | road,, | depart,turn right,arrive | s,a,f |
|
||||
|
||||
@@ -354,9 +354,9 @@ Feature: Merge Segregated Roads
|
||||
| hb | road | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | turns | route | intersections |
|
||||
| waypoints | turns | route | intersections |
|
||||
| a,f | depart,arrive | road,road | true:180,false:0 true:180,false:0 true:180;true:0 |
|
||||
| c,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
|
||||
| c,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
|
||||
| 1,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
|
||||
| f,a | depart,arrive | road,road | true:0,true:0 false:180,true:0 false:180;true:180 |
|
||||
| g,a | depart,arrive | bridge,road | true:0,true:0 false:180;true:180 |
|
||||
@@ -393,31 +393,44 @@ Feature: Merge Segregated Roads
|
||||
"""
|
||||
a
|
||||
|
|
||||
b
|
||||
b-----z
|
||||
/ \
|
||||
c h
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
d g
|
||||
\ /
|
||||
e
|
||||
|
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| ab | road | no |
|
||||
| ef | road | no |
|
||||
| bcde | road | yes |
|
||||
| eghb | road | yes |
|
||||
| nodes | name | oneway |
|
||||
| ab | road | no |
|
||||
| ef | road | no |
|
||||
| bcde | road | yes |
|
||||
| eghb | road | yes |
|
||||
| bz | cross | no |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction |
|
||||
| restriction | bz | bcde | b | no_left_turn |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | turns | route |
|
||||
| a,f | depart,arrive | road,road |
|
||||
| c,f | depart,arrive | road,road |
|
||||
| f,a | depart,arrive | road,road |
|
||||
| g,a | depart,arrive | road,road |
|
||||
| waypoints | turns | route |
|
||||
| a,f | depart,arrive | road,road |
|
||||
| c,f | depart,arrive | road,road |
|
||||
| f,a | depart,arrive | road,road |
|
||||
| g,a | depart,arrive | road,road |
|
||||
| z,a | depart,turn right,arrive | cross,road,road |
|
||||
|
||||
Scenario: Traffic Island
|
||||
Given the node map
|
||||
@@ -518,35 +531,32 @@ Feature: Merge Segregated Roads
|
||||
|
||||
# the goal here should be not to mention the intersection in the middle at all and also suppress the segregated parts
|
||||
When I route I should get
|
||||
| waypoints | route | intersections |
|
||||
| waypoints | route | intersections |
|
||||
| a,l | horiz,vert,vert | true:90;false:0 true:60 true:90 true:180 false:270,true:60 false:120 false:240 false:300,true:0 false:90 false:180 false:240 true:270;true:180 |
|
||||
| a,d | horiz,horiz | true:90,false:0 true:60 true:90 true:180 false:270,false:0 true:90 false:180 false:270 true:300;true:270 |
|
||||
| a,d | horiz,horiz | true:90,false:0 true:60 true:90 true:180 false:270,false:0 true:90 false:180 false:270 true:300;true:270 |
|
||||
| j,h | vert,horiz,horiz | true:0;true:0 true:90 false:180 false:270 true:300,false:60 false:120 false:240 true:300,false:0 false:90 false:120 true:180 true:270;true:90 |
|
||||
| j,l | vert,vert | true:0,true:0 true:90 false:180 false:270 true:300,true:0 false:90 false:180 true:240 false:270;true:180 |
|
||||
| j,l | vert,vert | true:0,true:0 true:90 false:180 false:270 true:300,true:0 false:90 false:180 true:240 false:270;true:180 |
|
||||
|
||||
|
||||
Scenario: Square Area - Don't merge almost circular roads
|
||||
Given a grid size of 2 meters
|
||||
Given the node map
|
||||
"""
|
||||
i
|
||||
/
|
||||
/
|
||||
/
|
||||
b---- g .
|
||||
/ p .
|
||||
a / \ f
|
||||
\ / o /
|
||||
\ / \ /
|
||||
c n /
|
||||
/ \ \/
|
||||
/ k e
|
||||
/ \ /
|
||||
h l /
|
||||
i
|
||||
b `
|
||||
` ` p .
|
||||
a ` g` ` \ f
|
||||
\ / o /
|
||||
\ / \ /
|
||||
h - - c n /
|
||||
\ \/
|
||||
k e
|
||||
\ /
|
||||
l /
|
||||
\ /
|
||||
m . d
|
||||
/
|
||||
j
|
||||
/
|
||||
j
|
||||
"""
|
||||
|
||||
And the ways
|
||||
@@ -560,5 +570,144 @@ Feature: Merge Segregated Roads
|
||||
| jd | Hubertusallee | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| i,h | Kurfürstendamm,Hubertusallee,Hubertusallee | depart,turn straight,arrive |
|
||||
| waypoints | route | turns |
|
||||
| i,h | Kurfürstendamm,Rathenauplatz,Hubertusallee,Hubertusallee | depart,turn right,turn right,arrive |
|
||||
|
||||
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
|
||||
Scenario: Do not merge links between segregated roads
|
||||
Given the node map
|
||||
"""
|
||||
f
|
||||
`````````` ..............
|
||||
` ` ` ` e - - - - - - - d
|
||||
a 1
|
||||
```````````.............. |
|
||||
`````````` b - - - - - - - c
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
g
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| ab | germ | yes |
|
||||
| bc | ober | yes |
|
||||
| de | ober | yes |
|
||||
| ef | germ | yes |
|
||||
| eb | germ | no |
|
||||
| gb | germ | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | germ,ober | depart,arrive |
|
||||
| a,g | germ,germ,germ | depart,continue right,arrive |
|
||||
| a,1 | germ,germ,germ | depart,continue left,arrive |
|
||||
| d,g | ober,germ,germ | depart,turn left,arrive |
|
||||
|
||||
# https://www.openstreetmap.org/#map=19/51.32888/6.57059
|
||||
Scenario: Places in presence of oneways
|
||||
Given the node map
|
||||
"""
|
||||
i l
|
||||
| |
|
||||
| |
|
||||
g - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - f
|
||||
| |
|
||||
| |
|
||||
a - - - b - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - - - - - - - - - - - - - - - c - - - d
|
||||
| |
|
||||
| |
|
||||
j k
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| ab | schwert | yes |
|
||||
| cd | schwert | yes |
|
||||
| ig | luise | yes |
|
||||
| bj | luise | yes |
|
||||
| kc | marianne | yes |
|
||||
| fl | marianne | yes |
|
||||
| bc | albrecht | no |
|
||||
| fg | albrecht | no |
|
||||
| gb | albrecht | yes |
|
||||
| cf | albrecht | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,l | schwert,albrecht,marianne,marianne | depart,new name straight,turn left,arrive |
|
||||
| a,j | schwert,luise,luise | depart,turn right,arrive |
|
||||
| a,1 | schwert,albrecht,albrecht,albrecht | depart,new name straight,continue uturn,arrive |
|
||||
| k,l | marianne,marianne | depart,arrive |
|
||||
| k,j | marianne,albrecht,luise,luise | depart,turn left,turn left,arrive |
|
||||
| k,d | marianne,schwert,schwert | depart,turn right,arrive |
|
||||
| i,j | luise,luise | depart,arrive |
|
||||
| i,d | luise,albrecht,schwert,schwert | depart,turn left,turn straight,arrive |
|
||||
| i,l | luise,albrecht,marianne,marianne | depart,turn left,turn left,arrive |
|
||||
|
||||
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
|
||||
Scenario: Do not merge links between segregated roads
|
||||
Given the node map
|
||||
"""
|
||||
d
|
||||
f............... |
|
||||
`````````` .............. |
|
||||
a............... ` ` ` ` e
|
||||
``````````.............. 1
|
||||
`````````` b
|
||||
- - - - - - - c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| ab | otto | yes |
|
||||
| bc | otto | no |
|
||||
| de | neu | no |
|
||||
| ef | otto | yes |
|
||||
| eb | otto | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns | # |
|
||||
| a,c | otto,otto | depart,arrive | |
|
||||
| a,f | otto,otto,otto | depart,continue uturn,arrive | |
|
||||
| a,1 | otto,otto,otto | depart,continue left,arrive | |
|
||||
| a,d | otto,neu,neu | depart,turn left,arrive | |
|
||||
| c,1 | otto,otto | depart,arrive | |
|
||||
| c,f | otto,otto,otto | depart,continue left,arrive | Ideally, this would be depart,arrive, but the obvious discovery making the turn onto `1` from `c` obvious interferes here |
|
||||
|
||||
# https://www.openstreetmap.org/#map=18/50.94608/7.02030
|
||||
Scenario: Do not merge oneway places
|
||||
Given the node map
|
||||
"""
|
||||
j
|
||||
|
|
||||
|
|
||||
g - f - - - - - - - e
|
||||
| |
|
||||
| |
|
||||
| d
|
||||
| \
|
||||
| .c.
|
||||
a - - - - - - b` `
|
||||
| `
|
||||
| ` h
|
||||
|
|
||||
|
|
||||
i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | oneway |
|
||||
| efabc | kobe | yes |
|
||||
| edc | kobe | no |
|
||||
| fg | arn | no |
|
||||
| ia | kobu | yes |
|
||||
| hc | wei | no |
|
||||
| ej | wei | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| j,h | wei,wei | depart,arrive |
|
||||
| a,d | kobe,kobe,kobe | depart,continue left,arrive |
|
||||
|
||||
@@ -126,3 +126,24 @@ Feature: Merging
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| d,c | ,A100,A100 | depart,merge slight right,arrive |
|
||||
|
||||
|
||||
# https://www.openstreetmap.org/way/254299122
|
||||
@merge
|
||||
Scenario: Merge onto a motorway with junction references
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | junction:ref | highway | oneway |
|
||||
| abc | A100 | | motorway | yes |
|
||||
| cd | A100 | 1A | motorway | yes |
|
||||
| eb | | | motorway_link | yes |
|
||||
| cf | | 1B | motorway_link | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| e,d | ,A100,A100 | depart,merge slight left,arrive |
|
||||
|
||||
@@ -36,6 +36,36 @@ Feature: Simple Turns
|
||||
| f,a | depart,arrive | road,road | true:0,true:0 false:150 false:180;true:180 |
|
||||
| e,a | depart,turn slight right,arrive | turn,road,road | true:333;true:0 false:150 false:180;true:180 |
|
||||
|
||||
Scenario: Turning into splitting road - no improvement
|
||||
Given the node map
|
||||
"""
|
||||
a
|
||||
b
|
||||
/ |
|
||||
c d - e
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
g f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | name | highway | oneway |
|
||||
| ab | road | primary | no |
|
||||
| bcg | road | primary | yes |
|
||||
| fdb | road | primary | yes |
|
||||
| ed | turn | primary | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | turns | route | intersections |
|
||||
| f,a | depart,arrive | road,road | true:0,true:0 false:90 false:180;true:180 |
|
||||
| e,a | depart,turn right,arrive | turn,road,road | true:270;true:0 false:90 false:180;true:180 |
|
||||
|
||||
Scenario: Turning into splitting road
|
||||
Given the node map
|
||||
"""
|
||||
|
||||
@@ -5,7 +5,7 @@ Feature: Basic Roundabout
|
||||
Given a grid size of 10 meters
|
||||
Given the profile file "car" initialized with
|
||||
"""
|
||||
profile.left_hand_driving = true
|
||||
profile.properties.left_hand_driving = true
|
||||
"""
|
||||
|
||||
Scenario: Roundabout exit counting for left sided driving
|
||||
|
||||
@@ -745,12 +745,15 @@ Feature: Basic Roundabout
|
||||
|
||||
|
||||
Scenario: Drive through roundabout
|
||||
Given a grid size of 5 meters
|
||||
Given the node map
|
||||
"""
|
||||
a
|
||||
b e d f
|
||||
c
|
||||
g h
|
||||
. a .
|
||||
. .
|
||||
b e --- d ---- f
|
||||
. .
|
||||
.c.
|
||||
g h
|
||||
"""
|
||||
|
||||
And the ways
|
||||
@@ -760,12 +763,12 @@ Feature: Basic Roundabout
|
||||
| gch | | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | bearings | route | turns |
|
||||
| e,f | 90 90 | edf,edf | depart,arrive |
|
||||
| e,h | 90 135 | edf,gch,gch,gch | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||
| g,f | 45 90 | gch,edf,edf,edf | depart,roundabout-exit-2,exit roundabout right,arrive |
|
||||
| g,h | 45 135 | gch,gch,gch | depart,exit roundabout right,arrive |
|
||||
| e,e | 90 270 | edf,edf,edf,edf | depart,roundabout-exit-3,exit roundabout sharp left,arrive |
|
||||
| waypoints | bearings | route | turns |
|
||||
| e,f | 90 90 | edf,edf | depart,arrive |
|
||||
| e,h | 90 130 | edf,gch,gch,gch | depart,roundabout-exit-2,exit roundabout straight,arrive |
|
||||
| g,f | 50 90 | gch,edf,edf,edf | depart,roundabout-exit-2,exit roundabout slight right,arrive |
|
||||
| g,h | 50 130 | gch,gch,gch | depart,exit roundabout right,arrive |
|
||||
| e,e | 90 270 | edf,edf,edf,edf | depart,roundabout-exit-3,exit roundabout sharp left,arrive |
|
||||
|
||||
Scenario: CCW and CW roundabouts with overlaps
|
||||
Given the node map
|
||||
|
||||
@@ -961,12 +961,12 @@ Feature: Simple Turns
|
||||
g
|
||||
.
|
||||
.
|
||||
.
|
||||
.
|
||||
f
|
||||
h .
|
||||
. .
|
||||
. j
|
||||
.
|
||||
.
|
||||
h f
|
||||
.
|
||||
. .
|
||||
. j
|
||||
. .
|
||||
c
|
||||
. . .
|
||||
|
||||
@@ -972,6 +972,8 @@ Feature: Simple Turns
|
||||
d
|
||||
|
||||
h
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
And the nodes
|
||||
@@ -981,16 +983,16 @@ Feature: Simple Turns
|
||||
And the ways
|
||||
| nodes | name | highway | oneway |
|
||||
| yf | yf | trunk_link | yes |
|
||||
| gfeh | Centreville Road | primary | |
|
||||
| gfehq | Centreville Road | primary | |
|
||||
| fi | fi | trunk_link | yes |
|
||||
| ij | Bloomingdale Road | residential | |
|
||||
| jkabx | Blue Star Memorial Hwy | trunk | |
|
||||
| jkabx | Blue Star Memorial Hwy | trunk | yes |
|
||||
| bcde | bcde | trunk_link | yes |
|
||||
| kh | kh | trunk_link | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | turns | route |
|
||||
| a,h | depart,off ramp right,turn sharp left,arrive | Blue Star Memorial Hwy,bcde,Centreville Road,Centreville Road |
|
||||
| a,q | depart,off ramp right,turn sharp left,arrive | Blue Star Memorial Hwy,bcde,Centreville Road,Centreville Road |
|
||||
|
||||
@todo
|
||||
# https://www.openstreetmap.org/#map=20/52.51609/13.41080
|
||||
@@ -1370,3 +1372,64 @@ Feature: Simple Turns
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
|
||||
| a,g | ab,befg,befg | depart,fork slight left,arrive |
|
||||
|
||||
# https://www.openstreetmap.org/#map=18/52.25130/10.42545
|
||||
Scenario: Turn for roads with no name, ref changes
|
||||
Given the node map
|
||||
"""
|
||||
d
|
||||
.
|
||||
.
|
||||
e c . . f
|
||||
.
|
||||
.
|
||||
b
|
||||
.
|
||||
.
|
||||
a
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | ref | name |
|
||||
| abc | tertiary | K 57 | |
|
||||
| cd | tertiary | K 56 | |
|
||||
| cf | tertiary | K 56 | |
|
||||
| ce | residential | | Heinrichshöhe |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,f | ,, | depart,turn right,arrive |
|
||||
|
||||
# https://www.openstreetmap.org/#map=18/52.24071/10.29066
|
||||
Scenario: Turn for roads with no name, ref changes
|
||||
Given the node map
|
||||
"""
|
||||
x
|
||||
.
|
||||
.
|
||||
d
|
||||
. .
|
||||
. .
|
||||
. .
|
||||
e. . t . c . p. .f
|
||||
. .
|
||||
. .
|
||||
. .
|
||||
b
|
||||
.
|
||||
.
|
||||
a
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | ref | name | oneway |
|
||||
| abp | tertiary | K 23 | | yes |
|
||||
| pdx | tertiary | K 23 | | yes |
|
||||
| xdt | tertiary | K 23 | | yes |
|
||||
| tba | tertiary | K 23 | | yes |
|
||||
| etcpf | primary | B 1 | | no |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| e,x | ,,, | depart,turn sharp left,turn right,arrive |
|
||||
| f,a | ,, | depart,turn left,arrive |
|
||||
|
||||
@@ -24,7 +24,7 @@ Feature: Invalid profile API versions
|
||||
Scenario: Profile API version too high
|
||||
Given the profile file
|
||||
"""
|
||||
api_version = 4
|
||||
api_version = 5
|
||||
"""
|
||||
And the node map
|
||||
"""
|
||||
|
||||
@@ -150,7 +150,8 @@ module.exports = function () {
|
||||
}
|
||||
var ok = true;
|
||||
var encodedResult = '',
|
||||
extendedTarget = '';
|
||||
extendedTarget = '',
|
||||
resultWaypoints = [];
|
||||
|
||||
var testSubMatching = (sub, si) => {
|
||||
var testSubNode = (ni) => {
|
||||
@@ -186,6 +187,29 @@ module.exports = function () {
|
||||
});
|
||||
}
|
||||
|
||||
if (headers.has('waypoints')) {
|
||||
var got_loc = [];
|
||||
for (let i = 0; i < json.tracepoints.length; i++) {
|
||||
if (!json.tracepoints[i]) continue;
|
||||
if (json.tracepoints[i].waypoint_index != null)
|
||||
got_loc.push(json.tracepoints[i].location);
|
||||
}
|
||||
|
||||
if (row.waypoints.length != got_loc.length)
|
||||
return cb(new Error(`Expected ${row.waypoints.length} waypoints, got ${got_loc.length}`));
|
||||
|
||||
for (i = 0; i < row.waypoints.length; i++)
|
||||
{
|
||||
var want_node = this.findNodeByName(row.waypoints[i]);
|
||||
if (!this.FuzzyMatch.matchLocation(got_loc[i], want_node)) {
|
||||
resultWaypoints.push(util.format('? [%s,%s]', got_loc[i][0], got_loc[i][1]));
|
||||
ok = false;
|
||||
} else {
|
||||
resultWaypoints.push(row.waypoints[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (headers.has('matchings')) {
|
||||
got.matchings = row.matchings;
|
||||
@@ -194,7 +218,12 @@ module.exports = function () {
|
||||
if (headers.has('timestamps')) {
|
||||
got.timestamps = row.timestamps;
|
||||
}
|
||||
|
||||
if (headers.has('waypoints')) {
|
||||
got.waypoints = row.waypoints;
|
||||
}
|
||||
} else {
|
||||
got.waypoints = resultWaypoints.join(';');
|
||||
got.matchings = encodedResult;
|
||||
row.matchings = extendedTarget;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ module.exports = {
|
||||
|
||||
FuzzyMatch: class {
|
||||
match (got, want) {
|
||||
// don't fail if bearings input and extected string is empty and actual result is undefined
|
||||
if (want === '' && (got === '' || got === undefined))
|
||||
return true;
|
||||
|
||||
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
|
||||
matchAbs = want.match(/(.*)\s+\+\-(.+)$/),
|
||||
matchRe = want.match(/^\/(.*)\/$/),
|
||||
|
||||
@@ -267,6 +267,10 @@ module.exports = function () {
|
||||
return this.extractInstructionList(instructions, s => s.mode);
|
||||
};
|
||||
|
||||
this.drivingSideList = (instructions) => {
|
||||
return this.extractInstructionList(instructions, s => s.driving_side);
|
||||
};
|
||||
|
||||
this.classesList = (instructions) => {
|
||||
return this.extractInstructionList(instructions, s => '[' + s.intersections.map(i => '(' + (i.classes ? i.classes.join(',') : '') + ')').join(',') + ']');
|
||||
};
|
||||
|
||||
@@ -35,7 +35,8 @@ module.exports = function () {
|
||||
if (err) return cb(err);
|
||||
if (body && body.length) {
|
||||
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
|
||||
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
|
||||
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches,
|
||||
driving_sides;
|
||||
|
||||
let json = JSON.parse(body);
|
||||
|
||||
@@ -53,6 +54,7 @@ module.exports = function () {
|
||||
turns = this.turnList(json.routes[0]);
|
||||
intersections = this.intersectionList(json.routes[0]);
|
||||
modes = this.modeList(json.routes[0]);
|
||||
driving_sides = this.drivingSideList(json.routes[0]);
|
||||
classes = this.classesList(json.routes[0]);
|
||||
times = this.timeList(json.routes[0]);
|
||||
distances = this.distanceList(json.routes[0]);
|
||||
@@ -186,6 +188,10 @@ module.exports = function () {
|
||||
putValue('weight', weight);
|
||||
putValue('approach', approaches);
|
||||
|
||||
if (driving_sides) {
|
||||
putValue('driving_side', driving_sides);
|
||||
}
|
||||
|
||||
for (var key in row) {
|
||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||
got[key] = row[key];
|
||||
|
||||
@@ -31,40 +31,32 @@ Feature: Alternative route
|
||||
| 5 | 6 | dc,ca,ab,bd,dc,dc | |
|
||||
| 7 | 8 | ca,ab,bd,dc,ca,ca | |
|
||||
|
||||
# This test case does not work in a platform independent way
|
||||
# since it depends on a specific CH structure that is only
|
||||
# present on linux it seems.
|
||||
@4111 @todo
|
||||
Scenario: Alternative Loop Paths with single node path
|
||||
|
||||
@mld-only
|
||||
Scenario: Alternative loop paths on a single node with an asymmetric circle
|
||||
# The test checks only MLD implementation, alternatives results are unpredictable for CH on windows (#4691, #4693)
|
||||
Given a grid size of 10 meters
|
||||
Given the node map
|
||||
"""
|
||||
a1b2c3d
|
||||
|
||||
|
||||
e f
|
||||
a b c
|
||||
l d
|
||||
k e
|
||||
j f
|
||||
i h g
|
||||
"""
|
||||
|
||||
And the nodes
|
||||
| node | barrier |
|
||||
| i | bollard |
|
||||
| g | bollard |
|
||||
|
||||
And the ways
|
||||
| nodes | maxspeed |
|
||||
| ab | 30 |
|
||||
| bc | 3 |
|
||||
| cd | 30 |
|
||||
| ae | 30 |
|
||||
| ef | 30 |
|
||||
| fd | 30 |
|
||||
| nodes | oneway |
|
||||
| abcdefghijkla | no |
|
||||
|
||||
And the query options
|
||||
| alternatives | true |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | alternative |
|
||||
| b | c | bc,bc | ab,ae,ef,fd,cd,cd |
|
||||
#| c | b | bc,bc | cd,fd,ef,ae,ab,ab | # alternative path depends on phantom snapping order
|
||||
| 1 | c | ab,bc,bc | ab,ae,ef,fd,cd,cd |
|
||||
#| c | 1 | bc,ab | cd,fd,ef,ae,ab | # alternative path depends on phantom snapping order
|
||||
| 2 | c | bc,bc | |
|
||||
| c | 2 | bc,bc | |
|
||||
| 1 | 3 | ab,ae,ef,fd,cd | ab,bc,cd |
|
||||
#| 3 | 1 | cd,fd,ef,ae,ab | cd,bc,ab | # alternative path depends on phantom snapping order
|
||||
| b | 3 | bc,cd | ab,ae,ef,fd,cd |
|
||||
#| 3 | b | cd,bc,bc | cd,fd,ef,ae,ab,ab | # alternative path depends on phantom snapping order
|
||||
| from | to | route | alternative | weight |
|
||||
| e | k | abcdefghijkla,abcdefghijkla | abcdefghijkla,abcdefghijkla | 6.8 |
|
||||
|
||||
@@ -59,3 +59,27 @@ Feature: Annotations
|
||||
| from | to | route | a:datasources | a:speed |
|
||||
| a | i | abcdefghi,abcdefghi | 1:0:1:0:1:0:0:0 | 50:10:50:10:50:10:10:10 |
|
||||
| i | a | abcdefghi,abcdefghi | 0:1:0:0:0:0:0:1 | 10:50:10:10:10:10:10:50 |
|
||||
|
||||
Scenario: Speed annotations should handle zero segments
|
||||
Given the profile "testbot"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a -- b --- c
|
||||
|
|
||||
d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abc |
|
||||
| cd |
|
||||
|
||||
# This test relies on the snapping to the EBN cd to introduce a zero segment after the turn
|
||||
And the query options
|
||||
| annotations | speed,distance,duration,nodes |
|
||||
| bearings | 90,5;180,5 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | a:speed | a:distance | a:duration | a:nodes |
|
||||
| a | c | abc,abc | 10:10:10 | 249.998641:299.931643:0 | 25:30:0 | 1:2:3 |
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
@routing @testbot @exclude
|
||||
Feature: Testbot - Exclude flags regression tests
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Testbot - Exclude toll regression 1
|
||||
Given the node map
|
||||
"""
|
||||
a g
|
||||
. .
|
||||
b....d-$-$-e....f
|
||||
. .
|
||||
c h
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | toll | # |
|
||||
| ab | primary | | always drivable |
|
||||
| cb | primary | | always drivable |
|
||||
| bd | primary | | always drivable |
|
||||
| de | motorway | yes | not drivable for exclude=toll |
|
||||
| ef | primary | | always drivable |
|
||||
| fg | primary | | always drivable |
|
||||
| fh | primary | | always drivable |
|
||||
|
||||
Given the query options
|
||||
| exclude | toll |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | h | |
|
||||
| a | g | |
|
||||
| g | a | |
|
||||
| d | e | |
|
||||
|
||||
Scenario: Testbot - Exclude toll regression 2
|
||||
Given the profile "testbot"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
a g
|
||||
. .
|
||||
b....d-$-$-e....f
|
||||
. .
|
||||
c h..i
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | toll | # |
|
||||
| ab | primary | | always drivable |
|
||||
| cb | primary | | always drivable |
|
||||
| bd | primary | | always drivable |
|
||||
| de | motorway | yes | not drivable for exclude=toll |
|
||||
| ef | primary | | always drivable |
|
||||
| fg | primary | | always drivable |
|
||||
| fh | primary | | always drivable |
|
||||
| hi | primary | | always drivable |
|
||||
|
||||
Given the query options
|
||||
| exclude | toll |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | h | |
|
||||
| a | g | |
|
||||
| g | a | |
|
||||
| d | e | |
|
||||
| d | i | |
|
||||
@@ -480,3 +480,126 @@ Feature: Basic Map Matching
|
||||
| trace | a:nodes |
|
||||
| 12 | 1:2:3:4:5:6 |
|
||||
| 21 | 6:5:4:3:2:1 |
|
||||
|
||||
|
||||
Scenario: Matching with waypoints param for start/end
|
||||
Given the node map
|
||||
"""
|
||||
a-----b---c
|
||||
|
|
||||
|
|
||||
d
|
||||
|
|
||||
|
|
||||
e
|
||||
"""
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abc | no |
|
||||
| bde | no |
|
||||
|
||||
Given the query options
|
||||
| waypoints | 0;3 |
|
||||
|
||||
When I match I should get
|
||||
| trace | code | matchings | waypoints |
|
||||
| abde | Ok | abde | ae |
|
||||
|
||||
Scenario: Matching with waypoints param that were tidied away
|
||||
Given the node map
|
||||
"""
|
||||
a - b - c - e
|
||||
|
|
||||
f
|
||||
|
|
||||
g
|
||||
"""
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abce | no |
|
||||
| cfg | no |
|
||||
|
||||
Given the query options
|
||||
| tidy | true |
|
||||
| waypoints | 0;2;5 |
|
||||
|
||||
When I match I should get
|
||||
| trace | code | matchings | waypoints |
|
||||
| abccfg | Ok | abcfg | acg |
|
||||
|
||||
Scenario: Testbot - Map matching refuses to use waypoints with trace splitting
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
Given the query options
|
||||
| waypoints | 0;3 |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | code |
|
||||
| abcd | 0 1 62 63 | NoMatch |
|
||||
|
||||
Scenario: Testbot - Map matching invalid waypoints
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
e
|
||||
"""
|
||||
Given the query options
|
||||
| waypoints | 0;4 |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
When I match I should get
|
||||
| trace | code |
|
||||
| abcd | InvalidOptions |
|
||||
|
||||
Scenario: Matching fail with waypoints param missing start/end
|
||||
Given the node map
|
||||
"""
|
||||
a-----b---c
|
||||
|
|
||||
|
|
||||
d
|
||||
|
|
||||
|
|
||||
e
|
||||
"""
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abc | no |
|
||||
| bde | no |
|
||||
|
||||
Given the query options
|
||||
| waypoints | 1;3 |
|
||||
|
||||
When I match I should get
|
||||
| trace | code |
|
||||
| abde | InvalidValue |
|
||||
|
||||
Scenario: Testbot - Map matching with outlier that has no candidate and waypoint parameter
|
||||
Given a grid size of 100 meters
|
||||
Given the node map
|
||||
"""
|
||||
a b c d
|
||||
|
||||
1
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| abcd | no |
|
||||
|
||||
Given the query options
|
||||
| waypoints | 0;2;3 |
|
||||
|
||||
When I match I should get
|
||||
| trace | timestamps | code |
|
||||
| ab1d | 0 1 2 3 | NoMatch |
|
||||
|
||||
@@ -309,7 +309,7 @@ Feature: Via points
|
||||
| waypoints | route |
|
||||
| a,b,e | |
|
||||
|
||||
@todo @3359
|
||||
@3359
|
||||
Scenario: U-Turn In Bearings
|
||||
Given the node map
|
||||
"""
|
||||
|
||||
@@ -69,6 +69,11 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
|
||||
});
|
||||
non_core_edges.resize(new_end - non_core_edges.begin());
|
||||
edge_container.Insert(std::move(non_core_edges));
|
||||
|
||||
for (const auto filter_index : util::irange<std::size_t>(0, filters.size()))
|
||||
{
|
||||
edge_container.Filter(filters[filter_index], filter_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract core graph for further contraction
|
||||
|
||||
@@ -60,6 +60,25 @@ struct ContractedEdgeContainer
|
||||
flags.resize(edges.size(), ALL_FLAGS);
|
||||
}
|
||||
|
||||
void Filter(const std::vector<bool> &filter, std::size_t index)
|
||||
{
|
||||
BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT);
|
||||
const MergedFlags flag = 1 << index;
|
||||
|
||||
for (auto edge_index : util::irange<std::size_t>(0, edges.size()))
|
||||
{
|
||||
auto allowed = filter[edges[edge_index].source] && filter[edges[edge_index].target];
|
||||
if (allowed)
|
||||
{
|
||||
flags[edge_index] |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags[edge_index] &= ~flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Merge(std::vector<QueryEdge> new_edges)
|
||||
{
|
||||
BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT);
|
||||
@@ -108,7 +127,7 @@ struct ContractedEdgeContainer
|
||||
edges.insert(edges.end(), new_edges.begin(), new_end);
|
||||
auto edges_size = edges.size();
|
||||
auto new_edges_size = std::distance(new_edges.begin(), new_end);
|
||||
BOOST_ASSERT(edges_size >= new_edges_size);
|
||||
BOOST_ASSERT(static_cast<int>(edges_size) >= new_edges_size);
|
||||
flags.resize(edges_size);
|
||||
std::fill(flags.begin() + edges_size - new_edges_size, flags.end(), flag);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "util/query_heap.hpp"
|
||||
|
||||
#include <tbb/enumerable_thread_specific.h>
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
@@ -33,22 +33,8 @@ namespace json
|
||||
namespace detail
|
||||
{
|
||||
|
||||
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
|
||||
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
|
||||
|
||||
/**
|
||||
* Returns a string representing all instruction types (including internal types that
|
||||
* are normally not exposed in route responses)
|
||||
*
|
||||
* @param type the TurnType value to convert into a string
|
||||
* @return a string representing the turn type (e.g. `turn` or `continue`)
|
||||
*/
|
||||
std::string internalInstructionTypeToString(extractor::guidance::TurnType::Enum type);
|
||||
|
||||
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
|
||||
|
||||
std::string modeToString(const extractor::TravelMode mode);
|
||||
|
||||
/**
|
||||
* Ensures that a bearing value is a whole number, and clamped to the range 0-359
|
||||
*/
|
||||
|
||||
@@ -86,6 +86,10 @@ class MatchAPI final : public RouteAPI
|
||||
for (auto point_index : util::irange(
|
||||
0u, static_cast<unsigned>(sub_matchings[sub_matching_index].indices.size())))
|
||||
{
|
||||
// tidied_to_original: index of the input coordinate that a tidied coordinate
|
||||
// corresponds to.
|
||||
// sub_matching indices: index of the coordinate passed to map matching plugin that
|
||||
// a matched node corresponds to.
|
||||
trace_idx_to_matching_idx[tidy_result
|
||||
.tidied_to_original[sub_matchings[sub_matching_index]
|
||||
.indices[point_index]]] =
|
||||
@@ -93,6 +97,9 @@ class MatchAPI final : public RouteAPI
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(parameters.waypoints.empty() || sub_matchings.size() == 1);
|
||||
|
||||
std::size_t was_waypoint_idx = 0;
|
||||
for (auto trace_index : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
{
|
||||
if (tidy_result.can_be_removed[trace_index])
|
||||
@@ -114,6 +121,20 @@ class MatchAPI final : public RouteAPI
|
||||
waypoint.values["alternatives_count"] =
|
||||
sub_matchings[matching_index.sub_matching_index]
|
||||
.alternatives_count[matching_index.point_index];
|
||||
// waypoint indices need to be adjusted if route legs were collapsed
|
||||
// waypoint parameter assumes there is only one match object
|
||||
if (!parameters.waypoints.empty())
|
||||
{
|
||||
if (tidy_result.was_waypoint[trace_index])
|
||||
{
|
||||
waypoint.values["waypoint_index"] = was_waypoint_idx;
|
||||
was_waypoint_idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
waypoint.values["waypoint_index"] = util::json::Null();
|
||||
}
|
||||
}
|
||||
waypoints.values.push_back(std::move(waypoint));
|
||||
}
|
||||
|
||||
|
||||
@@ -63,25 +63,40 @@ struct MatchParameters : public RouteParameters
|
||||
RouteParameters::GeometriesType::Polyline,
|
||||
RouteParameters::OverviewType::Simplified,
|
||||
{}),
|
||||
gaps(GapsType::Split), tidy(false)
|
||||
gaps(GapsType::Split), tidy(false), waypoints()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
MatchParameters(std::vector<unsigned> timestamps_, GapsType gaps_, bool tidy_, Args... args_)
|
||||
: MatchParameters(std::move(timestamps_), gaps_, tidy_, {}, std::forward<Args>(args_)...)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
MatchParameters(std::vector<unsigned> timestamps_,
|
||||
GapsType gaps_,
|
||||
bool tidy_,
|
||||
std::vector<std::size_t> waypoints_,
|
||||
Args... args_)
|
||||
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)},
|
||||
gaps(gaps_), tidy(tidy_)
|
||||
gaps(gaps_), tidy(tidy_), waypoints{std::move(waypoints_)}
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<unsigned> timestamps;
|
||||
GapsType gaps;
|
||||
bool tidy;
|
||||
std::vector<std::size_t> waypoints;
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
const auto valid_waypoints =
|
||||
std::all_of(waypoints.begin(), waypoints.end(), [this](const auto &w) {
|
||||
return w < coordinates.size();
|
||||
});
|
||||
return RouteParameters::IsValid() &&
|
||||
(timestamps.empty() || timestamps.size() == coordinates.size());
|
||||
(timestamps.empty() || timestamps.size() == coordinates.size()) && valid_waypoints;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ struct Result
|
||||
Mask can_be_removed;
|
||||
// Maps the MatchParameter's original items to items which should not be removed.
|
||||
Mapping tidied_to_original;
|
||||
// Masking the MatchParameter coordinates for items whose indices were present in the
|
||||
// `waypoints` parameter.
|
||||
Mask was_waypoint;
|
||||
};
|
||||
|
||||
inline Result keep_all(const MatchParameters ¶ms)
|
||||
@@ -44,6 +47,15 @@ inline Result keep_all(const MatchParameters ¶ms)
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
result.was_waypoint.resize(params.coordinates.size(), true);
|
||||
if (!params.waypoints.empty())
|
||||
{
|
||||
for (const auto p : params.waypoints)
|
||||
{
|
||||
result.was_waypoint.set(p, false);
|
||||
}
|
||||
result.was_waypoint.flip();
|
||||
}
|
||||
result.tidied_to_original.reserve(params.coordinates.size());
|
||||
for (std::size_t current = 0; current < params.coordinates.size(); ++current)
|
||||
{
|
||||
@@ -61,6 +73,8 @@ inline Result keep_all(const MatchParameters ¶ms)
|
||||
{
|
||||
result.parameters.coordinates.push_back(params.coordinates[i]);
|
||||
|
||||
if (result.was_waypoint[i])
|
||||
result.parameters.waypoints.push_back(result.parameters.coordinates.size() - 1);
|
||||
if (!params.hints.empty())
|
||||
result.parameters.hints.push_back(params.hints[i]);
|
||||
|
||||
@@ -74,6 +88,8 @@ inline Result keep_all(const MatchParameters ¶ms)
|
||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||
}
|
||||
}
|
||||
if (params.waypoints.empty())
|
||||
result.parameters.waypoints.clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -85,6 +101,15 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
Result result;
|
||||
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
result.was_waypoint.resize(params.coordinates.size(), true);
|
||||
if (!params.waypoints.empty())
|
||||
{
|
||||
for (const auto p : params.waypoints)
|
||||
{
|
||||
result.was_waypoint.set(p, false);
|
||||
}
|
||||
result.was_waypoint.flip();
|
||||
}
|
||||
|
||||
result.tidied_to_original.push_back(0);
|
||||
|
||||
@@ -138,13 +163,14 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
|
||||
// We have to filter parallel arrays that may be empty or the exact same size.
|
||||
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
|
||||
|
||||
for (std::size_t i = 0; i < result.can_be_removed.size(); ++i)
|
||||
{
|
||||
if (!result.can_be_removed[i])
|
||||
{
|
||||
result.parameters.coordinates.push_back(params.coordinates[i]);
|
||||
|
||||
if (result.was_waypoint[i])
|
||||
result.parameters.waypoints.push_back(result.parameters.coordinates.size() - 1);
|
||||
if (!params.hints.empty())
|
||||
result.parameters.hints.push_back(params.hints[i]);
|
||||
|
||||
@@ -157,8 +183,17 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
if (!params.timestamps.empty())
|
||||
result.parameters.timestamps.push_back(params.timestamps[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// one of the coordinates meant to be used as a waypoint was marked for removal
|
||||
// update the original waypoint index to the new representative coordinate
|
||||
const auto last_idx = result.parameters.coordinates.size() - 1;
|
||||
if (result.was_waypoint[i] && (result.parameters.waypoints.back() != last_idx))
|
||||
{
|
||||
result.parameters.waypoints.push_back(last_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(result.tidied_to_original.size() == result.parameters.coordinates.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,50 @@ class NearestAPI final : public BaseAPI
|
||||
phantom_nodes.front().end(),
|
||||
waypoints.values.begin(),
|
||||
[this](const PhantomNodeWithDistance &phantom_with_distance) {
|
||||
auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node);
|
||||
auto &phantom_node = phantom_with_distance.phantom_node;
|
||||
auto waypoint = MakeWaypoint(phantom_node);
|
||||
waypoint.values["distance"] = phantom_with_distance.distance;
|
||||
|
||||
util::json::Array nodes;
|
||||
|
||||
std::uint64_t from_node = 0;
|
||||
std::uint64_t to_node = 0;
|
||||
|
||||
std::vector<NodeID> forward_geometry;
|
||||
if (phantom_node.forward_segment_id.enabled)
|
||||
{
|
||||
auto segment_id = phantom_node.forward_segment_id.id;
|
||||
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
|
||||
forward_geometry =
|
||||
facade.GetUncompressedForwardGeometry(geometry_id);
|
||||
|
||||
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
||||
forward_geometry[phantom_node.fwd_segment_position]);
|
||||
to_node = static_cast<std::uint64_t>(osm_node_id);
|
||||
}
|
||||
|
||||
if (phantom_node.reverse_segment_id.enabled)
|
||||
{
|
||||
auto segment_id = phantom_node.reverse_segment_id.id;
|
||||
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
|
||||
std::vector<NodeID> geometry =
|
||||
facade.GetUncompressedForwardGeometry(geometry_id);
|
||||
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
||||
geometry[phantom_node.fwd_segment_position + 1]);
|
||||
from_node = static_cast<std::uint64_t>(osm_node_id);
|
||||
}
|
||||
else if (phantom_node.forward_segment_id.enabled &&
|
||||
phantom_node.fwd_segment_position > 0)
|
||||
{
|
||||
// In the case of one way, rely on forward segment only
|
||||
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
||||
forward_geometry[phantom_node.fwd_segment_position - 1]);
|
||||
from_node = static_cast<std::uint64_t>(osm_node_id);
|
||||
}
|
||||
nodes.values.push_back(from_node);
|
||||
nodes.values.push_back(to_node);
|
||||
waypoint.values["nodes"] = std::move(nodes);
|
||||
|
||||
return waypoint;
|
||||
});
|
||||
|
||||
|
||||
@@ -88,11 +88,12 @@ class RouteAPI : public BaseAPI
|
||||
{
|
||||
util::json::Array annotations_store;
|
||||
annotations_store.values.reserve(leg.annotations.size());
|
||||
std::for_each(leg.annotations.begin(),
|
||||
leg.annotations.end(),
|
||||
[Get, &annotations_store](const auto &step) {
|
||||
annotations_store.values.push_back(Get(step));
|
||||
});
|
||||
|
||||
for (const auto &step : leg.annotations)
|
||||
{
|
||||
annotations_store.values.push_back(Get(step));
|
||||
}
|
||||
|
||||
return annotations_store;
|
||||
}
|
||||
|
||||
@@ -255,10 +256,19 @@ class RouteAPI : public BaseAPI
|
||||
// AnnotationsType uses bit flags, & operator checks if a property is set
|
||||
if (parameters.annotations_type & RouteParameters::AnnotationsType::Speed)
|
||||
{
|
||||
double prev_speed = 0;
|
||||
annotation.values["speed"] = GetAnnotations(
|
||||
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
|
||||
auto val = std::round(anno.distance / anno.duration * 10.) / 10.;
|
||||
return util::json::clamp_float(val);
|
||||
leg_geometry, [&prev_speed](const guidance::LegGeometry::Annotation &anno) {
|
||||
if (anno.duration < std::numeric_limits<double>::min())
|
||||
{
|
||||
return prev_speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto speed = std::round(anno.distance / anno.duration * 10.) / 10.;
|
||||
prev_speed = speed;
|
||||
return util::json::clamp_float(speed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -293,11 +303,10 @@ class RouteAPI : public BaseAPI
|
||||
{
|
||||
util::json::Array nodes;
|
||||
nodes.values.reserve(leg_geometry.osm_node_ids.size());
|
||||
std::for_each(leg_geometry.osm_node_ids.begin(),
|
||||
leg_geometry.osm_node_ids.end(),
|
||||
[this, &nodes](const OSMNodeID &node_id) {
|
||||
nodes.values.push_back(static_cast<std::uint64_t>(node_id));
|
||||
});
|
||||
for (const auto node_id : leg_geometry.osm_node_ids)
|
||||
{
|
||||
nodes.values.push_back(static_cast<std::uint64_t>(node_id));
|
||||
}
|
||||
annotation.values["nodes"] = std::move(nodes);
|
||||
}
|
||||
|
||||
|
||||
@@ -885,6 +885,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
// TODO: can be moved to a data block indexed by GeometryID
|
||||
return edge_based_node_data.IsLeftHandDriving(id);
|
||||
}
|
||||
|
||||
bool IsSegregated(const NodeID id) const override final
|
||||
{
|
||||
return edge_based_node_data.IsSegregated(id);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
|
||||
|
||||
@@ -191,6 +191,8 @@ class BaseDataFacade
|
||||
virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0;
|
||||
|
||||
virtual bool IsLeftHandDriving(const NodeID id) const = 0;
|
||||
|
||||
virtual bool IsSegregated(const NodeID) const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,12 +53,12 @@ template <typename Algorithm> class Engine final : public EngineInterface
|
||||
{
|
||||
public:
|
||||
explicit Engine(const EngineConfig &config)
|
||||
: route_plugin(config.max_locations_viaroute, config.max_alternatives), //
|
||||
table_plugin(config.max_locations_distance_table), //
|
||||
nearest_plugin(config.max_results_nearest), //
|
||||
trip_plugin(config.max_locations_trip), //
|
||||
match_plugin(config.max_locations_map_matching), //
|
||||
tile_plugin() //
|
||||
: route_plugin(config.max_locations_viaroute, config.max_alternatives), //
|
||||
table_plugin(config.max_locations_distance_table), //
|
||||
nearest_plugin(config.max_results_nearest), //
|
||||
trip_plugin(config.max_locations_trip), //
|
||||
match_plugin(config.max_locations_map_matching, config.max_radius_map_matching), //
|
||||
tile_plugin() //
|
||||
|
||||
{
|
||||
if (config.use_shared_memory)
|
||||
|
||||
@@ -84,6 +84,7 @@ struct EngineConfig final
|
||||
int max_locations_viaroute = -1;
|
||||
int max_locations_distance_table = -1;
|
||||
int max_locations_map_matching = -1;
|
||||
double max_radius_map_matching = -1.0;
|
||||
int max_results_nearest = -1;
|
||||
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
|
||||
bool use_shared_memory = true;
|
||||
|
||||
@@ -56,6 +56,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
const auto source_node_id = source_traversed_in_reverse ? source_node.reverse_segment_id.id
|
||||
: source_node.forward_segment_id.id;
|
||||
const auto source_name_id = facade.GetNameIndex(source_node_id);
|
||||
bool is_segregated = facade.IsSegregated(source_node_id);
|
||||
const auto source_mode = facade.GetTravelMode(source_node_id);
|
||||
auto source_classes = facade.GetClasses(facade.GetClassData(source_node_id));
|
||||
|
||||
@@ -127,6 +128,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
intersection.classes = facade.GetClasses(path_point.classes);
|
||||
|
||||
steps.push_back(RouteStep{step_name_id,
|
||||
is_segregated,
|
||||
name.to_string(),
|
||||
ref.to_string(),
|
||||
pronunciation.to_string(),
|
||||
@@ -141,15 +143,18 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
maneuver,
|
||||
leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1,
|
||||
{intersection}});
|
||||
{intersection},
|
||||
path_point.is_left_hand_driving});
|
||||
|
||||
if (leg_data_index + 1 < leg_data.size())
|
||||
{
|
||||
step_name_id = leg_data[leg_data_index + 1].name_id;
|
||||
is_segregated = leg_data[leg_data_index + 1].is_segregated;
|
||||
}
|
||||
else
|
||||
{
|
||||
step_name_id = facade.GetNameIndex(target_node_id);
|
||||
is_segregated = facade.IsSegregated(target_node_id);
|
||||
}
|
||||
|
||||
// extract bearings
|
||||
@@ -205,6 +210,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
intersection.classes = facade.GetClasses(facade.GetClassData(target_node_id));
|
||||
BOOST_ASSERT(duration >= 0);
|
||||
steps.push_back(RouteStep{step_name_id,
|
||||
is_segregated,
|
||||
facade.GetNameForID(step_name_id).to_string(),
|
||||
facade.GetRefForID(step_name_id).to_string(),
|
||||
facade.GetPronunciationForID(step_name_id).to_string(),
|
||||
@@ -219,7 +225,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
maneuver,
|
||||
leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1,
|
||||
{intersection}});
|
||||
{intersection},
|
||||
facade.IsLeftHandDriving(target_node_id)});
|
||||
}
|
||||
// In this case the source + target are on the same edge segment
|
||||
else
|
||||
@@ -247,6 +254,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
const EdgeWeight duration = std::max(0, target_duration - source_duration);
|
||||
|
||||
steps.push_back(RouteStep{source_name_id,
|
||||
is_segregated,
|
||||
facade.GetNameForID(source_name_id).to_string(),
|
||||
facade.GetRefForID(source_name_id).to_string(),
|
||||
facade.GetPronunciationForID(source_name_id).to_string(),
|
||||
@@ -261,7 +269,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
std::move(maneuver),
|
||||
leg_geometry.FrontIndex(segment_index),
|
||||
leg_geometry.BackIndex(segment_index) + 1,
|
||||
{intersection}});
|
||||
{intersection},
|
||||
facade.IsLeftHandDriving(source_node_id)});
|
||||
}
|
||||
|
||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||
@@ -287,6 +296,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
|
||||
BOOST_ASSERT(!leg_geometry.locations.empty());
|
||||
steps.push_back(RouteStep{target_name_id,
|
||||
facade.IsSegregated(target_node_id),
|
||||
facade.GetNameForID(target_name_id).to_string(),
|
||||
facade.GetRefForID(target_name_id).to_string(),
|
||||
facade.GetPronunciationForID(target_name_id).to_string(),
|
||||
@@ -301,7 +311,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
std::move(maneuver),
|
||||
leg_geometry.locations.size() - 1,
|
||||
leg_geometry.locations.size(),
|
||||
{intersection}});
|
||||
{intersection},
|
||||
facade.IsLeftHandDriving(target_node_id)});
|
||||
|
||||
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
||||
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
||||
|
||||
@@ -121,9 +121,15 @@ inline bool haveSameMode(const RouteStep &first, const RouteStep &second, const
|
||||
// alias for readability
|
||||
inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
|
||||
{
|
||||
const auto has_name_or_ref = [](auto const &step) {
|
||||
return !step.name.empty() || !step.ref.empty();
|
||||
};
|
||||
|
||||
// make sure empty is not involved
|
||||
if (lhs.name_id == EMPTY_NAMEID || rhs.name_id == EMPTY_NAMEID)
|
||||
if (!has_name_or_ref(lhs) || !has_name_or_ref(rhs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// easy check to not go over the strings if not necessary
|
||||
else if (lhs.name_id == rhs.name_id)
|
||||
|
||||
@@ -60,6 +60,7 @@ inline IntermediateIntersection getInvalidIntersection()
|
||||
struct RouteStep
|
||||
{
|
||||
unsigned name_id;
|
||||
bool is_segregated;
|
||||
std::string name;
|
||||
std::string ref;
|
||||
std::string pronunciation;
|
||||
@@ -76,6 +77,7 @@ struct RouteStep
|
||||
std::size_t geometry_begin;
|
||||
std::size_t geometry_end;
|
||||
std::vector<IntermediateIntersection> intersections;
|
||||
bool is_left_hand_driving;
|
||||
|
||||
// remove all information from the route step, marking it as invalid (used to indicate empty
|
||||
// steps to be removed).
|
||||
@@ -123,12 +125,13 @@ inline void RouteStep::Invalidate()
|
||||
duration = 0;
|
||||
distance = 0;
|
||||
weight = 0;
|
||||
mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
mode = extractor::TRAVEL_MODE_INACCESSIBLE;
|
||||
maneuver = getInvalidStepManeuver();
|
||||
geometry_begin = 0;
|
||||
geometry_end = 0;
|
||||
intersections.clear();
|
||||
intersections.push_back(getInvalidIntersection());
|
||||
is_left_hand_driving = false;
|
||||
}
|
||||
|
||||
// Elongate by another step in front
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
#include "engine/phantom_node.hpp"
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/guidance/turn_bearing.hpp"
|
||||
#include "util/guidance/turn_lanes.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <vector>
|
||||
@@ -27,6 +27,8 @@ struct PathData
|
||||
NodeID turn_via_node;
|
||||
// name of the street that leads to the turn
|
||||
unsigned name_id;
|
||||
// segregated edge-based node that leads to the turn
|
||||
bool is_segregated;
|
||||
// weight that is traveled on the segment until the turn is reached
|
||||
// including the turn weight, if one exists
|
||||
EdgeWeight weight_until_turn;
|
||||
@@ -57,6 +59,9 @@ struct PathData
|
||||
util::guidance::TurnBearing pre_turn_bearing;
|
||||
// bearing (as seen from the intersection) post-turn
|
||||
util::guidance::TurnBearing post_turn_bearing;
|
||||
|
||||
// Driving side of the turn
|
||||
bool is_left_hand_driving;
|
||||
};
|
||||
|
||||
struct InternalRouteResult
|
||||
@@ -97,6 +102,56 @@ struct InternalManyRoutesResult
|
||||
|
||||
std::vector<InternalRouteResult> routes;
|
||||
};
|
||||
|
||||
inline InternalRouteResult CollapseInternalRouteResult(const InternalRouteResult &leggy_result,
|
||||
const std::vector<bool> &is_waypoint)
|
||||
{
|
||||
BOOST_ASSERT(leggy_result.is_valid());
|
||||
BOOST_ASSERT(is_waypoint[0]); // first and last coords
|
||||
BOOST_ASSERT(is_waypoint.back()); // should always be waypoints
|
||||
// Nothing to collapse! return result as is
|
||||
if (leggy_result.unpacked_path_segments.size() == 1)
|
||||
return leggy_result;
|
||||
|
||||
BOOST_ASSERT(leggy_result.segment_end_coordinates.size() > 1);
|
||||
|
||||
InternalRouteResult collapsed;
|
||||
collapsed.shortest_path_weight = leggy_result.shortest_path_weight;
|
||||
for (auto i : util::irange<std::size_t>(0, leggy_result.unpacked_path_segments.size()))
|
||||
{
|
||||
if (is_waypoint[i])
|
||||
{
|
||||
// start another leg vector
|
||||
collapsed.unpacked_path_segments.push_back(leggy_result.unpacked_path_segments[i]);
|
||||
// save new phantom node pair
|
||||
collapsed.segment_end_coordinates.push_back(leggy_result.segment_end_coordinates[i]);
|
||||
// save data about phantom nodes
|
||||
collapsed.source_traversed_in_reverse.push_back(
|
||||
leggy_result.source_traversed_in_reverse[i]);
|
||||
collapsed.target_traversed_in_reverse.push_back(
|
||||
leggy_result.target_traversed_in_reverse[i]);
|
||||
}
|
||||
else
|
||||
// no new leg, collapse the next segment into the last leg
|
||||
{
|
||||
BOOST_ASSERT(!collapsed.unpacked_path_segments.empty());
|
||||
auto &last_segment = collapsed.unpacked_path_segments.back();
|
||||
// deduplicate last segment (needs to be checked for empty for the same node query edge
|
||||
// case)
|
||||
if (!last_segment.empty())
|
||||
last_segment.pop_back();
|
||||
// update target phantom node of leg
|
||||
BOOST_ASSERT(!collapsed.segment_end_coordinates.empty());
|
||||
collapsed.segment_end_coordinates.back().target_phantom =
|
||||
leggy_result.segment_end_coordinates[i].target_phantom;
|
||||
// copy path segments into current leg
|
||||
last_segment.insert(last_segment.end(),
|
||||
leggy_result.unpacked_path_segments[i].begin(),
|
||||
leggy_result.unpacked_path_segments[i].end());
|
||||
}
|
||||
}
|
||||
return collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ class MatchPlugin : public BasePlugin
|
||||
using CandidateLists = routing_algorithms::CandidateLists;
|
||||
static const constexpr double RADIUS_MULTIPLIER = 3;
|
||||
|
||||
MatchPlugin(const int max_locations_map_matching)
|
||||
: max_locations_map_matching(max_locations_map_matching)
|
||||
MatchPlugin(const int max_locations_map_matching, const double max_radius_map_matching)
|
||||
: max_locations_map_matching(max_locations_map_matching),
|
||||
max_radius_map_matching(max_radius_map_matching)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,6 +36,7 @@ class MatchPlugin : public BasePlugin
|
||||
|
||||
private:
|
||||
const int max_locations_map_matching;
|
||||
const double max_radius_map_matching;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,7 @@ void annotatePath(const FacadeT &facade,
|
||||
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
|
||||
const auto node_id = *node_from; // edge-based graph node index
|
||||
const auto name_index = facade.GetNameIndex(node_id);
|
||||
const bool is_segregated = facade.IsSegregated(node_id);
|
||||
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
|
||||
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
|
||||
const auto classes = facade.GetClassData(node_id);
|
||||
@@ -185,12 +186,15 @@ void annotatePath(const FacadeT &facade,
|
||||
: 0);
|
||||
const std::size_t end_index = weight_vector.size();
|
||||
|
||||
bool is_left_hand_driving = facade.IsLeftHandDriving(node_id);
|
||||
|
||||
BOOST_ASSERT(start_index >= 0);
|
||||
BOOST_ASSERT(start_index < end_index);
|
||||
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
||||
{
|
||||
unpacked_path.push_back(PathData{id_vector[segment_idx + 1],
|
||||
name_index,
|
||||
is_segregated,
|
||||
weight_vector[segment_idx],
|
||||
0,
|
||||
duration_vector[segment_idx],
|
||||
@@ -202,7 +206,8 @@ void annotatePath(const FacadeT &facade,
|
||||
EMPTY_ENTRY_CLASS,
|
||||
datasource_vector[segment_idx],
|
||||
util::guidance::TurnBearing(0),
|
||||
util::guidance::TurnBearing(0)});
|
||||
util::guidance::TurnBearing(0),
|
||||
is_left_hand_driving});
|
||||
}
|
||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||
if (facade.HasLaneData(turn_id))
|
||||
@@ -254,6 +259,7 @@ void annotatePath(const FacadeT &facade,
|
||||
// t: fwd_segment 3
|
||||
// -> (U, v), (v, w), (w, x)
|
||||
// note that (x, t) is _not_ included but needs to be added later.
|
||||
bool is_target_left_hand_driving = facade.IsLeftHandDriving(target_node_id);
|
||||
for (std::size_t segment_idx = start_index; segment_idx != end_index;
|
||||
(start_index < end_index ? ++segment_idx : --segment_idx))
|
||||
{
|
||||
@@ -262,6 +268,7 @@ void annotatePath(const FacadeT &facade,
|
||||
unpacked_path.push_back(
|
||||
PathData{id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
||||
facade.GetNameIndex(target_node_id),
|
||||
facade.IsSegregated(target_node_id),
|
||||
weight_vector[segment_idx],
|
||||
0,
|
||||
duration_vector[segment_idx],
|
||||
@@ -273,7 +280,8 @@ void annotatePath(const FacadeT &facade,
|
||||
EMPTY_ENTRY_CLASS,
|
||||
datasource_vector[segment_idx],
|
||||
util::guidance::TurnBearing(0),
|
||||
util::guidance::TurnBearing(0)});
|
||||
util::guidance::TurnBearing(0),
|
||||
is_target_left_hand_driving});
|
||||
}
|
||||
|
||||
if (unpacked_path.size() > 0)
|
||||
|
||||
@@ -75,6 +75,7 @@ class EdgeBasedGraphFactory
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const std::unordered_set<EdgeID> &segregated_edges,
|
||||
guidance::LaneDescriptionMap &lane_description_map);
|
||||
|
||||
void Run(ScriptingEnvironment &scripting_environment,
|
||||
@@ -157,6 +158,7 @@ class EdgeBasedGraphFactory
|
||||
const CompressedEdgeContainer &m_compressed_edge_container;
|
||||
|
||||
const util::NameTable &name_table;
|
||||
const std::unordered_set<EdgeID> &segregated_edges;
|
||||
guidance::LaneDescriptionMap &lane_description_map;
|
||||
|
||||
// In the edge based graph, any traversable (non reversed) edge of the node-based graph forms a
|
||||
|
||||
@@ -12,7 +12,8 @@ struct EdgeBasedNode
|
||||
{
|
||||
GeometryID geometry_id;
|
||||
ComponentID component_id;
|
||||
AnnotationID annotation_id;
|
||||
std::uint32_t annotation_id : 31;
|
||||
std::uint32_t segregated : 1;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
|
||||
@@ -14,41 +14,33 @@ namespace extractor
|
||||
|
||||
struct ExtractionTurn
|
||||
{
|
||||
ExtractionTurn(const guidance::ConnectedRoad &turn,
|
||||
ExtractionTurn(double angle,
|
||||
int number_of_roads,
|
||||
bool is_u_turn,
|
||||
bool has_traffic_light,
|
||||
bool source_restricted,
|
||||
bool target_restricted,
|
||||
bool is_left_hand_driving)
|
||||
: angle(180. - turn.angle), turn_type(turn.instruction.type),
|
||||
direction_modifier(turn.instruction.direction_modifier),
|
||||
bool is_left_hand_driving,
|
||||
TravelMode source_mode,
|
||||
TravelMode target_mode)
|
||||
: angle(180. - angle), number_of_roads(number_of_roads), is_u_turn(is_u_turn),
|
||||
has_traffic_light(has_traffic_light), source_restricted(source_restricted),
|
||||
target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving),
|
||||
weight(0.), duration(0.)
|
||||
{
|
||||
}
|
||||
|
||||
ExtractionTurn(bool has_traffic_light,
|
||||
bool source_restricted,
|
||||
bool target_restricted,
|
||||
bool is_left_hand_driving)
|
||||
: angle(0), turn_type(guidance::TurnType::NoTurn),
|
||||
direction_modifier(guidance::DirectionModifier::Straight),
|
||||
has_traffic_light(has_traffic_light), source_restricted(source_restricted),
|
||||
target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving),
|
||||
weight(0.), duration(0.)
|
||||
weight(0.), duration(0.), source_mode(source_mode), target_mode(target_mode)
|
||||
{
|
||||
}
|
||||
|
||||
const double angle;
|
||||
const guidance::TurnType::Enum turn_type;
|
||||
const guidance::DirectionModifier::Enum direction_modifier;
|
||||
const int number_of_roads;
|
||||
const bool is_u_turn;
|
||||
const bool has_traffic_light;
|
||||
const bool source_restricted;
|
||||
const bool target_restricted;
|
||||
const bool is_left_hand_driving;
|
||||
|
||||
double weight;
|
||||
double duration;
|
||||
const TravelMode source_mode;
|
||||
const TravelMode target_mode;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ struct ExtractionWay
|
||||
turn_lanes_forward.clear();
|
||||
turn_lanes_backward.clear();
|
||||
road_classification = guidance::RoadClassification();
|
||||
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
forward_travel_mode = extractor::TRAVEL_MODE_INACCESSIBLE;
|
||||
backward_travel_mode = extractor::TRAVEL_MODE_INACCESSIBLE;
|
||||
roundabout = false;
|
||||
circular = false;
|
||||
is_startpoint = true;
|
||||
@@ -112,8 +112,8 @@ struct ExtractionWay
|
||||
std::string turn_lanes_forward;
|
||||
std::string turn_lanes_backward;
|
||||
guidance::RoadClassification road_classification;
|
||||
TravelMode forward_travel_mode : 4;
|
||||
TravelMode backward_travel_mode : 4;
|
||||
extractor::TravelMode forward_travel_mode : 4;
|
||||
extractor::TravelMode backward_travel_mode : 4;
|
||||
|
||||
// Boolean flags
|
||||
bool roundabout : 1;
|
||||
|
||||
@@ -71,6 +71,7 @@ class Extractor
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const std::vector<TurnRestriction> &turn_restrictions,
|
||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
const std::unordered_set<EdgeID> &segregated_edges,
|
||||
// might have to be updated to add new lane combinations
|
||||
guidance::LaneDescriptionMap &turn_lane_map,
|
||||
// for calculating turn penalties
|
||||
|
||||
@@ -69,6 +69,7 @@ struct ExtractorConfig final : storage::IOConfig
|
||||
".osrm.cnbg",
|
||||
".osrm.cnbg_to_ebg"}),
|
||||
requested_num_threads(0),
|
||||
parse_conditionals(false),
|
||||
use_locations_cache(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ operator()(const NodeID intersection_node,
|
||||
const boost::optional<util::json::Object> &way_style) const
|
||||
{
|
||||
// request the number of lanes. This process needs to be in sync with what happens over at
|
||||
// intersection_generator
|
||||
// intersection analysis
|
||||
const auto intersection_lanes =
|
||||
intersection.FindMaximum(guidance::makeExtractLanesForRoad(node_based_graph));
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ const double constexpr DISTINCTION_RATIO = 2;
|
||||
const double constexpr MAX_ROUNDABOUT_RADIUS = 15;
|
||||
// Unnamed small roundabouts that look like intersections are announced as turns,
|
||||
// guard against data issues or such roundabout intersections getting too large.
|
||||
const double constexpr MAX_ROUNDABOUT_INTERSECTION_RADIUS = 25;
|
||||
const double constexpr MAX_ROUNDABOUT_INTERSECTION_RADIUS = 15;
|
||||
|
||||
const double constexpr INCREASES_BY_FOURTY_PERCENT = 1.4;
|
||||
|
||||
|
||||
@@ -14,10 +14,13 @@ namespace guidance
|
||||
class DrivewayHandler final : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
DrivewayHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
DrivewayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_
|
||||
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
// check if two name ids can be seen as identical (in presence of refs/others)
|
||||
// in our case this translates into no name announcement in either direction (lhs->rhs and
|
||||
// rhs->lhs)
|
||||
bool HaveIdenticalNames(const NameID lhs,
|
||||
const NameID rhs,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /*OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_*/
|
||||
@@ -44,14 +44,6 @@ inline auto makeCompareShapeDataByBearing(const double base_bearing)
|
||||
};
|
||||
}
|
||||
|
||||
inline auto makeCompareShapeDataAngleToBearing(const double base_bearing)
|
||||
{
|
||||
return [base_bearing](const auto &lhs, const auto &rhs) {
|
||||
return util::bearing::angleBetween(lhs.bearing, base_bearing) <
|
||||
util::bearing::angleBetween(rhs.bearing, base_bearing);
|
||||
};
|
||||
}
|
||||
|
||||
inline auto makeCompareAngularDeviation(const double angle)
|
||||
{
|
||||
return [angle](const auto &lhs, const auto &rhs) {
|
||||
@@ -301,10 +293,11 @@ struct IntersectionView final : std::vector<IntersectionViewData>, //
|
||||
};
|
||||
|
||||
// `Intersection` is a relative view of an intersection by an incoming edge.
|
||||
// `Intersection` are streets at an intersection ordered from from sharp right counter-clockwise to
|
||||
// `Intersection` are streets at an intersection stored as an ordered list of connected roads
|
||||
// ordered from sharp right counter-clockwise to
|
||||
// sharp left where `intersection[0]` is _always_ a u-turn
|
||||
|
||||
// An intersection is an ordered list of connected roads ordered from from sharp right
|
||||
// An intersection is an ordered list of connected roads ordered from sharp right
|
||||
// counter-clockwise to sharp left where `intersection[0]` is always a u-turn
|
||||
//
|
||||
// |
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_GENERATOR_HPP_
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_GENERATOR_HPP_
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/coordinate_extractor.hpp"
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_normalization_operation.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "util/attributes.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
struct IntersectionGenerationParameters
|
||||
{
|
||||
NodeID nid;
|
||||
EdgeID via_eid;
|
||||
};
|
||||
|
||||
// The Intersection Generator is given a turn location and generates an intersection representation
|
||||
// from it. For this all turn possibilities are analysed.
|
||||
// We consider turn restrictions to indicate possible turns. U-turns are generated based on profile
|
||||
// decisions.
|
||||
class IntersectionGenerator
|
||||
{
|
||||
public:
|
||||
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container);
|
||||
|
||||
// For a source node `a` and a via edge `ab` creates an intersection at target `b`.
|
||||
//
|
||||
// a . . . b . .
|
||||
// .
|
||||
// .
|
||||
//
|
||||
IntersectionView operator()(const NodeID nid, const EdgeID via_eid) const;
|
||||
|
||||
/*
|
||||
* Compute the shape of an intersection, returning a set of connected roads, without any further
|
||||
* concern for which of the entries are actually allowed.
|
||||
* The shape also only comes with turn bearings, not with turn angles. All turn angles will be
|
||||
* set to zero
|
||||
*/
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
IntersectionShape
|
||||
ComputeIntersectionShape(const NodeID center_node,
|
||||
const boost::optional<NodeID> sorting_base = boost::none,
|
||||
bool use_low_precision_angles = false) const;
|
||||
|
||||
// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
|
||||
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
|
||||
// intermediate intersection, if there is a traffic light in between. If we want to look farther
|
||||
// down a road, finding the next actual decision requires the look at multiple intersections.
|
||||
// Here we follow the road until we either reach a dead end or find the next intersection with
|
||||
// more than a single next road. This function skips over degree two nodes to find coorect input
|
||||
// for GetConnectedRoads.
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
IntersectionGenerationParameters SkipDegreeTwoNodes(const NodeID starting_node,
|
||||
const EdgeID via_edge) const;
|
||||
|
||||
// Allow access to the coordinate extractor for all owners
|
||||
const CoordinateExtractor &GetCoordinateExtractor() const;
|
||||
|
||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
||||
// the node reached from `from_node` via `via_eid`. The resulting candidates have to be analysed
|
||||
// for their actual instructions later on.
|
||||
// The switch for `use_low_precision_angles` enables a faster mode that will procude less
|
||||
// accurate coordinates. It should be good enough to check order of turns, find straightmost
|
||||
// turns. Even good enough to do some simple angle verifications. It is mostly available to
|
||||
// allow for faster graph traversal in the extraction phase.
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
IntersectionView GetConnectedRoads(const NodeID from_node,
|
||||
const EdgeID via_eid,
|
||||
const bool use_low_precision_angles = false) const;
|
||||
|
||||
/*
|
||||
* To be used in the road network, we need to check for valid/restricted turns. These two
|
||||
* functions transform a basic intersection / a normalised intersection into the
|
||||
* correct view when entering via a given edge.
|
||||
*/
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
IntersectionView
|
||||
TransformIntersectionShapeIntoView(const NodeID previous_node,
|
||||
const EdgeID entering_via_edge,
|
||||
const IntersectionShape &intersection) const;
|
||||
// version for normalised intersection
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
IntersectionView TransformIntersectionShapeIntoView(
|
||||
const NodeID previous_node,
|
||||
const EdgeID entering_via_edge,
|
||||
const IntersectionShape &normalised_intersection,
|
||||
const IntersectionShape &intersection,
|
||||
const std::vector<IntersectionNormalizationOperation> &merging_map) const;
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const RestrictionMap &restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
|
||||
// own state, used to find the correct coordinates along a road
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_GENERATOR_HPP_ */
|
||||
@@ -2,8 +2,8 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_HANDLER_HPP_
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/node_based_graph_walker.hpp"
|
||||
#include "extractor/intersection/intersection_analysis.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
|
||||
@@ -34,10 +34,13 @@ class IntersectionHandler
|
||||
public:
|
||||
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
virtual ~IntersectionHandler() = default;
|
||||
|
||||
@@ -52,10 +55,13 @@ class IntersectionHandler
|
||||
protected:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const RestrictionMap &node_restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data;
|
||||
const util::NameTable &name_table;
|
||||
const SuffixTable &street_name_suffix_table;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const NodeBasedGraphWalker graph_walker; // for skipping traffic signal, distances etc.
|
||||
|
||||
// Decide on a basic turn types
|
||||
@@ -90,9 +96,6 @@ class IntersectionHandler
|
||||
const std::size_t begin,
|
||||
const std::size_t end) const;
|
||||
|
||||
// Checks the intersection for a through street connected to `intersection[index]`
|
||||
bool isThroughStreet(const std::size_t index, const Intersection &intersection) const;
|
||||
|
||||
// See `getNextIntersection`
|
||||
struct IntersectionViewAndNode final
|
||||
{
|
||||
@@ -567,11 +570,19 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// try to find whether there is a turn going to the opposite direction of our obvious
|
||||
// turn, this should be alright.
|
||||
const auto previous_intersection = [&]() -> IntersectionView {
|
||||
const auto parameters = intersection_generator.SkipDegreeTwoNodes(
|
||||
node_at_intersection, intersection[0].eid);
|
||||
if (node_based_graph.GetTarget(parameters.via_eid) == node_at_intersection)
|
||||
const auto parameters = intersection::skipDegreeTwoNodes(
|
||||
node_based_graph, {node_at_intersection, intersection[0].eid});
|
||||
if (node_based_graph.GetTarget(parameters.edge) == node_at_intersection)
|
||||
return {};
|
||||
return intersection_generator.GetConnectedRoads(parameters.nid, parameters.via_eid);
|
||||
|
||||
return intersection::getConnectedRoads<false>(node_based_graph,
|
||||
node_data_container,
|
||||
node_coordinates,
|
||||
compressed_geometries,
|
||||
node_restriction_map,
|
||||
barrier_nodes,
|
||||
turn_lanes_data,
|
||||
parameters);
|
||||
}();
|
||||
|
||||
if (!previous_intersection.empty())
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZATION_OPERATION_HPP_
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZATION_OPERATION_HPP_
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
struct IntersectionNormalizationOperation
|
||||
{
|
||||
// the source of the merge, not part of the intersection after the merge is performed.
|
||||
EdgeID merged_eid;
|
||||
// the edge that is covering the `merged_eid`
|
||||
EdgeID into_eid;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /*OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZATION_OPERATION_HPP_*/
|
||||
@@ -1,125 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
|
||||
|
||||
#include "util/attributes.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "extractor/guidance/coordinate_extractor.hpp"
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_normalization_operation.hpp"
|
||||
#include "extractor/guidance/mergable_road_detector.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
/*
|
||||
* An intersection is a central part in computing guidance decisions. However the model in OSM and
|
||||
* the view we want to use in guidance are not necessarily the same thing. We have to account for
|
||||
* some models that are chosen explicitly in OSM and that don't actually describe how a human would
|
||||
* experience an intersection.
|
||||
*
|
||||
* For example, if a small pedestrian island is located at a traffic light right in the middle of a
|
||||
* road, OSM tends to model the road as two separate ways. A human would consider these two ways a
|
||||
* single road, though. In this normalizer, we try to account for these subtle differences between
|
||||
* OSM data and human perception to improve our decision base for guidance later on.
|
||||
*/
|
||||
class IntersectionNormalizer
|
||||
{
|
||||
public:
|
||||
struct NormalizationResult
|
||||
{
|
||||
IntersectionShape normalized_shape;
|
||||
std::vector<IntersectionNormalizationOperation> performed_merges;
|
||||
};
|
||||
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
// The function takes an intersection an converts it to a `perceived` intersection which closer
|
||||
// represents how a human might experience the intersection
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
NormalizationResult operator()(const NodeID node_at_intersection,
|
||||
IntersectionShape intersection) const;
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const MergableRoadDetector mergable_road_detector;
|
||||
|
||||
/* check if two indices in an intersection can be seen as a single road in the perceived
|
||||
* intersection representation. See below for an example. Utility function for
|
||||
* MergeSegregatedRoads. It also checks for neighboring merges.
|
||||
* This is due possible segments where multiple roads could end up being merged into one.
|
||||
* We only support merging two roads, not three or more, though.
|
||||
* c c
|
||||
* / /
|
||||
* a - b -> a - b - (c,d) but not a - b d -> a,b,(cde)
|
||||
* \ \
|
||||
* d e
|
||||
*/
|
||||
bool CanMerge(const NodeID intersection_node,
|
||||
const IntersectionShape &intersection,
|
||||
std::size_t first_index,
|
||||
std::size_t second_index) const;
|
||||
|
||||
// Perform an Actual Merge
|
||||
IntersectionNormalizationOperation
|
||||
DetermineMergeDirection(const IntersectionShapeData &lhs,
|
||||
const IntersectionShapeData &rhs) const;
|
||||
IntersectionShapeData MergeRoads(const IntersectionShapeData &destination,
|
||||
const IntersectionShapeData &source) const;
|
||||
IntersectionShapeData MergeRoads(const IntersectionNormalizationOperation direction,
|
||||
const IntersectionShapeData &lhs,
|
||||
const IntersectionShapeData &rhs,
|
||||
const double opposite_bearing) const;
|
||||
|
||||
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
|
||||
// one.
|
||||
// This function combines roads the following way:
|
||||
//
|
||||
// * *
|
||||
// * is converted to *
|
||||
// v ^ +
|
||||
// v ^ +
|
||||
//
|
||||
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
|
||||
// 160
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
NormalizationResult MergeSegregatedRoads(const NodeID intersection_node,
|
||||
IntersectionShape intersection) const;
|
||||
|
||||
// The counterpiece to mergeSegregatedRoads. While we can adjust roads that split up at the
|
||||
// intersection itself, it can also happen that intersections are connected to joining roads.
|
||||
//
|
||||
// * *
|
||||
// * is converted to *
|
||||
// v a --- a ---
|
||||
// v ^ +
|
||||
// v ^ +
|
||||
// b
|
||||
//
|
||||
// for the local view of b at a.
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
IntersectionShape AdjustBearingsForMergeAtDestination(const NodeID node_at_intersection,
|
||||
IntersectionShape intersection) const;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_ */
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_IS_THROUGH_STREET_HPP_
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_IS_THROUGH_STREET_HPP_
|
||||
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
#include "util/guidance/name_announcements.hpp"
|
||||
|
||||
using osrm::util::angularDeviation;
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
template <typename IntersectionType>
|
||||
inline bool isThroughStreet(const std::size_t index,
|
||||
const IntersectionType &intersection,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
{
|
||||
|
||||
const auto &data_at_index = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(intersection[index].eid).annotation_data);
|
||||
|
||||
if (data_at_index.name_id == EMPTY_NAMEID)
|
||||
return false;
|
||||
|
||||
// a through street cannot start at our own position -> index 1
|
||||
for (std::size_t road_index = 1; road_index < intersection.size(); ++road_index)
|
||||
{
|
||||
if (road_index == index)
|
||||
continue;
|
||||
|
||||
const auto &road = intersection[road_index];
|
||||
const auto &road_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(road.eid).annotation_data);
|
||||
|
||||
// roads have a near straight angle (180 degree)
|
||||
const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) >
|
||||
(STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE);
|
||||
|
||||
const bool have_same_name = HaveIdenticalNames(
|
||||
data_at_index.name_id, road_data.name_id, name_table, street_name_suffix_table);
|
||||
|
||||
const bool have_same_category =
|
||||
node_based_graph.GetEdgeData(intersection[index].eid).flags.road_classification ==
|
||||
node_based_graph.GetEdgeData(road.eid).flags.road_classification;
|
||||
|
||||
if (is_nearly_straight && have_same_name && have_same_category)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /*OSRM_EXTRACTOR_GUIDANCE_IS_THROUGH_STREET_HPP_*/
|
||||
@@ -1,7 +1,12 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/coordinate_extractor.hpp"
|
||||
#include "extractor/guidance/have_identical_names.hpp"
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
@@ -9,6 +14,7 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
@@ -39,8 +45,10 @@ class MergableRoadDetector
|
||||
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const IntersectionGenerator &intersection_generator,
|
||||
const CoordinateExtractor &coordinate_extractor,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
@@ -71,11 +79,6 @@ class MergableRoadDetector
|
||||
bool IsDistinctFrom(const MergableRoadData &lhs, const MergableRoadData &rhs) const;
|
||||
|
||||
private:
|
||||
// check if two name ids can be seen as identical (in presence of refs/others)
|
||||
// in our case this translates into no name announcement in either direction (lhs->rhs and
|
||||
// rhs->lhs)
|
||||
bool HaveIdenticalNames(const NameID lhs, const NameID rhs) const;
|
||||
|
||||
// When it comes to merging roads, we need to find out if two ways actually represent the
|
||||
// same road. This check tries to identify roads which are the same road in opposite directions
|
||||
bool EdgeDataSupportsMerge(const NodeBasedEdgeClassification &lhs_flags,
|
||||
@@ -140,15 +143,38 @@ class MergableRoadDetector
|
||||
// The detector wants to prevent merges that are connected to `b-e`
|
||||
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
|
||||
|
||||
// The condition suppresses roads merging for intersections like
|
||||
// . .
|
||||
// . .
|
||||
// ---- ----
|
||||
// . .
|
||||
// . .
|
||||
// but will allow roads merging for intersections like
|
||||
// -------
|
||||
// / \
|
||||
// ---- ----
|
||||
// \ /
|
||||
// -------
|
||||
bool IsCircularShape(const NodeID intersection_node,
|
||||
const MergableRoadData &lhs,
|
||||
const MergableRoadData &rhs) const;
|
||||
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const CoordinateExtractor &coordinate_extractor;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const RestrictionMap &node_restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data;
|
||||
|
||||
// name detection
|
||||
const util::NameTable &name_table;
|
||||
const SuffixTable &street_name_suffix_table;
|
||||
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
|
||||
// limit for detecting circles / parallel roads
|
||||
const static double constexpr distance_to_extract = 120;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_MOTORWAY_HANDLER_HPP_
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/is_through_street.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
|
||||
#include "util/attributes.hpp"
|
||||
@@ -26,9 +26,12 @@ class MotorwayHandler : public IntersectionHandler
|
||||
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
~MotorwayHandler() override final = default;
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_NODE_BASED_GRAPH_WALKER
|
||||
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/coordinate_extractor.hpp"
|
||||
#include "extractor/guidance/turn_lane_data.hpp"
|
||||
#include "extractor/intersection/intersection_analysis.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
@@ -29,7 +31,11 @@ class NodeBasedGraphWalker
|
||||
public:
|
||||
NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data);
|
||||
|
||||
/*
|
||||
* the returned node-id, edge-id are either the last ones used, just prior accumulator
|
||||
@@ -48,7 +54,11 @@ class NodeBasedGraphWalker
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const RestrictionMap &node_restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -123,7 +133,8 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
|
||||
{
|
||||
SelectStraightmostRoadByNameAndOnlyChoice(const NameID desired_name_id,
|
||||
const double initial_bearing,
|
||||
const bool requires_entry);
|
||||
const bool requires_entry,
|
||||
const bool stop_on_ambiguous_turns);
|
||||
|
||||
/*
|
||||
* !! REQUIRED - Function for the use of TraverseRoad in the graph walker.
|
||||
@@ -141,13 +152,20 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
|
||||
const NameID desired_name_id;
|
||||
const double initial_bearing;
|
||||
const bool requires_entry;
|
||||
const bool stop_on_ambiguous_turns;
|
||||
};
|
||||
|
||||
// find the next intersection given a hop limit
|
||||
struct IntersectionFinderAccumulator
|
||||
{
|
||||
IntersectionFinderAccumulator(const std::uint8_t hop_limit,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data);
|
||||
// true if the path has traversed enough distance
|
||||
bool terminate();
|
||||
|
||||
@@ -157,13 +175,19 @@ struct IntersectionFinderAccumulator
|
||||
std::uint8_t hops;
|
||||
const std::uint8_t hop_limit;
|
||||
|
||||
// we need to be able to look-up the intersection
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
|
||||
// the result we are looking for
|
||||
NodeID nid;
|
||||
EdgeID via_edge_id;
|
||||
IntersectionView intersection;
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const RestrictionMap &node_restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data;
|
||||
};
|
||||
|
||||
template <class accumulator_type, class selector_type>
|
||||
@@ -197,9 +221,15 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
|
||||
return {};
|
||||
|
||||
// look at the next intersection
|
||||
const constexpr auto LOW_PRECISION = true;
|
||||
const auto next_intersection = intersection_generator.GetConnectedRoads(
|
||||
current_node_id, current_edge_id, LOW_PRECISION);
|
||||
const auto next_intersection =
|
||||
intersection::getConnectedRoads<true>(node_based_graph,
|
||||
node_data_container,
|
||||
node_coordinates,
|
||||
compressed_geometries,
|
||||
node_restriction_map,
|
||||
barrier_nodes,
|
||||
turn_lanes_data,
|
||||
{current_node_id, current_edge_id});
|
||||
|
||||
// don't follow u-turns or go past our initial intersection
|
||||
if (next_intersection.size() <= 1)
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/coordinate_extractor.hpp"
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/is_through_street.hpp"
|
||||
#include "extractor/guidance/roundabout_type.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
|
||||
@@ -42,10 +42,12 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
~RoundaboutHandler() override final = default;
|
||||
|
||||
@@ -64,10 +66,6 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
const EdgeID via_eid,
|
||||
const Intersection &intersection) const;
|
||||
|
||||
void invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
const EdgeID via_eid,
|
||||
Intersection &intersection) const;
|
||||
|
||||
// decide whether we lookk at a roundabout or a rotary
|
||||
RoundaboutType getRoundaboutType(const NodeID nid) const;
|
||||
|
||||
@@ -84,7 +82,6 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
bool
|
||||
qualifiesAsRoundaboutIntersection(const std::unordered_set<NodeID> &roundabout_nodes) const;
|
||||
|
||||
const CompressedEdgeContainer &compressed_edge_container;
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
class NameTable;
|
||||
}
|
||||
|
||||
namespace extractor
|
||||
{
|
||||
class NodeBasedGraphFactory;
|
||||
|
||||
namespace guidance
|
||||
{
|
||||
// Find all "segregated" edges, e.g. edges that can be skipped in turn instructions.
|
||||
// The main cases are:
|
||||
// - middle edges between two osm ways in one logic road (U-turn)
|
||||
// - staggered intersections (X-cross)
|
||||
// - square/circle intersections
|
||||
std::unordered_set<EdgeID> findSegregatedNodes(const NodeBasedGraphFactory &factory,
|
||||
const util::NameTable &names);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_SLIPROAD_HANDLER_HPP_
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/is_through_street.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
|
||||
#include "util/name_table.hpp"
|
||||
@@ -24,10 +24,13 @@ namespace guidance
|
||||
class SliproadHandler final : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
SliproadHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
SliproadHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
@@ -51,9 +54,6 @@ class SliproadHandler final : public IntersectionHandler
|
||||
// Next intersection from `start` onto `onto` is too far away for a Siproad scenario
|
||||
bool nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const;
|
||||
|
||||
// Through street: does a road continue with from's name at the intersection
|
||||
bool isThroughStreet(const EdgeID from, const IntersectionView &intersection) const;
|
||||
|
||||
// Does the road from `current` to `next` continue
|
||||
bool roadContinues(const EdgeID current, const EdgeID next) const;
|
||||
|
||||
@@ -78,6 +78,8 @@ class SliproadHandler final : public IntersectionHandler
|
||||
// The return value is guaranteed to not be larger than `threshold`.
|
||||
static double scaledThresholdByRoadClass(const double max_threshold,
|
||||
const RoadClassification &classification);
|
||||
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#ifndef OSRM_EXTRACTOR_GUIDANCE_STATISTICS_HANDLER_HPP_
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_STATISTICS_HANDLER_HPP_
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
|
||||
#include "util/log.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
// Unconditionally runs over all intersections and gathers statistics for
|
||||
// instruction turn types and direction modifiers (see turn_instruction.hpp).
|
||||
class StatisticsHandler final : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
StatisticsHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
compressed_geometries,
|
||||
node_restriction_map,
|
||||
barrier_nodes,
|
||||
turn_lanes_data,
|
||||
name_table,
|
||||
street_name_suffix_table)
|
||||
{
|
||||
}
|
||||
|
||||
~StatisticsHandler() override final
|
||||
{
|
||||
const auto add_second = [](const auto acc, const auto &kv) { return acc + kv.second; };
|
||||
|
||||
const auto num_types =
|
||||
std::accumulate(begin(type_hist), end(type_hist), std::uint64_t{0}, add_second);
|
||||
const auto num_modifiers =
|
||||
std::accumulate(begin(modifier_hist), end(modifier_hist), std::uint64_t{0}, add_second);
|
||||
|
||||
util::Log() << "Assigned " << num_types << " turn instruction types:";
|
||||
|
||||
for (const auto &kv : type_hist)
|
||||
if (kv.second > 0)
|
||||
util::Log() << " " << std::fixed << std::setprecision(2)
|
||||
<< internalInstructionTypeToString(kv.first) << ": " << kv.second
|
||||
<< " (" << (kv.second / static_cast<float>(num_types) * 100.) << "%)";
|
||||
|
||||
util::Log() << "Assigned " << num_modifiers << " turn instruction modifiers:";
|
||||
|
||||
for (const auto &kv : modifier_hist)
|
||||
if (kv.second > 0)
|
||||
util::Log() << " " << std::fixed << std::setprecision(2)
|
||||
<< instructionModifierToString(kv.first) << ": " << kv.second << " ("
|
||||
<< (kv.second / static_cast<float>(num_modifiers) * 100.) << "%)";
|
||||
}
|
||||
|
||||
bool canProcess(const NodeID, const EdgeID, const Intersection &) const override final
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Intersection
|
||||
operator()(const NodeID, const EdgeID, Intersection intersection) const override final
|
||||
{
|
||||
// Lock histograms updates on a per-intersection basis.
|
||||
std::lock_guard<std::mutex> defer{lock};
|
||||
|
||||
// Generate histograms for all roads; this way we will get duplicates
|
||||
// which we would not get doing it after EBF generation. But we want
|
||||
// numbers closer to the handlers and see how often handlers ran.
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
if (road.entry_allowed)
|
||||
{
|
||||
const auto type = road.instruction.type;
|
||||
const auto modifier = road.instruction.direction_modifier;
|
||||
|
||||
type_hist[type] += 1;
|
||||
modifier_hist[modifier] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::mutex lock;
|
||||
mutable std::map<TurnType::Enum, std::uint64_t> type_hist;
|
||||
mutable std::map<DirectionModifier::Enum, std::uint64_t> modifier_hist;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_GUIDANCE_VALIDATION_HANDLER_HPP_
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
@@ -21,10 +20,13 @@ namespace guidance
|
||||
class SuppressModeHandler final : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
SuppressModeHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
SuppressModeHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/driveway_handler.hpp"
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_normalization_operation.hpp"
|
||||
#include "extractor/guidance/intersection_normalizer.hpp"
|
||||
#include "extractor/guidance/motorway_handler.hpp"
|
||||
#include "extractor/guidance/roundabout_handler.hpp"
|
||||
#include "extractor/guidance/sliproad_handler.hpp"
|
||||
#include "extractor/guidance/statistics_handler.hpp"
|
||||
#include "extractor/guidance/suppress_mode_handler.hpp"
|
||||
#include "extractor/guidance/turn_classification.hpp"
|
||||
#include "extractor/guidance/turn_handler.hpp"
|
||||
@@ -42,10 +40,11 @@ class TurnAnalysis
|
||||
public:
|
||||
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
@@ -55,40 +54,21 @@ class TurnAnalysis
|
||||
Intersection operator()(const NodeID node_prior_to_intersection,
|
||||
const EdgeID entering_via_edge) const;
|
||||
|
||||
/*
|
||||
* Returns a normalized intersection without any assigned turn types.
|
||||
* This intersection can be used as input for intersection classification, turn lane assignment
|
||||
* and similar.
|
||||
*/
|
||||
struct ShapeResult
|
||||
{
|
||||
// the basic shape, containing all turns
|
||||
IntersectionShape intersection_shape;
|
||||
// normalized shape, merged some roads into others, adjusted bearings
|
||||
// see intersection_normalizer for further explanations
|
||||
IntersectionNormalizer::NormalizationResult annotated_normalized_shape;
|
||||
};
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
ShapeResult ComputeIntersectionShapes(const NodeID node_at_center_of_intersection) const;
|
||||
|
||||
// Select turn types based on the intersection shape
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
Intersection AssignTurnTypes(const NodeID from_node,
|
||||
const EdgeID via_eid,
|
||||
const IntersectionView &intersection) const;
|
||||
|
||||
const IntersectionGenerator &GetIntersectionGenerator() const;
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const IntersectionGenerator intersection_generator;
|
||||
const IntersectionNormalizer intersection_normalizer;
|
||||
const RoundaboutHandler roundabout_handler;
|
||||
const MotorwayHandler motorway_handler;
|
||||
const TurnHandler turn_handler;
|
||||
const SliproadHandler sliproad_handler;
|
||||
const SuppressModeHandler suppress_mode_handler;
|
||||
const DrivewayHandler driveway_handler;
|
||||
const StatisticsHandler statistics_handler;
|
||||
|
||||
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
||||
Intersection
|
||||
|
||||
@@ -2,15 +2,27 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_TURN_DISCOVERY_HPP_
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/turn_lane_data.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
struct Coordinate;
|
||||
}
|
||||
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
class CompressedEdgeContainer;
|
||||
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
namespace lanes
|
||||
{
|
||||
|
||||
@@ -21,8 +33,13 @@ bool findPreviousIntersection(
|
||||
const NodeID node,
|
||||
const EdgeID via_edge,
|
||||
const Intersection &intersection,
|
||||
const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph, // query edge data
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
// output parameters, will be in an arbitrary state on failure
|
||||
NodeID &result_node,
|
||||
EdgeID &result_via_edge,
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_TURN_HANDLER_HPP_
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/is_through_street.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
|
||||
#include "util/attributes.hpp"
|
||||
@@ -30,9 +30,12 @@ class TurnHandler : public IntersectionHandler
|
||||
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
~TurnHandler() override final = default;
|
||||
|
||||
|
||||
@@ -77,7 +77,11 @@ struct TurnInstruction
|
||||
|
||||
TurnType::Enum type : 5;
|
||||
DirectionModifier::Enum direction_modifier : 3;
|
||||
// the lane tupel that is used for the turn
|
||||
|
||||
bool IsUTurn() const
|
||||
{
|
||||
return type != TurnType::NoTurn && direction_modifier == DirectionModifier::UTurn;
|
||||
}
|
||||
|
||||
static TurnInstruction INVALID() { return {TurnType::Invalid, DirectionModifier::UTurn}; }
|
||||
|
||||
@@ -309,6 +313,86 @@ inline DirectionModifier::Enum bearingToDirectionModifier(const double bearing)
|
||||
return extractor::guidance::DirectionModifier::Left;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
const constexpr char *modifier_names[] = {"uturn",
|
||||
"sharp right",
|
||||
"right",
|
||||
"slight right",
|
||||
"straight",
|
||||
"slight left",
|
||||
"left",
|
||||
"sharp left"};
|
||||
|
||||
/**
|
||||
* Human readable values for TurnType enum values
|
||||
*/
|
||||
struct TurnTypeName
|
||||
{
|
||||
// String value we return with our API
|
||||
const char *external_name;
|
||||
// Internal only string name for the turn type - useful for debugging
|
||||
// and used by debug tiles for visualizing hidden turn types
|
||||
const char *internal_name;
|
||||
};
|
||||
|
||||
// Indexes in this list correspond to the Enum values of osrm::extractor::guidance::TurnType
|
||||
const constexpr TurnTypeName turn_type_names[] = {
|
||||
{"invalid", "(not set)"},
|
||||
{"new name", "new name"},
|
||||
{"continue", "continue"},
|
||||
{"turn", "turn"},
|
||||
{"merge", "merge"},
|
||||
{"on ramp", "on ramp"},
|
||||
{"off ramp", "off ramp"},
|
||||
{"fork", "fork"},
|
||||
{"end of road", "end of road"},
|
||||
{"notification", "notification"},
|
||||
{"roundabout", "enter roundabout"},
|
||||
{"exit roundabout", "enter and exit roundabout"},
|
||||
{"rotary", "enter rotary"},
|
||||
{"exit rotary", "enter and exit rotary"},
|
||||
{"roundabout turn", "enter roundabout turn"},
|
||||
{"roundabout turn", "enter and exit roundabout turn"},
|
||||
{"use lane", "use lane"},
|
||||
{"invalid", "(noturn)"},
|
||||
{"invalid", "(suppressed)"},
|
||||
{"roundabout", "roundabout"},
|
||||
{"exit roundabout", "exit roundabout"},
|
||||
{"rotary", "rotary"},
|
||||
{"exit rotary", "exit rotary"},
|
||||
{"roundabout turn", "roundabout turn"},
|
||||
{"exit roundabout", "exit roundabout turn"},
|
||||
{"invalid", "(stay on roundabout)"},
|
||||
{"invalid", "(sliproad)"}};
|
||||
|
||||
} // ns detail
|
||||
|
||||
inline std::string instructionTypeToString(const TurnType::Enum type)
|
||||
{
|
||||
static_assert(sizeof(detail::turn_type_names) / sizeof(detail::turn_type_names[0]) >=
|
||||
TurnType::MaxTurnType,
|
||||
"Some turn types have no string representation.");
|
||||
return detail::turn_type_names[static_cast<std::size_t>(type)].external_name;
|
||||
}
|
||||
|
||||
inline std::string internalInstructionTypeToString(const TurnType::Enum type)
|
||||
{
|
||||
static_assert(sizeof(detail::turn_type_names) / sizeof(detail::turn_type_names[0]) >=
|
||||
TurnType::MaxTurnType,
|
||||
"Some turn types have no string representation.");
|
||||
return detail::turn_type_names[static_cast<std::size_t>(type)].internal_name;
|
||||
}
|
||||
|
||||
inline std::string instructionModifierToString(const DirectionModifier::Enum modifier)
|
||||
{
|
||||
static_assert(sizeof(detail::modifier_names) / sizeof(detail::modifier_names[0]) >=
|
||||
DirectionModifier::MaxDirectionModifier,
|
||||
"Some direction modifiers have no string representation.");
|
||||
return detail::modifier_names[static_cast<std::size_t>(modifier)];
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
@@ -74,6 +74,11 @@ class TurnLaneHandler
|
||||
|
||||
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
LaneDescriptionMap &lane_description_map,
|
||||
const TurnAnalysis &turn_analysis,
|
||||
util::guidance::LaneDataIdMap &id_map);
|
||||
@@ -90,6 +95,12 @@ class TurnLaneHandler
|
||||
// lanes for a turn
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const RestrictionMap &node_restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data;
|
||||
|
||||
std::vector<std::uint32_t> turn_lane_offsets;
|
||||
std::vector<TurnLaneType::Mask> turn_lane_masks;
|
||||
LaneDescriptionMap &lane_description_map;
|
||||
|
||||
@@ -100,8 +100,10 @@ typedef util::ConcurrentIDMap<guidance::TurnLaneDescription,
|
||||
guidance::TurnLaneDescription_hash>
|
||||
LaneDescriptionMap;
|
||||
|
||||
inline std::tuple<std::vector<std::uint32_t>, std::vector<TurnLaneType::Mask>>
|
||||
transformTurnLaneMapIntoArrays(const LaneDescriptionMap &turn_lane_map)
|
||||
using TurnLanesIndexedArray =
|
||||
std::tuple<std::vector<std::uint32_t>, std::vector<TurnLaneType::Mask>>;
|
||||
|
||||
inline TurnLanesIndexedArray transformTurnLaneMapIntoArrays(const LaneDescriptionMap &turn_lane_map)
|
||||
{
|
||||
// could use some additional capacity? To avoid a copy during processing, though small data so
|
||||
// probably not that important.
|
||||
@@ -111,8 +113,7 @@ transformTurnLaneMapIntoArrays(const LaneDescriptionMap &turn_lane_map)
|
||||
//
|
||||
// turn lane offsets points into the locations of the turn_lane_masks array. We use a standard
|
||||
// adjacency array like structure to store the turn lane masks.
|
||||
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.data.size() +
|
||||
2); // empty ID + sentinel
|
||||
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.data.size() + 1); // + sentinel
|
||||
for (auto entry = turn_lane_map.data.begin(); entry != turn_lane_map.data.end(); ++entry)
|
||||
turn_lane_offsets[entry->second + 1] = entry->first.size();
|
||||
|
||||
@@ -125,6 +126,7 @@ transformTurnLaneMapIntoArrays(const LaneDescriptionMap &turn_lane_map)
|
||||
std::copy(entry->first.begin(),
|
||||
entry->first.end(),
|
||||
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
|
||||
|
||||
return std::make_tuple(std::move(turn_lane_offsets), std::move(turn_lane_masks));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#ifndef OSRM_EXTRACTOR_INTERSECTION_INTERSECTION_ANALYSIS_HPP
|
||||
#define OSRM_EXTRACTOR_INTERSECTION_INTERSECTION_ANALYSIS_HPP
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/mergable_road_detector.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/intersection/intersection_edge.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace intersection
|
||||
{
|
||||
|
||||
IntersectionEdges getIncomingEdges(const util::NodeBasedDynamicGraph &graph,
|
||||
const NodeID intersection);
|
||||
|
||||
IntersectionEdges getOutgoingEdges(const util::NodeBasedDynamicGraph &graph,
|
||||
const NodeID intersection);
|
||||
|
||||
bool isTurnAllowed(const util::NodeBasedDynamicGraph &graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const IntersectionEdgeGeometries &geometries,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const IntersectionEdge &from,
|
||||
const IntersectionEdge &to);
|
||||
|
||||
double findEdgeBearing(const IntersectionEdgeGeometries &geometries, const EdgeID &edge);
|
||||
|
||||
double findEdgeLength(const IntersectionEdgeGeometries &geometries, const EdgeID &edge);
|
||||
|
||||
std::pair<IntersectionEdgeGeometries, std::unordered_set<EdgeID>>
|
||||
getIntersectionGeometries(const util::NodeBasedDynamicGraph &graph,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const guidance::MergableRoadDetector &detector,
|
||||
const NodeID intersection);
|
||||
|
||||
guidance::IntersectionView
|
||||
convertToIntersectionView(const util::NodeBasedDynamicGraph &graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const IntersectionEdgeGeometries &edge_geometries,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const IntersectionEdge &incoming_edge,
|
||||
const IntersectionEdges &outgoing_edges,
|
||||
const std::unordered_set<EdgeID> &merged_edges);
|
||||
|
||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
||||
// the node reached from `incoming_edge`. The resulting candidates have to be analyzed
|
||||
// for their actual instructions later on.
|
||||
template <bool USE_CLOSE_COORDINATE>
|
||||
guidance::IntersectionView
|
||||
getConnectedRoads(const util::NodeBasedDynamicGraph &graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const guidance::TurnLanesIndexedArray &turn_lanes_data,
|
||||
const IntersectionEdge &incoming_edge);
|
||||
|
||||
// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
|
||||
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
|
||||
// intermediate intersection, if there is a traffic light in between. If we want to look farther
|
||||
// down a road, finding the next actual decision requires the look at multiple intersections.
|
||||
// Here we follow the road until we either reach a dead end or find the next intersection with
|
||||
// more than a single next road. This function skips over degree two nodes to find correct input
|
||||
// for getConnectedRoads.
|
||||
IntersectionEdge skipDegreeTwoNodes(const util::NodeBasedDynamicGraph &graph,
|
||||
IntersectionEdge road);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef OSRM_EXTRACTOR_INTERSECTION_INTERSECTION_EDGE_HPP
|
||||
#define OSRM_EXTRACTOR_INTERSECTION_INTERSECTION_EDGE_HPP
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace intersection
|
||||
{
|
||||
|
||||
// IntersectionEdge is an alias for incoming and outgoing node-based graph edges of an intersection
|
||||
struct IntersectionEdge
|
||||
{
|
||||
NodeID node;
|
||||
EdgeID edge;
|
||||
|
||||
bool operator<(const IntersectionEdge &other) const
|
||||
{
|
||||
return std::tie(node, edge) < std::tie(other.node, other.edge);
|
||||
}
|
||||
};
|
||||
|
||||
using IntersectionEdges = std::vector<IntersectionEdge>;
|
||||
|
||||
struct IntersectionEdgeGeometry
|
||||
{
|
||||
EdgeID edge;
|
||||
double initial_bearing;
|
||||
double perceived_bearing;
|
||||
double length;
|
||||
|
||||
bool operator<(const IntersectionEdgeGeometry &other) const { return edge < other.edge; }
|
||||
};
|
||||
|
||||
using IntersectionEdgeGeometries = std::vector<IntersectionEdgeGeometry>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -71,6 +71,16 @@ struct NodeBasedEdgeAnnotation
|
||||
std::tie(name_id, classes, travel_mode, is_left_hand_driving) ==
|
||||
std::tie(other.name_id, other.classes, other.travel_mode, other.is_left_hand_driving));
|
||||
}
|
||||
|
||||
bool operator<(const NodeBasedEdgeAnnotation &other) const
|
||||
{
|
||||
return (std::tie(name_id, lane_description_id, classes, travel_mode, is_left_hand_driving) <
|
||||
std::tie(other.name_id,
|
||||
other.lane_description_id,
|
||||
other.classes,
|
||||
other.travel_mode,
|
||||
other.is_left_hand_driving));
|
||||
}
|
||||
};
|
||||
|
||||
struct NodeBasedEdge
|
||||
|
||||
@@ -44,6 +44,10 @@ class NodeBasedGraphFactory
|
||||
auto const &GetGraph() const { return compressed_output_graph; }
|
||||
auto const &GetBarriers() const { return barriers; }
|
||||
auto const &GetTrafficSignals() const { return traffic_signals; }
|
||||
auto const &GetCompressedEdges() const { return compressed_edge_container; }
|
||||
auto const &GetCoordinates() const { return coordinates; }
|
||||
auto const &GetAnnotationData() const { return annotation_data; }
|
||||
auto const &GetOsmNodes() const { return osm_node_ids; }
|
||||
auto &GetCompressedEdges() { return compressed_edge_container; }
|
||||
auto &GetCoordinates() { return coordinates; }
|
||||
auto &GetAnnotationData() { return annotation_data; }
|
||||
@@ -75,7 +79,7 @@ class NodeBasedGraphFactory
|
||||
// unreferenced entries
|
||||
void CompressAnnotationData();
|
||||
|
||||
// After produce, this will contain a compresse version of the node-based graph
|
||||
// After produce, this will contain a compressed version of the node-based graph
|
||||
util::NodeBasedDynamicGraph compressed_output_graph;
|
||||
// To store the meta-data for the graph that is purely annotative / not used for the navigation
|
||||
// itself. Since the edges of a node-based graph form the nodes of the edge based graphs, we
|
||||
|
||||
@@ -77,6 +77,8 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
return annotation_data[nodes[node_id].annotation_id].is_left_hand_driving;
|
||||
}
|
||||
|
||||
bool IsSegregated(const NodeID node_id) const { return nodes[node_id].segregated; }
|
||||
|
||||
NameID GetNameID(const NodeID node_id) const
|
||||
{
|
||||
return annotation_data[nodes[node_id].annotation_id].name_id;
|
||||
@@ -105,13 +107,8 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
// between a large set of nodes
|
||||
AnnotationID NumberOfAnnotations() const { return annotation_data.size(); }
|
||||
|
||||
EdgeBasedNode &GetNode(const NodeID node_id) { return nodes[node_id]; }
|
||||
EdgeBasedNode const &GetNode(const NodeID node_id) const { return nodes[node_id]; }
|
||||
|
||||
NodeBasedEdgeAnnotation &GetAnnotation(const AnnotationID annotation)
|
||||
{
|
||||
return annotation_data[annotation];
|
||||
}
|
||||
NodeBasedEdgeAnnotation const &GetAnnotation(const AnnotationID annotation) const
|
||||
{
|
||||
return annotation_data[annotation];
|
||||
|
||||
@@ -21,7 +21,7 @@ struct OriginalEdgeData
|
||||
LaneDataID lane_data_id,
|
||||
guidance::TurnInstruction turn_instruction,
|
||||
EntryClassID entry_classid,
|
||||
TravelMode travel_mode,
|
||||
extractor::TravelMode travel_mode,
|
||||
util::guidance::TurnBearing pre_turn_bearing,
|
||||
util::guidance::TurnBearing post_turn_bearing)
|
||||
: via_geometry(via_geometry), name_id(name_id), entry_classid(entry_classid),
|
||||
@@ -34,7 +34,8 @@ struct OriginalEdgeData
|
||||
: via_geometry{std::numeric_limits<unsigned>::max() >> 1, false},
|
||||
name_id(std::numeric_limits<unsigned>::max()), entry_classid(INVALID_ENTRY_CLASSID),
|
||||
lane_data_id(INVALID_LANE_DATAID), turn_instruction(guidance::TurnInstruction::INVALID()),
|
||||
travel_mode(TRAVEL_MODE_INACCESSIBLE), pre_turn_bearing(0.0), post_turn_bearing(0.0)
|
||||
travel_mode(extractor::TRAVEL_MODE_INACCESSIBLE), pre_turn_bearing(0.0),
|
||||
post_turn_bearing(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,7 +44,7 @@ struct OriginalEdgeData
|
||||
EntryClassID entry_classid;
|
||||
LaneDataID lane_data_id;
|
||||
guidance::TurnInstruction turn_instruction;
|
||||
TravelMode travel_mode;
|
||||
extractor::TravelMode travel_mode;
|
||||
util::guidance::TurnBearing pre_turn_bearing;
|
||||
util::guidance::TurnBearing post_turn_bearing;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user