Compare commits

..

6 Commits

Author SHA1 Message Date
Daniel Patterson 356bab9fcb Prepare for alpha release. 2017-08-17 17:38:50 -07:00
Moritz Kobitzsch 314bf51465 format 2017-08-17 17:10:00 -07:00
Moritz Kobitzsch 5dc31252ef remove debug output 2017-08-17 17:10:00 -07:00
Moritz Kobitzsch 8ec3c83d82 emit exit roundabout on turns only when mode changes 2017-08-17 17:09:58 -07:00
Moritz Kobitzsch 8319a96aed format 2017-08-17 17:09:28 -07:00
Moritz Kobitzsch 28ddd983b3 use enter + exit for roundabout instructions 2017-08-17 17:09:26 -07:00
595 changed files with 17047 additions and 30262 deletions
-1
View File
@@ -13,4 +13,3 @@
!profiles/*
!profiles/lib/*
!profiles/examples/*
!scripts/node_install.sh
+28 -48
View File
@@ -7,13 +7,16 @@ git:
sudo: required
dist: trusty
node_js:
- "4"
- "6"
notifications:
email: false
branches:
only:
- master
- "5.13"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@@ -69,34 +72,25 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev', 'lcov']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
before_script:
- cd ${TRAVIS_BUILD_DIR}
- lcov --directory . --zerocounters # clean cached da files
after_success:
# Creating report
- cd ${TRAVIS_BUILD_DIR}
- lcov --directory . --capture --output-file coverage.info # capture coverage info
- lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter out system
- lcov --list coverage.info #debug info
# Uploading report to CodeCov
- bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports"
- bash <(curl -s https://codecov.io/bash)
- os: linux
compiler: "gcc-6-debug-asan"
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000 LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
- os: linux
compiler: "clang-4.0-debug"
addons: &clang40
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
@@ -104,8 +98,8 @@ matrix:
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_SANITIZER=ON LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
# Release Builds
- os: linux
@@ -113,7 +107,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
- os: linux
@@ -121,7 +115,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
- os: linux
@@ -135,7 +129,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On
- os: linux
@@ -143,22 +137,14 @@ matrix:
addons: &gcc49
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev', 'ccache']
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
- os: osx
osx_image: xcode8.2
compiler: "mason-osx-release"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="4"
after_success:
- ./scripts/travis/publish.sh
- os: osx
osx_image: xcode8.2
compiler: "mason-osx-release"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="6"
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
after_success:
- ./scripts/travis/publish.sh
@@ -168,7 +154,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release'
# Shared Library
@@ -177,7 +163,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Disabled because CI slowness
@@ -186,7 +172,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Node build jobs. These skip running the tests.
@@ -196,7 +182,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
@@ -205,8 +191,7 @@ matrix:
-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
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -220,7 +205,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
@@ -229,8 +214,7 @@ matrix:
-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
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -244,7 +228,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
@@ -253,8 +237,7 @@ matrix:
-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
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -268,7 +251,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
@@ -277,8 +260,7 @@ matrix:
-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
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -352,8 +334,7 @@ install:
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
-DBUILD_TOOLS=ON \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-OFF}
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- echo "travis_fold:start:MAKE"
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
@@ -380,7 +361,6 @@ script:
- pushd ${OSRM_BUILD_DIR}
- ./unit_tests/library-tests
- ./unit_tests/extractor-tests
- ./unit_tests/contractor-tests
- ./unit_tests/engine-tests
- ./unit_tests/util-tests
- ./unit_tests/server-tests
+3 -53
View File
@@ -1,55 +1,5 @@
# 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`
- Support of `distance` weight in foot and bicycle profiles
- Support of relations processing
- Added `way:get_location_tag(key)` method to get location-dependent tags https://github.com/Project-OSRM/osrm-backend/wiki/Using-location-dependent-data-in-profiles
- Added `forward_ref` and `backward_ref` support
- Left-side driving mode is specified by a local Boolean flag `is_left_hand_driving` in `ExtractionWay` and `ExtractionTurn`
- Support literal values for maxspeeds in NO, PL and ZA
- Infrastructure:
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
- Fixed pkg-config version of OSRM
- Removed `.osrm.core` file since CoreCH is deprecated now.
- Tools:
- Because of boost/program_options#32 with boost 1.65+ we needed to change the behavior of the following flags to not accept `={true|false}` anymore:
- `--use-locations-cache=false` becomes `--disable-location-cache`
- `--parse-conditional-restrictions=true` becomes `--parse-conditional-restrictions`
- The deprecated options `--use-level-cache` and `--generate-edge-lookup`
- Bugfixes:
- Fixed #4348: Some cases of sliproads pre-processing were broken
- Fixed #4331: Correctly compute left/right modifiers of forks in case the fork is curved.
- Fixed #4472: Correctly count the number of lanes using the delimter in `turn:lanes` tag.
- Fixed #4214: Multiple runs of `osrm-partition` lead to crash.
- Fixed #4348: Fix assorted problems around slip roads.
- Fixed #4420: A bug that would result in unnecessary instructions, due to problems in suffix/prefix detection
- Algorithm
- Deprecate CoreCH functionality. Usage of CoreCH specific options will fall back to using CH with core_factor of 1.0
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices which yields speedup.
# 5.12.0
- Changes from 5.11:
- Guidance
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways)
- Adds new instruction types at the exit of roundabouts and rotaries `exit roundabout` and `exit rotary`.
- HTTP:
- New query parameter for route/table/match/trip plugings:
`exclude=` that can be used to exclude certain classes (e.g. exclude=motorway, exclude=toll).
This is configurable in the profile.
- NodeJS:
- New query option `exclude` for the route/table/match/trip plugins. (e.g. `exclude: ["motorway", "toll"]`)
- Profile:
- New property for profile table: `excludable` that can be used to configure which classes are excludable at query time.
- New optional property for profile table: `classes` that allows you to specify which classes you expect to be used.
We recommend this for better error messages around classes, otherwise the possible class names are infered automatically.
- Traffic:
- If traffic data files contain an empty 4th column, they will update edge durations but not modify the edge weight. This is useful for
updating ETAs returned, without changing route selection (for example, in a distance-based profile with traffic data loaded).
- Infrastructure:
- New file `.osrm.cell_metrics` created by `osrm-customize`.
- Debug tiles:
- Added new properties `type` and `modifier` to `turns` layer, useful for viewing guidance calculated turn types on the map
# UNRELEASED
- Adds new instruction types at the exit of roundabouts and rotaries `exit roundabout` and `exit rotary`.
# 5.11.0
- Changes from 5.10:
@@ -92,7 +42,7 @@
- Bugfixes
- Properly save/retrieve datasource annotations for road segments ([#4346](https://github.com/Project-OSRM/osrm-backend/issues/4346)
- Fix conditional restriction grammer parsing so it works for single-day-of-week restrictions ([#4357](https://github.com/Project-OSRM/osrm-backend/pull/4357))
- Algorithm
- Algorithm)
- BREAKING: the file format requires re-processing due to the changes on via-ways
- Added support for via-way restrictions
+44 -31
View File
@@ -31,13 +31,12 @@ option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
option(ENABLE_GLIBC_WORKAROUND "Workaround GLIBC symbol exports" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
if(ENABLE_MASON)
# versions in use
set(MASON_BOOST_VERSION "1.65.1")
set(MASON_BOOST_VERSION "1.63.0")
set(MASON_STXXL_VERSION "1.4.1-1")
set(MASON_EXPAT_VERSION "2.2.0")
set(MASON_LUA_VERSION "5.2.4")
@@ -61,7 +60,7 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 13)
set(OSRM_VERSION_MINOR 12)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
@@ -212,19 +211,19 @@ endif()
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "Configuring debug mode flags")
set(ENABLE_ASSERTIONS ON)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline -fno-omit-frame-pointer")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb")
else()
# Don't override the -O parameter for RelWithDebInfo, we want an optimized build
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
endif()
endif()
endif()
endif()
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fno-inline -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-inline -fno-omit-frame-pointer")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ggdb")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -ggdb")
endif()
if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "Configuring release mode optimizations")
# Check if LTO is available
@@ -304,11 +303,10 @@ if (ENABLE_COVERAGE)
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
message(ERROR "ENABLE_COVERAGE=ON only make sense with a Debug build")
endif()
message(STATUS "Enabling coverage")
message(INFO "Enabling coverage")
set(MAYBE_COVERAGE_LIBRARIES "-lgcov")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ftest-coverage -fprofile-arcs")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
endif()
if (ENABLE_SANITIZER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -fsanitize=address")
@@ -381,8 +379,8 @@ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
# Activate C++1y
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++14")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y")
endif()
# Configuring other platform dependencies
@@ -470,7 +468,7 @@ if(ENABLE_MASON)
install(FILES ${TBBGlob} DESTINATION lib)
endforeach()
if(APPLE)
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} -Wl,-rpath -Wl,@loader_path")
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} -Wl,-rpath -Wl,@executable_path")
elseif(UNIX)
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} '-Wl,-rpath,$ORIGIN' -Wl,-z,origin")
endif()
@@ -519,10 +517,29 @@ else()
find_package(BZip2 REQUIRED)
add_dependency_includes(${BZIP2_INCLUDE_DIR})
find_package(Lua 5.2 REQUIRED)
if (LUA_FOUND)
message(STATUS "Using Lua ${LUA_VERSION_STRING}")
endif()
FIND_PACKAGE(Lua 5.2 EXACT)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
FIND_PACKAGE(Lua 5.1 EXACT)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
# Now fall back to a lua verison without exact
# in case this cmake version also forces patch versions
FIND_PACKAGE(Lua 5.2)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
FIND_PACKAGE(Lua 5.1)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
MESSAGE(FATAL_ERROR "Lua 5.1 or 5.2 was not found.")
ENDIF()
ENDIF()
ENDIF()
ENDIF()
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
add_dependency_includes(${LUA_INCLUDE_DIR})
@@ -675,10 +692,10 @@ set(UTIL_LIBRARIES
# Libraries
target_link_libraries(osrm ${ENGINE_LIBRARIES})
target_link_libraries(osrm_update ${UPDATER_LIBRARIES})
target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES} osrm_update osrm_store)
target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES} osrm_update)
target_link_libraries(osrm_extract ${EXTRACTOR_LIBRARIES})
target_link_libraries(osrm_partition ${PARTITIONER_LIBRARIES})
target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update osrm_store)
target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update)
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
# BUILD_COMPONENTS
@@ -721,7 +738,7 @@ file(GLOB VariantGlob third_party/variant/include/mapbox/*.hpp)
file(GLOB LibraryGlob include/osrm/*.hpp)
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/approach.hpp include/engine/phantom_node.hpp)
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/alias.hpp include/util/exception.hpp include/util/bearing.hpp)
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/alias.hpp include/util/exception.hpp)
set(ExtractorHeader include/extractor/extractor.hpp include/storage/io_config.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
set(PartitionerHeader include/partition/partitioner.hpp include/partition/partition_config.hpp)
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
@@ -812,10 +829,6 @@ add_custom_target(uninstall
add_subdirectory(unit_tests)
add_subdirectory(src/benchmarks)
if (ENABLE_GLIBC_WORKAROUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLIBC_WORKAROUND")
endif()
if (ENABLE_NODE_BINDINGS)
add_subdirectory(src/nodejs)
endif()
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+25 -16
View File
@@ -41,14 +41,6 @@ Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
The easiest and quickest way to setup your own routing engine is to use Docker images we provide.
There are two pre-processing pipelines available:
- Contraction Hierarchies (CH)
- Multi-Level Dijkstra (MLD)
we recommend using MLD by default except for special use-cases such as very large distance matrices where CH is still a better fit for the time being.
In the following we explain the MLD pipeline.
If you want to use the CH pipeline instead replace `osrm-partition` and `osrm-customize` with a single `osrm-contract` and change the algorithm option for `osrm-routed` to `--algorithm ch`.
### Using Docker
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
@@ -60,10 +52,9 @@ Download OpenStreetMap extracts for example from [Geofabrik](http://download.geo
Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-partition /data/berlin-latest.osrm
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-customize /data/berlin-latest.osrm
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed --algorithm mld /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
Make requests against the HTTP server
@@ -99,8 +90,8 @@ Install dependencies
```bash
sudo apt install build-essential git cmake pkg-config \
libbz2-dev libxml2-dev libzip-dev libboost-all-dev \
lua5.2 liblua5.2-dev libtbb-dev
libbz2-dev libstxxl-dev libstxxl1v5 libxml2-dev \
libzip-dev libboost-all-dev lua5.2 liblua5.2-dev libtbb-dev
```
Compile and install OSRM binaries
@@ -113,6 +104,26 @@ cmake --build .
sudo cmake --build . --target install
```
Grab a `.osm.pbf` extract from [Geofabrik](http://download.geofabrik.de/index.html) or [Mapzen's Metro Extracts](https://mapzen.com/data/metro-extracts/)
```bash
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
```
Pre-process the extract and start the HTTP server
```
osrm-extract berlin-latest.osm.pbf -p profiles/car.lua
osrm-contract berlin-latest.osrm
osrm-routed berlin-latest.osrm
```
Running Queries
```
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
```
### Request Against the Demo Server
Read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy).
@@ -146,9 +157,7 @@ which will check and use pre-built binaries if they're available for this releas
to always force building the Node.js bindings from source.
For usage details have a look [these API docs](docs/nodejs/api.md).
An exemplary implementation by a 3rd party with Docker and Node.js can be found [here](https://github.com/door2door-io/osrm-express-server-demo).
For usage details have a look [these API docs](docs/nodejs/api.md).
## References in publications
+5 -8
View File
@@ -7,22 +7,19 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SET PROJECT_DIR=%CD%
ECHO PROJECT_DIR^: %PROJECT_DIR%
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
:: Check CMake version
SET CMAKE_VERSION=3.9.2
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
ECHO cmake^: && cmake --version
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK
cmake --version | findstr /C:%CMAKE_VERSION% && GOTO CMAKE_OK
cmake --version | findstr /C:"3.7.1" && GOTO CMAKE_OK
:CMAKE_NOT_OK
SET CMAKE_VERSION=3.7.1
ECHO CMAKE NOT OK - downloading new CMake %CMAKE_VERSION%
powershell Invoke-WebRequest https://cmake.org/files/v3.9/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
IF NOT EXIST cm.zip powershell Invoke-WebRequest https://cmake.org/files/v3.7/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
IF NOT EXIST cmake-%CMAKE_VERSION%-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
:CMAKE_OK
ECHO CMAKE_OK
@@ -40,7 +37,7 @@ ECHO msbuild version
msbuild /version
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
SET DEPSPKG=osrm-deps-win-x64-14.0-2017.09.7z
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
:: local development
ECHO.
-3
View File
@@ -36,8 +36,6 @@
# This is because, the lua location is not standardized and may exist in
# locations other than lua/
include(FindPkgConfig)
unset(_lua_include_subdirs)
unset(_lua_library_names)
unset(_lua_append_versions)
@@ -83,7 +81,6 @@ function(_lua_set_version_vars)
lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
pkg_check_modules(LUA QUIET "lua${ver}")
endforeach ()
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
+1 -1
View File
@@ -4,7 +4,7 @@ libdir=@PKGCONFIG_LIBRARY_DIR@
Name: libOSRM
Description: Project OSRM library
Version: @OSRM_VERSION@
Version: v@OSRM_VERSION@
Requires:
Libs: -L${libdir} -losrm @PKGCONFIG_OSRM_LDFLAGS@
Libs.private: @PKGCONFIG_OSRM_DEPENDENT_LIBRARIES@
+2 -2
View File
@@ -3,5 +3,5 @@ module.exports = {
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
all: '--strict --require features/support --require features/step_definitions',
mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
};
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --require features/support --require features/step_definitions -f progress'
}
+3 -3
View File
@@ -7,7 +7,7 @@ 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 && \
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.1-dev libtbb@testing libtbb-dev@testing && \
\
echo "Building libstxxl" && \
cd /opt && \
@@ -46,8 +46,8 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
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 && \
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.1-dev git make gcc && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.1 expat && \
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
EXPOSE 5000
+1 -1
View File
@@ -20,7 +20,7 @@ A guard (ScopedGeojsonLoggerGuard) requires a logging policy. Per default we pro
The initialisation to do so looks like this:
`util::ScopedGeojsonLoggerGuard<util::NodeIdVectorToLineString> geojson_guard( "debug.geojson", data-for-conversion);`
Make sure to give the guard a name, so it actually gets a lifetime.
Make sure to give the guar a name, so it actually gets a lifetime.
The field `data-for-conversion` can be an arbitrary long set of features and needs to match the parameters used for constructing our policy (in this case `util::NodeIdVectorToLineString`).
+1 -10
View File
@@ -31,7 +31,6 @@ To pass parameters to each location some options support an array like encoding:
|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. |
|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. |
|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curb side. |
|exclude |`{class}[,{class}]` |Additive list of classes to avoid, order does not matter. |
Where the elements follow the following format:
@@ -41,13 +40,12 @@ Where the elements follow the following format:
|radius |`double >= 0` or `unlimited` (default) |
|hint |Base64 `string` |
|approach |`curb` or `unrestricted` (default) |
|class |A class name determined by the profile or `none`. |
```
{option}={element};{element}[;{element} ... ]
```
The number of elements must match exactly the number of locations (except for `generate_hints` and `exclude`). If you don't want to pass a value but instead use the default you can pass an empty `element`.
The number of elements must match exactly the number of locations. If you don't want to pass a value but instead use the default you can pass an empty `element`.
Example: 2nd location use the default value for `option`:
@@ -61,9 +59,6 @@ Example: 2nd location use the default value for `option`:
# Query on Berlin with three coordinates:
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false'
# Query on Berlin excluding the usage of motorways:
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407?exclude=motorway'
# Using polyline:
curl 'http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false'
```
@@ -437,8 +432,6 @@ Vector tiles contain two layers:
| `turn_angle` | `integer` | the angle of the turn, relative to the `bearing_in`. -180 to +180, 0 = straight ahead, 90 = 90-degrees to the right |
| `cost` | `float` | the time we think it takes to make that turn, in seconds. May be negative, depending on how the data model is constructed (some turns get a "bonus"). |
| `weight` | `float` | the weight we think it takes to make that turn. May be negative, depending on how the data model is constructed (some turns get a "bonus"). ACTUAL ROUTING USES THIS VALUE |
| `type` | `string` | the type of this turn - values like `turn`, `continue`, etc. See the `StepManeuver` for a partial list, this field also exposes internal turn types that are never returned with an API response |
| `modifier` | `string` | the direction modifier of the turn (`left`, `sharp left`, etc) |
## Result objects
@@ -668,8 +661,6 @@ step.
| `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 |
| `exit roundabout`| Describes a maneuver exiting a roundabout (usually preceeded by a `roundabout` instruction) |
| `exit rotary` | Describes the maneuver exiting a rotary (large named roundabout) |
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
between all instructions. They only offer a fallback in case nothing else is to report.
+9 -25
View File
@@ -47,7 +47,7 @@ Profiles can also define a `process_segment` function to handle differences in s
At the end of the file, a table if returned with references to the setup and processing functions the profile has defined.
## Understanding speed, weight and rate
## 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.
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.
@@ -91,7 +91,7 @@ The `setup` function is called once when the profile is loaded and must return a
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.
The following global properties can be set under `properties` in the hash you return in the `setup` function:
The following global properties can be set under `properties` in the hash you return in the `setup` function:
Attribute | Type | Notes
-------------------------------------|----------|----------------------------------------------------------------------------
@@ -104,19 +104,7 @@ max_speed_for_map_matching | Float | Maximum vehicle speed to be as
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `process_segment` will be called for all segments (default `false`)
The following additional global properties can be set in the hash you return in the `setup` function:
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.
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".
relation_types | Sequence | Determines wich relations should be cached for processing in this profile. It contains relations types
### process_node(profile, node, result, relations)
### process_node(profile, node, result)
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
Argument | Description
@@ -124,7 +112,6 @@ Argument | Description
profile | The configuration table you returned in `setup`.
node | The input node to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `node` is a member.
The following attributes can be set on `result`:
@@ -133,7 +120,7 @@ Attribute | Type | Notes
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
### process_way(profile, way, result, relations)
## process_way(profile, way, result)
Given an OpenStreetMap way, the `process_way` function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash.
Argument | Description
@@ -141,7 +128,6 @@ Argument | Description
profile | The configuration table you returned in `setup`.
node | The input way to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `way` is a member.
Importantly it will set `result.forward_mode` and `result.backward_mode` to indicate the travel mode in each direction, as well as set `result.forward_speed` and `result.backward_speed` to integer values representing the speed for traversing the way.
@@ -171,9 +157,7 @@ is_startpoint | Boolean | Can a journey start on this
roundabout | Boolean | Is this part of a roundabout?
circular | Boolean | Is this part of a non-roundabout circular junction?
name | String | Name of the way
ref | String | Road number (equal to set `forward_ref` and `backward_ref` with one value)
forward_ref | String | Road number in forward way direction
backward_ref | String | Road number in backward way direction
ref | String | Road number
destinations | String | The road's destinations
exits | String | The ramp's exit numbers or names
pronunciation | String | Name pronunciation
@@ -184,9 +168,9 @@ road_classification.may_be_ignored | Boolean | Guidance: way is non-highwa
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
### process_segment(profile, segment)
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
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.
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.
@@ -271,7 +255,7 @@ Example:
function process_segment (profile, segment)
local sourceData = raster:query(profile.raster_source, segment.source.lon, segment.source.lat)
local targetData = raster:query(profile.raster_source, segment.target.lon, segment.target.lat)
local invalid = sourceData.invalid_data()
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
-- use values to adjust weight and duration
@@ -288,4 +272,4 @@ durationIsValid
parseDuration
trimLaneString
applyAccessTokens
canonicalizeStringList
canonicalizeStringList
-35
View File
@@ -1,35 +0,0 @@
@routing @bicycle
Feature: Bike - Use distance weight
Background:
Given a grid size of 200 meters
Scenario: Bike - Check distance weight
Given the profile file
"""
local functions = require('bicycle')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.properties.weight_name = 'distance'
return profile
end
return functions
"""
Given the node map
"""
a-b-c
"""
And the ways
| nodes | highway |
| abc | residential |
When I route I should get
| from | to | route | weight | time | distance |
| a | b | abc,abc | 200 | 48s | 200m +-1 |
| a | c | abc,abc | 400 | 96s | 400m +-1 |
+9 -10
View File
@@ -157,16 +157,15 @@ Feature: Car - Restricted access
Scenario: Car - Access combinations
Then routability should be
| highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
| runway | private | | | permissive | x | x | |
| primary | forestry | | yes | | x | x | |
| cycleway | | | designated | | x | x | |
| unclassified | | | destination | destination | x | x | |
| residential | | yes | no | | | | |
| motorway | yes | permissive | | private | x | | implied oneway |
| trunk | agricultural | designated | permissive | no | | | |
| pedestrian | | | | | | | |
| pedestrian | | | | destination | | | temporary disabled #3773 |
| highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
| runway | private | | | permissive | x | x | |
| primary | forestry | | yes | | x | x | |
| cycleway | | | designated | | x | x | |
| residential | | yes | no | | | | |
| motorway | yes | permissive | | private | x | | implied oneway |
| trunk | agricultural | designated | permissive | no | | | |
| pedestrian | | | | | | | |
| pedestrian | | | | destination | | | temporary disabled #3773 |
Scenario: Car - Ignore access tags for other modes
Then routability should be
+179 -179
View File
@@ -17,27 +17,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | only_right_turn @ (has_pygmies > 10 p) |
| restriction | ej | nj | j | only_right_turn @ (has_pygmies > 10 p) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Restriction would be on, but the restriction was badly tagged
@@ -48,29 +48,29 @@ Feature: Car - Turn restrictions
Given the node map
"""
a
n
p |
\ |
j
| \
c m
s m
"""
And the ways
| nodes |
| aj |
| jc |
| nj |
| js |
| pjm |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | aj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
| restriction | jc | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) |
| restriction | nj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
| restriction | js | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) |
When I route I should get
| from | to | route |
| a | m | aj,pjm,pjm |
| c | m | jc,pjm,pjm |
| n | m | nj,pjm,pjm |
| s | m | js,pjm,pjm |
@no_turning @conditionals
Scenario: Car - Restriction With Compressed Geometry
@@ -149,29 +149,29 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | no |
| jd | no |
| nj | no |
| js | no |
| ej | no |
| jp | no |
And the relations
| type | way:from | way:to | node:via | restriction:conditional | except |
| restriction | bj | aj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar |
| restriction | jd | aj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar |
| restriction | jp | nj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus |
When I route I should get
| from | to | route | # |
| b | c | bj,jc,jc | |
| b | a | bj,aj,aj | restriction does not apply to cars |
| b | d | bj,jd,jd | |
| d | c | jd,aj,aj,jc,jc | restriction excepting busses still applies to cars |
| e | s | ej,js,js | |
| e | n | ej,nj,nj | restriction does not apply to cars |
| e | p | ej,jp,jp | |
| p | s | jp,nj,nj,js,js | restriction excepting busses still applies to cars |
@no_turning @conditionals
Scenario: Car - only_right_turn
@@ -181,27 +181,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,aj,aj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,nj,nj,jp,jp |
@no_turning @conditionals
Scenario: Car - No right turn
@@ -211,27 +211,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
When I route I should get
| from | to | route | # |
| b | c | bj,jc,jc | normal turn |
| b | a | bj,jc,jc,aj,aj | avoids right turn |
| b | d | bj,jd,jd | normal maneuver |
| e | s | ej,js,js | normal turn |
| e | n | ej,js,js,nj,nj | avoids right turn |
| e | p | ej,jp,jp | normal maneuver |
@only_turning @conditionals
Scenario: Car - only_left_turn
@@ -241,27 +241,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jc,jc,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,js,js,jp,jp |
@no_turning @conditionals
Scenario: Car - No left turn
@@ -271,27 +271,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | no_left_turn @ (Mo-Su 00:00-23:59) |
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is off
@@ -301,27 +301,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is on
@@ -331,27 +331,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction with multiple time windows
@@ -362,28 +362,28 @@ Feature: Car - Turn restrictions
Given the node map
"""
a
n
p |
\ |
j
| \
c m
s m
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| nj | no |
| js | no |
| jp | yes |
| mj | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | aj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
| restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| a | p | aj,jc,jc,jp,jp |
| n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp |
@no_turning @conditionals
@@ -394,27 +394,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,aj,aj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,nj,nj,jp,jp |
@no_turning @conditionals
Scenario: Car - No right turn
@@ -424,27 +424,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
When I route I should get
| from | to | route | # |
| b | c | bj,jc,jc | normal turn |
| b | a | bj,jc,jc,aj,aj | avoids right turn |
| b | d | bj,jd,jd | normal maneuver |
| e | s | ej,js,js | normal turn |
| e | n | ej,js,js,nj,nj | avoids right turn |
| e | p | ej,jp,jp | normal maneuver |
@only_turning @conditionals
Scenario: Car - only_left_turn
@@ -454,27 +454,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jc,jc,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,js,js,jp,jp |
@no_turning @conditionals
Scenario: Car - No left turn
@@ -484,27 +484,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | no_left_turn @ (Mo-Su 00:00-23:59) |
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is off
@@ -514,27 +514,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is on
@@ -544,27 +544,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | jb | aj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction with multiple time windows
@@ -575,28 +575,28 @@ Feature: Car - Turn restrictions
Given the node map
"""
a
n
p |
\ |
j
| \
c m
s m
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| nj | no |
| js | no |
| jp | yes |
| mj | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | aj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
| restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| a | p | aj,jc,jc,jp,jp |
| n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp |
@restriction-way
@@ -677,7 +677,7 @@ Feature: Car - Turn restrictions
# https://www.openstreetmap.org/#map=18/38.91099/-77.00888
@no_turning @conditionals
Scenario: Car - DC North capitol situation, two on one off
Given the extract extra arguments "--parse-conditional-restrictions"
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 9pm Wed 02 May, 2017 UTC, 5pm EDT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
@@ -724,7 +724,7 @@ Feature: Car - Turn restrictions
@no_turning @conditionals
Scenario: Car - DC North capitol situation, one on two off
Given the extract extra arguments "--parse-conditional-restrictions"
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 10:30am utc, wed, 6:30am est
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
@@ -848,7 +848,7 @@ Feature: Car - Turn restrictions
@only_turning @conditionals
Scenario: Car - Somewhere in London, the UK, GMT timezone
Given the extract extra arguments "--parse-conditional-restrictions"
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 9am UTC, 10am BST
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
+128 -134
View File
@@ -11,27 +11,27 @@ Feature: Car - Turn restrictions
Scenario: Car - No left turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | no_left_turn |
| restriction | sj | wj | j | no_left_turn |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Car - No straight on
@@ -67,259 +67,253 @@ Feature: Car - Turn restrictions
Scenario: Car - No right turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | bj | j | no_right_turn |
| restriction | sj | ej | j | no_right_turn |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | cj,aj,aj |
| c | b | |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | |
@no_turning
Scenario: Car - No u-turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | no_u_turn |
| restriction | sj | wj | j | no_u_turn |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Car - Handle any no_* relation
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | no_weird_zigzags |
| restriction | sj | wj | j | no_weird_zigzags |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning
Scenario: Car - Only left turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | only_left_turn |
When I route I should get
| from | to | route |
| c | a | |
| c | b | |
| c | d | cj,dj,dj |
| restriction | sj | wj | j | only_left_turn |
Scenario: Car - Only right turn, invalid
Given the node map
"""
a
d j b r
c
n
w j e r
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| rb | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
| re | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | br | j | only_right_on |
| restriction | sj | er | j | only_right_on |
When I route I should get
| from | to | route |
| c | r | cj,bj,rb,rb |
| s | r | sj,ej,re,re |
@only_turning
Scenario: Car - Only right turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | bj | j | only_right_turn |
| restriction | sj | ej | j | only_right_turn |
When I route I should get
| from | to | route |
| c | d | |
| c | a | |
| c | b | cj,bj,bj |
| s | w | |
| s | n | |
| s | e | sj,ej,ej |
@only_turning
Scenario: Car - Only straight on
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | aj | j | only_straight_on |
| restriction | sj | nj | j | only_straight_on |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | |
| s | w | |
| s | n | sj,nj,nj |
| s | e | |
@no_turning
Scenario: Car - Handle any only_* restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | aj | j | only_weird_zigzags |
| restriction | sj | nj | j | only_weird_zigzags |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | |
| s | w | |
| s | n | sj,nj,nj |
| s | e | |
@specific
Scenario: Car - :hgv-qualified on a standard turn restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction:hgv |
| restriction | cj | aj | j | no_straight_on |
| restriction | sj | nj | j | no_straight_on |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@specific
Scenario: Car - :motorcar-qualified on a standard turn restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction:motorcar |
| restriction | cj | aj | j | no_straight_on |
| restriction | sj | nj | j | no_straight_on |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | |
| c | b | cj,bj,bj |
| s | w | sj,wj,wj |
| s | n | |
| s | e | sj,ej,ej |
@except
Scenario: Car - Except tag and on no_ restrictions
@@ -490,27 +484,27 @@ Feature: Car - Turn restrictions
Scenario: Car - Ignore unrecognized restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | yield |
| restriction | sj | wj | j | yield |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@restriction @compression
Scenario: Restriction On Compressed Geometry
-329
View File
@@ -1,329 +0,0 @@
@routing @car @relations
Feature: Car - route relations
Background:
Given the profile "car"
Scenario: Assignment using relation membership roles
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | way:east | way:west | route | ref | network |
| route | cd | ba | road | 80 | US:I |
| route | cd | ba | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80 $west,I 80 $west |
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
Scenario: No cardinal directions by default
Given the profile file "car" initialized with
"""
profile.cardinal_directions = false
"""
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | way:east | way:west | route | ref | network |
| route | cd | ba | road | 80 | US:I |
| route | cd | ba | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80,I 80 |
| c,d | eastbound,eastbound | I 80; CO 93,I 80; CO 93 |
Scenario: No cardinal directions by default
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | way:east | way:west | route | ref | network |
| route | cd | ba | road | 80 | US:I |
| route | cd | ba | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80,I 80 |
| c,d | eastbound,eastbound | I 80; CO 93,I 80; CO 93 |
Scenario: Assignment using relation direction property (no role on members)
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | direction | way | route | ref | network |
| route | west | ba | road | 80 | US:I |
| route | east | cd | road | 80 | US:I |
| route | east | cd | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80 $west,I 80 $west |
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
Scenario: Forward assignment on one-way roads using relation direction property
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | direction | way:forward | route | ref | network |
| route | west | ba | road | 80 | US:I |
| route | east | cd | road | 80 | US:I |
| route | east | cd | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80 $west,I 80 $west |
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
Scenario: Forward/backward assignment on non-divided roads with role direction tag
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref | oneway |
| ab | mainroad | motorway | I 80 | no |
And the relations
| type | direction | way:forward | route | ref | network |
| route | west | ab | road | 80 | US:I |
And the relations
| type | direction | way:backward | route | ref | network |
| route | east | ab | road | 80 | US:I |
When I route I should get
| waypoints | route | ref |
| a,b | mainroad,mainroad | I 80 $west,I 80 $west |
| b,a | mainroad,mainroad | I 80 $east,I 80 $east |
Scenario: Conflict between role and direction
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | direction | way:east | route | ref | network |
| route | west | ab | road | 80 | US:I |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80,I 80 |
Scenario: Conflict between role and superrelation direction
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:east | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | direction | relation | route | ref | network | name |
| route | west | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80,I 80 |
Scenario: Conflict between role and superrelation role
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:east | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | relation:west | route | ref | network | name |
| route | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80,I 80 |
Scenario: Direction only available via superrelation role
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:forward | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | relation:east | route | ref | network | name |
| route | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80 $east,I 80 $east |
Scenario: Direction only available via superrelation direction
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:forward | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | direction | relation | route | ref | network | name |
| route | east | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80 $east,I 80 $east |
# Scenario: Three levels of indirection
# Given the node map
# """
# a----------------b
# """
#
# And the ways
# | nodes | name | highway | ref |
# | ab | eastbound | motorway | I 80 |
#
# And the relations
# | type | way:forward | route | ref | network | name |
# | route | ab | road | 80 | US:I | baserelation |
#
# And the relations
# | type | relation | route | ref | network | name |
# | route | baserelation | road | 80 | US:I | superrelation1 |
#
# And the relations
# | type | direction | relation | route | ref | network | name |
# | route | east | superrelation1 | road | 80 | US:I | superrelation2 |
#
# When I route I should get
# | waypoints | route | ref |
# | a,b | eastbound,eastbound | I 80 $east,I 80 $east |
+4 -73
View File
@@ -5,9 +5,9 @@ Feature: Testbot - side bias
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.turn_bias = 1.075
profile.turn_bias = 1/1.075
"""
And the node map
Given the node map
"""
a b c
@@ -28,7 +28,7 @@ Feature: Testbot - side bias
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.turn_bias = 1 / 1.075
profile.turn_bias = 1.075
"""
And the node map
"""
@@ -42,77 +42,8 @@ Feature: Testbot - side bias
| bc |
| 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 | |
Scenario: Roundabout exit counting for left sided driving
Given the profile file "testbot" initialized with
"""
profile.left_hand_driving = true
"""
And a grid size of 10 meters
And the node map
"""
a
b
h g c d
e
f
"""
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| 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 |
Scenario: Left-hand bias via location-dependent tags
Given the profile "car"
And the node map
"""
a b c
d
"""
And the ways with locations
| nodes |
| ab |
| bc |
| bd |
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 |
Scenario: Left-hand bias via OSM tags
Given the profile "car"
And the node map
"""
a b c
d
"""
And the ways with locations
| nodes | driving_side |
| ab | right |
| bc | right |
| bd | right |
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 |
# should be inverse of left hand bias
| d | c | bd,bc,bc | 24s +-1 |
-35
View File
@@ -1,35 +0,0 @@
@routing @foot
Feature: Foot - Use distance weight
Background:
Given a grid size of 200 meters
Scenario: Foot - Check distance weight
Given the profile file
"""
local functions = require('foot')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.properties.weight_name = 'distance'
return profile
end
return functions
"""
Given the node map
"""
a-b-c
"""
And the ways
| nodes | highway |
| abc | residential |
When I route I should get
| from | to | route | weight | time | distance |
| a | b | abc,abc | 200 | 144s | 200m +-1 |
| a | c | abc,abc | 400 | 288s | 400m +-1 |
-29
View File
@@ -147,32 +147,3 @@ Feature: Collapse
| waypoints | route | turns |
| a,d | road,left,left | depart,turn left,arrive |
| a,e | road,right,right | depart,turn right,arrive |
# https://www.openstreetmap.org/#map=18/53.89755/27.54306
Scenario: Wide turn into invalid u-turn
Given the node map
"""
g
|
|
f - - - - e
|
|
|
h - - d
|
|
|
a - - - - b - - - - c
"""
And the ways
| nodes | highway | name |
| abc | secondary | road |
| bdfg | service | |
| hd | service | |
| fe | service | |
When I route I should get
| waypoints | route | turns |
| c,e | road,,, | depart,turn right,turn right,arrive |
-34
View File
@@ -22,40 +22,6 @@ Feature: Continue Instructions
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,d | abc,bd,bd | depart,turn straight,arrive |
Scenario: Road turning left, Suffix changes
Given the node map
"""
c
a - b-d
"""
And the ways
| nodes | highway | name |
| ab | primary | North Capitol Northeast |
| bc | primary | North Capitol Northwest |
| bd | primary | some random street |
When I route I should get
| waypoints | route | turns |
| a,c | North Capitol Northeast,North Capitol Northwest,North Capitol Northwest | depart,continue left,arrive |
Scenario: Road turning left, Suffix changes, no-spaces
Given the node map
"""
c
a - b-d
"""
And the ways
| nodes | highway | name |
| ab | primary | North CapitolNortheast |
| bc | primary | North CapitolNorthwest |
| bd | primary | some random street |
When I route I should get
| waypoints | route | turns |
| a,c | North CapitolNortheast,North CapitolNorthwest,North CapitolNorthwest | depart,continue left,arrive |
Scenario: Road turning left and straight
Given the node map
"""
+1 -56
View File
@@ -995,59 +995,4 @@ Feature: Slipways and Dedicated Turn Lanes
When I route I should get
| waypoints | route | turns | locations |
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
@sliproads
Scenario: Sliproad from link via link to primary
Given the node map
"""
d
.
s . a . b
` .
` .
'.
c
.
f
"""
And the ways
| nodes | highway | name | oneway |
| sab | primary_link | sab | |
| 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 |
@sliproads
Scenario: Sliproad with a single intersection in a cross-road
Given the node map
"""
d
.
s . a . b
` .
' c . g
..
e
.
f
"""
And the ways
| nodes | highway | name | oneway |
| sab | primary | sab | |
| dbcef | primary | dbcef | |
| 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 |
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
-19
View File
@@ -24,25 +24,6 @@ Feature: End Of Road Instructions
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |
# http://map.project-osrm.org/?z=18&center=38.906632%2C-77.008265&loc=38.906463%2C-77.007621&loc=38.906822%2C-77.008860&hl=en&alt=0
Scenario: End of Road, unnamed oneway
Given the node map
"""
c
a e b
f d
"""
And the ways
| nodes | highway | name | oneway |
| aeb | primary | road | yes |
| cbd | primary | | yes |
| ef | primary | turn | yes |
When I route I should get
| waypoints | route | turns |
| a,d | road,, | depart,end of road right,arrive |
@3605
Scenario: End of Road with oneway through street
Given the node map
@@ -523,42 +523,3 @@ Feature: Merge Segregated Roads
| 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 |
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 /
\ /
m . d
/
j
"""
And the ways
| nodes | name | oneway |
| ac | Halenseestraße | yes |
| gb | Halenseestraße | yes |
| cklmdenopgc | Rathenauplatz | yes |
| ig | Kurfürstendamm | yes |
| ef | Kurfürstendamm | yes |
| ch | Hubertusallee | yes |
| jd | Hubertusallee | yes |
When I route I should get
| waypoints | route | turns |
| i,h | Kurfürstendamm,Hubertusallee,Hubertusallee | depart,turn straight,arrive |
+4 -4
View File
@@ -274,8 +274,8 @@ Feature: New-Name Instructions
| bc | Central Expressway | US 75 | motorway |
When I route I should get
| waypoints | route | turns |
| a,c | North Central Expressway,Central Expressway | depart,arrive |
| waypoints | route | turns |
| a,c | North Central Expressway,Central Expressway,Central Expressway | depart,new name straight,arrive |
Scenario: Prefix Change
Given the node map
@@ -289,8 +289,8 @@ Feature: New-Name Instructions
| cb | Central Expressway | US 75 | motorway |
When I route I should get
| waypoints | route | turns |
| c,a | Central Expressway,North Central Expressway | depart,arrive |
| waypoints | route | turns |
| c,a | Central Expressway,North Central Expressway,North Central Expressway | depart,new name straight,arrive |
Scenario: No Name, Same Reference
Given the node map
+22 -22
View File
@@ -158,23 +158,23 @@ Feature: Rotary
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,exit rotary right,arrive |
| a,l | abc,jkl,jkl,jkl | depart,bkheb-exit-2,exit rotary straight,arrive |
| a,i | abc,ghi,ghi,ghi | depart,bkheb-exit-3,exit rotary straight,arrive |
| a,f | abc,def,def,def | depart,bkheb-exit-4,exit rotary straight,arrive |
| d,f | def,def,def | depart,exit rotary right,arrive |
| d,c | def,abc,abc,abc | depart,bkheb-exit-2,exit rotary straight,arrive |
| d,l | def,jkl,jkl,jkl | depart,bkheb-exit-3,exit rotary straight,arrive |
| d,i | def,ghi,ghi,ghi | depart,bkheb-exit-4,exit rotary straight,arrive |
| g,i | ghi,ghi,ghi | depart,exit rotary right,arrive |
| g,f | ghi,def,def,def | depart,bkheb-exit-2,exit rotary straight,arrive |
| g,c | ghi,abc,abc,abc | depart,bkheb-exit-3,exit rotary straight,arrive |
| g,l | ghi,jkl,jkl,jkl | depart,bkheb-exit-4,exit rotary straight,arrive |
| j,l | jkl,jkl,jkl | depart,exit rotary right,arrive |
| j,i | jkl,ghi,ghi,ghi | depart,bkheb-exit-2,exit rotary straight,arrive |
| j,f | jkl,def,def,def | depart,bkheb-exit-3,exit rotary straight,arrive |
| j,c | jkl,abc,abc,abc | depart,bkheb-exit-4,exit rotary straight,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,exit rotary right,arrive |
| a,l | abc,jkl,jkl,jkl | depart,bkheb-exit-2,exit rotary straight,arrive |
| a,i | abc,ghi,ghi,ghi | depart,bkheb-exit-3,exit rotary straight,arrive |
| a,f | abc,def,def,def | depart,bkheb-exit-4,exit rotary straight,arrive |
| d,f | def,def,def | depart,exit rotary right,arrive |
| d,c | def,abc,abc,abc | depart,bkheb-exit-2,exit rotary straight,arrive |
| d,l | def,jkl,jkl,jkl | depart,bkheb-exit-3,exit rotary straight,arrive |
| d,i | def,ghi,ghi,ghi | depart,bkheb-exit-4,exit rotary straight,arrive |
| g,i | ghi,ghi,ghi | depart,exit rotary right,arrive |
| g,f | ghi,def,def,def | depart,bkheb-exit-2,exit rotary straight,arrive |
| g,c | ghi,abc,abc,abc | depart,bkheb-exit-3,exit rotary straight,arrive |
| g,l | ghi,jkl,jkl,jkl | depart,bkheb-exit-4,exit rotary straight,arrive |
| j,l | jkl,jkl,jkl | depart,exit rotary right,arrive |
| j,i | jkl,ghi,ghi,ghi | depart,bkheb-exit-2,exit rotary straight,arrive |
| j,f | jkl,def,def,def | depart,bkheb-exit-3,exit rotary straight,arrive |
| j,c | jkl,abc,abc,abc | depart,bkheb-exit-4,exit rotary straight,arrive |
Scenario: Collinear in X,Y
Given the node map
@@ -193,7 +193,7 @@ Feature: Rotary
| df | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ab,ce,ce,ce | depart,bcdb-exit-1,exit rotary straight,arrive |
| a,f | ab,df,df,df | depart,bcdb-exit-2,exit rotary straight,arrive |
@@ -214,7 +214,7 @@ Feature: Rotary
| cf | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ad,be,be,be | depart,bcdb-exit-1,exit rotary straight,arrive |
| a,f | ad,cf,cf,cf | depart,bcdb-exit-2,exit rotary straight,arrive |
@@ -235,7 +235,7 @@ Feature: Rotary
| bf | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ac,de,de,de | depart,bcdb-exit-1,exit rotary straight,arrive |
| a,f | ac,bf,bf,bf | depart,bcdb-exit-2,exit rotary straight,arrive |
@@ -256,7 +256,7 @@ Feature: Rotary
| df | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ab,ce,ce,ce | depart,bcdb-exit-1,exit rotary right,arrive |
| a,f | ab,df,df,df | depart,bcdb-exit-2,exit rotary right,arrive |
@@ -277,6 +277,6 @@ Feature: Rotary
| df | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ab,ce,ce,ce | depart,bcdb-exit-1,exit rotary right,arrive |
| a,f | ab,df,df,df | depart,bcdb-exit-2,exit rotary right,arrive |
@@ -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
+12 -12
View File
@@ -26,15 +26,15 @@ Feature: Basic 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,ef | depart,roundabout turn straight exit-1,exit roundabout right,arrive |
| a,h | ab,gh,gh,gh | depart,roundabout turn right exit-1,exit roundabout right,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout turn left exit-2,exit roundabout right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout turn straight exit-2,exit roundabout right,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout turn left exit-3,exit roundabout right,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-2,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-1,arrive |
| h,f | gh,ef,ef,ef | depart,roundabout turn right exit-1,exit roundabout right,arrive |
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef,ef | depart,roundabout turn straight exit-1,exit roundabout right,arrive |
| a,h | ab,gh,gh,gh | depart,roundabout turn right exit-1,exit roundabout right,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout turn left exit-2,exit roundabout right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout turn straight exit-2,exit roundabout right,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout turn left exit-3,exit roundabout right,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-2,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-1,arrive |
| h,f | gh,ef,ef,ef | depart,roundabout turn right exit-1,exit roundabout right,arrive |
+137 -137
View File
@@ -25,18 +25,18 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
Scenario: Enter and Exit - Rotated
Given the node map
@@ -56,21 +56,21 @@ Feature: Basic Roundabout
| bgecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
Scenario: Only Enter
Scenario: Only Enter
Given the node map
"""
a
@@ -122,19 +122,19 @@ Feature: Basic Roundabout
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| b,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
| b,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
| b,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
| c,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
| c,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
| c,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
| e,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
| e,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
| e,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
| g,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
| g,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
| g,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
| waypoints | route | turns |
| b,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
| b,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
| b,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
| c,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
| c,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
| c,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
| e,h | bcegb,gh,gh | depart,exit roundabout right,arrive |
| e,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
| e,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
| g,a | bcegb,ab,ab | depart,exit roundabout right,arrive |
| g,d | bcegb,cd,cd | depart,exit roundabout right,arrive |
| g,f | bcegb,ef,ef | depart,exit roundabout right,arrive |
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
Scenario: Drive Around
@@ -189,23 +189,23 @@ Feature: Basic Roundabout
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,exit roundabout right,arrive |
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout straight,arrive |
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout straight,arrive |
| a,f | abc,def,def,def | depart,roundabout-exit-4,exit roundabout straight,arrive |
| d,f | def,def,def | depart,exit roundabout right,arrive |
| d,c | def,abc,abc,abc | depart,roundabout-exit-2,exit roundabout straight,arrive |
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout straight,arrive |
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout straight,arrive |
| g,i | ghi,ghi,ghi | depart,exit roundabout right,arrive |
| g,f | ghi,def,def,def | depart,roundabout-exit-2,exit roundabout straight,arrive |
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-3,exit roundabout straight,arrive |
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout straight,arrive |
| j,l | jkl,jkl,jkl | depart,exit roundabout right,arrive |
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout straight,arrive |
| j,f | jkl,def,def,def | depart,roundabout-exit-3,exit roundabout straight,arrive |
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-4,exit roundabout straight,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,exit roundabout right,arrive |
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout straight,arrive |
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout straight,arrive |
| a,f | abc,def,def,def | depart,roundabout-exit-4,exit roundabout straight,arrive |
| d,f | def,def,def | depart,exit roundabout right,arrive |
| d,c | def,abc,abc,abc | depart,roundabout-exit-2,exit roundabout straight,arrive |
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout straight,arrive |
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout straight,arrive |
| g,i | ghi,ghi,ghi | depart,exit roundabout right,arrive |
| g,f | ghi,def,def,def | depart,roundabout-exit-2,exit roundabout straight,arrive |
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-3,exit roundabout straight,arrive |
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout straight,arrive |
| j,l | jkl,jkl,jkl | depart,exit roundabout right,arrive |
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout straight,arrive |
| j,f | jkl,def,def,def | depart,roundabout-exit-3,exit roundabout straight,arrive |
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-4,exit roundabout straight,arrive |
Scenario: Segregated roads - Not an intersection
Given the node map
@@ -226,23 +226,23 @@ Feature: Basic Roundabout
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc,abc | depart,roundabout-exit-4,exit roundabout right,arrive |
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-1,exit roundabout right,arrive |
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout right,arrive |
| a,f | abc,def,def,def | depart,roundabout-exit-3,exit roundabout right,arrive |
| d,f | def,def,def,def | depart,roundabout-exit-4,exit roundabout right,arrive |
| d,c | def,abc,abc,abc | depart,roundabout-exit-1,exit roundabout right,arrive |
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout right,arrive |
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout right,arrive |
| g,i | ghi,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout right,arrive |
| g,f | ghi,def,def,def | depart,roundabout-exit-1,exit roundabout right,arrive |
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-2,exit roundabout right,arrive |
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout right,arrive |
| j,l | jkl,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout right,arrive |
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-1,exit roundabout right,arrive |
| j,f | jkl,def,def,def | depart,roundabout-exit-2,exit roundabout right,arrive |
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-3,exit roundabout right,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc,abc | depart,roundabout-exit-4,exit roundabout right,arrive |
| a,l | abc,jkl,jkl,jkl | depart,roundabout-exit-1,exit roundabout right,arrive |
| a,i | abc,ghi,ghi,ghi | depart,roundabout-exit-2,exit roundabout right,arrive |
| a,f | abc,def,def,def | depart,roundabout-exit-3,exit roundabout right,arrive |
| d,f | def,def,def,def | depart,roundabout-exit-4,exit roundabout right,arrive |
| d,c | def,abc,abc,abc | depart,roundabout-exit-1,exit roundabout right,arrive |
| d,l | def,jkl,jkl,jkl | depart,roundabout-exit-2,exit roundabout right,arrive |
| d,i | def,ghi,ghi,ghi | depart,roundabout-exit-3,exit roundabout right,arrive |
| g,i | ghi,ghi,ghi,ghi | depart,roundabout-exit-4,exit roundabout right,arrive |
| g,f | ghi,def,def,def | depart,roundabout-exit-1,exit roundabout right,arrive |
| g,c | ghi,abc,abc,abc | depart,roundabout-exit-2,exit roundabout right,arrive |
| g,l | ghi,jkl,jkl,jkl | depart,roundabout-exit-3,exit roundabout right,arrive |
| j,l | jkl,jkl,jkl,jkl | depart,roundabout-exit-4,exit roundabout right,arrive |
| j,i | jkl,ghi,ghi,ghi | depart,roundabout-exit-1,exit roundabout right,arrive |
| j,f | jkl,def,def,def | depart,roundabout-exit-2,exit roundabout right,arrive |
| j,c | jkl,abc,abc,abc | depart,roundabout-exit-3,exit roundabout right,arrive |
Scenario: Collinear in X
Given the node map
@@ -259,9 +259,9 @@ Feature: Basic Roundabout
| df | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout turn right exit-1,arrive |
| a,f | ab,df,df | depart,roundabout turn straight exit-2,arrive |
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout turn right exit-1,arrive |
| a,f | ab,df,df | depart,roundabout turn straight exit-2,arrive |
Scenario: Collinear in Y
Given the node map
@@ -281,7 +281,7 @@ Feature: Basic Roundabout
| df | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout turn right exit-1,arrive |
| a,f | ab,df,df | depart,roundabout turn straight exit-2,arrive |
@@ -302,7 +302,7 @@ Feature: Basic Roundabout
| df | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout turn straight exit-1,arrive |
| a,f | ab,df,df | depart,roundabout turn left exit-2,arrive |
@@ -323,7 +323,7 @@ Feature: Basic Roundabout
| cf | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ad,be,be | depart,roundabout turn straight exit-1,arrive |
| a,f | ad,cf,cf | depart,roundabout turn left exit-2,arrive |
@@ -344,7 +344,7 @@ Feature: Basic Roundabout
| bf | |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,e | ac,de,de | depart,roundabout turn straight exit-1,arrive |
| a,f | ac,bf,bf | depart,roundabout turn left exit-2,arrive |
@@ -368,19 +368,19 @@ Feature: Basic Roundabout
| bigecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd,cd | depart,roundabout-exit-4,exit roundabout right,arrive |
| a,f | ab,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
| a,h | ab,gh,gh,gh | depart,roundabout-exit-2,exit roundabout right,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout-exit-4,exit roundabout right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout-exit-3,exit roundabout right,arrive |
| d,a | cd,ab,ab,ab | depart,roundabout-exit-1,exit roundabout right,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout-exit-4,exit roundabout right,arrive |
| f,a | ef,ab,ab,ab | depart,roundabout-exit-2,exit roundabout right,arrive |
| f,d | ef,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
| h,a | gh,ab,ab,ab | depart,roundabout-exit-3,exit roundabout right,arrive |
| h,d | gh,cd,cd,cd | depart,roundabout-exit-2,exit roundabout right,arrive |
| h,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
| waypoints | route | turns |
| a,d | ab,cd,cd,cd | depart,roundabout-exit-4,exit roundabout right,arrive |
| a,f | ab,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
| a,h | ab,gh,gh,gh | depart,roundabout-exit-2,exit roundabout right,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout-exit-4,exit roundabout right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout-exit-3,exit roundabout right,arrive |
| d,a | cd,ab,ab,ab | depart,roundabout-exit-1,exit roundabout right,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout-exit-4,exit roundabout right,arrive |
| f,a | ef,ab,ab,ab | depart,roundabout-exit-2,exit roundabout right,arrive |
| f,d | ef,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
| h,a | gh,ab,ab,ab | depart,roundabout-exit-3,exit roundabout right,arrive |
| h,d | gh,cd,cd,cd | depart,roundabout-exit-2,exit roundabout right,arrive |
| h,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
Scenario: Enter and Exit -- Non-Distinct
Given the node map
@@ -401,19 +401,19 @@ Feature: Basic Roundabout
| bgecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd,cd | depart,roundabout-exit-3,exit roundabout right,arrive |
| a,f | ab,ef,ef,ef | depart,roundabout-exit-2,exit roundabout right,arrive |
| a,h | ab,gh,gh,gh | depart,roundabout-exit-1,exit roundabout straight,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout-exit-2,exit roundabout straight,arrive |
| d,a | cd,ab,ab,ab | depart,roundabout-exit-1,exit roundabout right,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout-exit-3,exit roundabout straight,arrive |
| f,a | ef,ab,ab,ab | depart,roundabout-exit-2,exit roundabout right,arrive |
| f,d | ef,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
| h,a | gh,ab,ab,ab | depart,roundabout-exit-3,exit roundabout right,arrive |
| h,d | gh,cd,cd,cd | depart,roundabout-exit-2,exit roundabout right,arrive |
| h,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
| waypoints | route | turns |
| a,d | ab,cd,cd,cd | depart,roundabout-exit-3,exit roundabout right,arrive |
| a,f | ab,ef,ef,ef | depart,roundabout-exit-2,exit roundabout right,arrive |
| a,h | ab,gh,gh,gh | depart,roundabout-exit-1,exit roundabout straight,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout-exit-3,exit roundabout right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout-exit-2,exit roundabout straight,arrive |
| d,a | cd,ab,ab,ab | depart,roundabout-exit-1,exit roundabout right,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout-exit-3,exit roundabout straight,arrive |
| f,a | ef,ab,ab,ab | depart,roundabout-exit-2,exit roundabout right,arrive |
| f,d | ef,cd,cd,cd | depart,roundabout-exit-1,exit roundabout right,arrive |
| h,a | gh,ab,ab,ab | depart,roundabout-exit-3,exit roundabout right,arrive |
| h,d | gh,cd,cd,cd | depart,roundabout-exit-2,exit roundabout right,arrive |
| h,f | gh,ef,ef,ef | depart,roundabout-exit-1,exit roundabout right,arrive |
Scenario: Enter and Exit -- Bearing
Given the node map
@@ -435,9 +435,9 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns | bearing |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive | 0->180,180->225,90->0 |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive | 0->180,180->225,180->0 |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive | 0->180,180->225,270->0 |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive | 0->180,180->225,90->0 |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive | 0->180,180->225,180->0 |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive | 0->180,180->225,270->0 |
Scenario: Enter and Exit - Bearings
Given the node map
@@ -461,9 +461,9 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns | bearing |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive | 0->180,180->270,90->0 |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive | 0->180,180->270,180->0 |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive | 0->180,180->270,270->0 |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive | 0->180,180->270,90->0 |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive | 0->180,180->270,180->0 |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive | 0->180,180->270,270->0 |
Scenario: Large radius Roundabout Intersection and ways modelled out: East Mission St, North 7th St
# http://www.openstreetmap.org/way/348812150
@@ -495,18 +495,18 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns |
| a,e | North 7th St,East Mission St,East Mission St | depart,roundabout turn right exit-1,arrive |
| a,h | North 7th St,North 7th St,North 7th St | depart,roundabout turn straight exit-2,arrive |
| a,l | North 7th St,East Mission St,East Mission St | depart,roundabout turn left exit-3,arrive |
| h,l | North 7th St,East Mission St,East Mission St | depart,roundabout turn right exit-1,arrive |
| h,a | North 7th St,North 7th St,North 7th St | depart,roundabout turn straight exit-2,arrive |
| h,e | North 7th St,East Mission St,East Mission St | depart,roundabout turn left exit-3,arrive |
| e,h | East Mission St,North 7th St,North 7th St | depart,roundabout turn right exit-1,arrive |
| e,l | East Mission St,East Mission St,East Mission St | depart,roundabout turn straight exit-2,arrive |
| e,a | East Mission St,North 7th St,North 7th St | depart,roundabout turn left exit-3,arrive |
| l,a | East Mission St,North 7th St,North 7th St | depart,roundabout turn right exit-1,arrive |
| l,e | East Mission St,East Mission St,East Mission St | depart,roundabout turn straight exit-2,arrive |
| l,h | East Mission St,North 7th St,North 7th St | depart,roundabout turn left exit-3,arrive |
| a,e | North 7th St,East Mission St,East Mission St | depart,roundabout turn right exit-1,arrive |
| a,h | North 7th St,North 7th St,North 7th St | depart,roundabout turn straight exit-2,arrive |
| a,l | North 7th St,East Mission St,East Mission St | depart,roundabout turn left exit-3,arrive |
| h,l | North 7th St,East Mission St,East Mission St | depart,roundabout turn right exit-1,arrive |
| h,a | North 7th St,North 7th St,North 7th St | depart,roundabout turn straight exit-2,arrive |
| h,e | North 7th St,East Mission St,East Mission St | depart,roundabout turn left exit-3,arrive |
| e,h | East Mission St,North 7th St,North 7th St | depart,roundabout turn right exit-1,arrive |
| e,l | East Mission St,East Mission St,East Mission St | depart,roundabout turn straight exit-2,arrive |
| e,a | East Mission St,North 7th St,North 7th St | depart,roundabout turn left exit-3,arrive |
| l,a | East Mission St,North 7th St,North 7th St | depart,roundabout turn right exit-1,arrive |
| l,e | East Mission St,East Mission St,East Mission St | depart,roundabout turn straight exit-2,arrive |
| l,h | East Mission St,North 7th St,North 7th St | depart,roundabout turn left exit-3,arrive |
Scenario: Enter and Exit - Traffic Signals
Given the node map
@@ -534,19 +534,19 @@ Feature: Basic Roundabout
| bigjekclb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
#http://www.openstreetmap.org/#map=19/41.03275/-2.18990
#at some point we probably want to recognise these situations and don't mention the roundabout at all here
+10 -10
View File
@@ -829,16 +829,16 @@ Feature: Basic Roundabout
"""
And the ways
| nodes | highway | junction | oneway | # |
| abcda | tertiary | roundabout | | circle |
| ebds | tertiary | | | road |
| cm | tertiary | | | |
| ds | tertiary | | | road |
| rstur | tertiary | roundabout | | circle2 |
| ufghl | tertiary | | | road |
| tv | tertiary | | | |
| gi | tertiary_link | | yes | sliproad |
| jhik | tertiary | | | crossroad |
| nodes | highway | junction | oneway | # |
| abcda | tertiary | roundabout | | circle |
| ebds | tertiary | | | road |
| cm | tertiary | | | |
| ds | tertiary | | | road |
| rstur | tertiary | roundabout | | circle2 |
| ufghl | tertiary | | | road |
| tv | tertiary | | | |
| gi | tertiary | | yes | sliproad |
| jhik | tertiary | | | crossroad |
When I route I should get
-29
View File
@@ -280,35 +280,6 @@ Feature: Simple Turns
| a,d | road,road | depart,arrive |
| e,a | road,road | depart,arrive |
Scenario: Splitting Road with many lanes; same as above makes sure len(turn:lanes) work as expected
Given the node map
"""
f - - - - - - - - - - - - - - - - - - - - e
'
'
'
'
'
a - - - - - b
'
'
'
'
'
c - - - - - - - - - - - - - - - - - - - - d
"""
And the ways
| nodes | highway | name | turn:lanes | oneway |
| ab | primary | road | left\|left\|right\|right | no |
| bcd | primary | road | through\|through | yes |
| efb | primary | road | through\|through | yes |
When I route I should get
| waypoints | route | turns |
| a,d | road,road | depart,arrive |
| e,a | road,road | depart,arrive |
@todo
# currently the intersections don't match up do to the `merging` process.
# The intermediate intersection is technically no-turn at all, since the road continues.
-21
View File
@@ -1349,24 +1349,3 @@ Feature: Simple Turns
When I route I should get
| waypoints | route | turns |
| a,d | ab,dc,dc | depart,turn left,arrive |
# https://www.openstreetmap.org/node/1332083066
Scenario: Turns ordering must respect initial bearings
Given the node map
"""
a . be .
\ c.
d/ .f . g
"""
And the ways
| nodes | highway | oneway |
| ab | primary | yes |
| bcd | primary | yes |
| befg | primary | yes |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
| a,g | ab,befg,befg | depart,fork slight left,arrive |
+2 -2
View File
@@ -20,11 +20,11 @@ module.exports = {
});
},
hashOfFile: (path, additional_content, cb) => {
hashOfFile: (path, cb) => {
fs.readFile(path, (err, result) => {
if (err) return cb(err);
let checksum = crypto.createHash('md5');
checksum.update(result + (additional_content || "") );
checksum.update(result);
cb(null, checksum.digest('hex'));
});
}
+6 -13
View File
@@ -61,13 +61,8 @@ class DB {
});
w.nodes.forEach((k) => {
let nd = way.ele('nd')
way.ele('nd')
.att('ref', k.id);
if (w.add_locations) {
nd.att('lon', k.lon);
nd.att('lat', k.lat);
}
});
for (var k in w.tags) {
@@ -86,12 +81,11 @@ class DB {
});
r.members.forEach((m) => {
var d = {
relation.ele('member', {
type: m.type,
ref: m.id
};
if (m.role) d.role = m.role;
relation.ele('member', d);
ref: m.id,
role: m.role
});
});
for (var k in r.tags) {
@@ -126,14 +120,13 @@ class Node {
}
class Way {
constructor (id, OSM_USER, OSM_TIMESTAMP, OSM_UID, add_locations) {
constructor (id, OSM_USER, OSM_TIMESTAMP, OSM_UID) {
this.id = id;
this.OSM_USER = OSM_USER;
this.OSM_TIMESTAMP = OSM_TIMESTAMP;
this.OSM_UID = OSM_UID;
this.tags = {};
this.nodes = [];
this.add_locations = add_locations;
}
addNode (node) {
+1 -1
View File
@@ -18,5 +18,5 @@ Feature: osrm-contract command line options: files
Scenario: osrm-contract - Missing input file
When I try to run "osrm-contract over-the-rainbow.osrm"
And stderr should contain "over-the-rainbow.osrm"
And stderr should contain "Missing/Broken"
And stderr should contain "not found"
And it should exit with an error
+3 -3
View File
@@ -8,10 +8,10 @@ Feature: osrm-contract command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--core"
And stdout should contain "--level-cache"
And stdout should contain "--segment-speed-file"
And it should exit with an error
@@ -22,10 +22,10 @@ Feature: osrm-contract command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--core"
And stdout should contain "--level-cache"
And stdout should contain "--segment-speed-file"
And it should exit successfully
@@ -36,9 +36,9 @@ Feature: osrm-contract command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--core"
And stdout should contain "--level-cache"
And stdout should contain "--segment-speed-file"
And it should exit successfully
+1 -1
View File
@@ -8,7 +8,7 @@ Feature: osrm-contract command line options: version
Given the profile "testbot"
Scenario: osrm-contract - Version, short
When I run "osrm-contract -v"
When I run "osrm-contract --v"
Then stderr should be empty
And stdout should contain 1 line
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+1 -1
View File
@@ -19,5 +19,5 @@ Feature: osrm-contract command line options: files
Scenario: osrm-customize - Missing input file
When I try to run "osrm-customize over-the-rainbow.osrm"
And stderr should contain "over-the-rainbow.osrm"
And stderr should contain "Missing/Broken"
And stderr should contain "not found"
And it should exit with an error
-3
View File
@@ -8,7 +8,6 @@ Feature: osrm-customize command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And it should exit with an error
@@ -20,7 +19,6 @@ Feature: osrm-customize command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And it should exit successfully
@@ -32,7 +30,6 @@ Feature: osrm-customize command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And it should exit successfully
+1 -1
View File
@@ -5,7 +5,7 @@ Feature: osrm-customize command line options: version
Given the profile "testbot"
Scenario: osrm-customize - Version, short
When I run "osrm-customize -v"
When I run "osrm-customize --v"
Then stderr should be empty
And stdout should contain 1 line
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
-3
View File
@@ -11,7 +11,6 @@ Feature: osrm-extract command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--profile"
And stdout should contain "--threads"
@@ -25,7 +24,6 @@ Feature: osrm-extract command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--profile"
And stdout should contain "--threads"
@@ -39,7 +37,6 @@ Feature: osrm-extract command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--profile"
And stdout should contain "--threads"
+12 -130
View File
@@ -1,12 +1,22 @@
@extract
Feature: osrm-extract lua ways:get_nodes()
Background:
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
Scenario: osrm-extract - Passing base file
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result)
function way_function(profile, way, result)
for _, node in ipairs(way:get_nodes()) do
print('node id ' .. node:id())
end
@@ -14,138 +24,10 @@ Feature: osrm-extract lua ways:get_nodes()
result.forward_speed = 1
end
functions.process_way = way_function
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file}"
Then it should exit successfully
And stdout should contain "node id 1"
And stdout should contain "node id 2"
Scenario: osrm-extract location-dependent data without add-locations-to-ways preprocessing and node locations cache
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print(way:get_location_tag('driving_side'))
end
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I try to run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --disable-location-cache"
Then it should exit with an error
And stderr should contain "invalid location"
Scenario: osrm-extract location-dependent data
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
for _, key in ipairs({'answer', 'boolean', 'object', 'array'}) do
print (key .. ' ' .. tostring(way:get_location_tag(key)))
end
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node map
"""
a b
"""
And the ways with locations
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --disable-location-cache"
Then it should exit successfully
And stdout should contain "answer 42"
And stdout should contain "boolean true"
And stdout should contain "array nil"
And stdout should contain "object nil"
Scenario: osrm-extract location-dependent data with multi-polygons
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print('ISO3166-1 ' .. (way:get_location_tag('ISO3166-1') or 'none'))
print('answer ' .. (way:get_location_tag('answer') or 'none'))
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node locations
| node | lat | lon | id |
| a | 22.4903670 | 113.9455227 | 1 |
| b | 22.4901701 | 113.9455899 | 2 |
| c | 22.4901852 | 113.9458608 | 3 |
| d | 22.4904033 | 113.9456999 | 4 |
| e | 1.1 | 1 | 5 |
| f | 1.2 | 1 | 6 |
And the ways with locations
| nodes | # |
| ab | Hong Kong |
| cd | China Mainland |
| ef | Null Island |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --location-dependent-data test/data/regions/hong-kong.geojson --disable-location-cache"
Then it should exit successfully
And stdout should not contain "1 GeoJSON polygon"
And stdout should contain "2 GeoJSON polygons"
And stdout should contain "ISO3166-1 HK"
And stdout should contain "ISO3166-1 none"
And stdout should contain "answer 42"
Scenario: osrm-extract location-dependent data via locations cache
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print ('answer ' .. tostring(way:get_location_tag('answer')))
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson"
Then it should exit successfully
And stdout should contain "answer 42"
@@ -1,32 +0,0 @@
@extract
Feature: osrm-extract must be silent with NONE
Background:
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
Scenario: osrm-extract - Passing base file with verbosity NONE
Given the profile file
"""
functions = require('testbot')
function way_function(profile, way, result)
result.forward_mode = mode.driving
result.forward_speed = 1
end
functions.process_way = way_function
return functions
"""
When I run "osrm-extract --profile {profile_file} {osm_file} --verbosity NONE"
Then it should exit successfully
And stdout should not contain "[info]"
And stdout should not contain "[error]"
And stdout should not contain "10%"
And stderr should be empty
+1 -1
View File
@@ -8,7 +8,7 @@ Feature: osrm-extract command line options: version
Given the profile "testbot"
Scenario: osrm-extract - Version, short
When I run "osrm-extract -v"
When I run "osrm-extract --v"
Then stderr should be empty
And stdout should contain 1 line
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
-3
View File
@@ -8,7 +8,6 @@ Feature: osrm-partition command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--balance"
@@ -25,7 +24,6 @@ Feature: osrm-partition command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--balance"
@@ -42,7 +40,6 @@ Feature: osrm-partition command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--balance"
+1 -1
View File
@@ -5,7 +5,7 @@ Feature: osrm-partition command line options: version
Given the profile "testbot"
Scenario: osrm-partition - Version, short
When I run "osrm-partition -v"
When I run "osrm-partition --v"
Then stderr should be empty
And stdout should contain 1 line
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
@@ -24,7 +24,7 @@ Feature: Invalid profile API versions
Scenario: Profile API version too high
Given the profile file
"""
api_version = 4
api_version = 3
"""
And the node map
"""
-101
View File
@@ -1,101 +0,0 @@
Feature: Profile API version 3
Background:
Given a grid size of 100 meters
Scenario: Basic profile function calls and property values
Given the profile file
"""
api_version = 3
Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
function setup()
return {
properties = {
max_speed_for_map_matching = 180/3.6,
use_turn_restrictions = true,
continue_straight_at_waypoint = true,
weight_name = 'test_version2',
weight_precision = 2
},
relation_types = Sequence { "route" }
}
end
function process_node(profile, node, result, relations)
print ('process_node ' .. node:id())
end
function process_way(profile, way, result, relations)
result.name = way:get_value_by_key('name')
result.weight = 10
result.forward_mode = mode.driving
result.backward_mode = mode.driving
result.forward_speed = 36
result.backward_speed = 36
local rel_id_list = relations:get_relations(way)
for i, rel_id in ipairs(rel_id_list) do
local rel = relations:relation(rel_id)
local role = rel:get_role(way)
print('role_' .. role)
end
print ('process_way ' .. way:id() .. ' ' .. result.name)
end
function process_turn (profile, turn)
print('process_turn', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
turn.weight = turn.angle == 0 and 0 or 4.2
turn.duration = turn.weight
end
function process_segment (profile, segment)
print ('process_segment ' .. segment.source.lon .. ' ' .. segment.source.lat)
end
return {
setup = setup,
process_node = process_node,
process_way = process_way,
process_relation = process_relation,
process_segment = process_segment,
process_turn = process_turn
}
"""
And the node map
"""
a
bcd
e
"""
And the ways
| nodes |
| ac |
| cb |
| cd |
| ce |
And the relations
| type | way:north | route |
| route | ac | road |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file}"
Then it should exit successfully
And stdout should contain "process_node"
And stdout should contain "process_way"
And stdout should contain "process_turn"
And stdout should contain "process_segment"
And stdout should contain "role_north"
When I route I should get
| from | to | route | time |
| a | b | ac,cb,cb | 19.2s |
| a | d | ac,cd,cd | 19.2s |
| a | e | ac,ce | 20s |
-3
View File
@@ -11,7 +11,6 @@ Feature: osrm-routed command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "--trial"
And stdout should contain "Configuration:"
And stdout should contain "--ip"
@@ -31,7 +30,6 @@ Feature: osrm-routed command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "--trial"
And stdout should contain "Configuration:"
And stdout should contain "--ip"
@@ -51,7 +49,6 @@ Feature: osrm-routed command line options: help
And stdout should contain "Options:"
And stdout should contain "--version"
And stdout should contain "--help"
And stdout should contain "--verbosity"
And stdout should contain "--trial"
And stdout should contain "Configuration:"
And stdout should contain "--ip"
+1 -1
View File
@@ -8,7 +8,7 @@ Feature: osrm-routed command line options: version
Given the profile "testbot"
Scenario: osrm-routed - Version, short
When I run "osrm-routed -v"
When I run "osrm-routed --v"
Then stderr should be empty
And stdout should contain 1 line
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
+5 -20
View File
@@ -8,7 +8,7 @@ var OSM = require('../lib/osm');
module.exports = function () {
this.Given(/^the profile "([^"]*)"$/, (profile, callback) => {
this.profile = this.OSRM_PROFILE || profile;
this.profile = profile;
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
callback();
});
@@ -129,13 +129,13 @@ module.exports = function () {
q.awaitAll(callback);
});
this.Given(/^the ways( with locations)?$/, (add_locations, table, callback) => {
this.Given(/^the ways$/, (table, callback) => {
if (this.osm_str) throw new Error('*** Map data already defined - did you pass an input file in this scenario?');
let q = d3.queue();
let addWay = (row, cb) => {
let way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID, !!add_locations);
let way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID);
let nodes = row.nodes;
if (this.nameWayHash.nodes) throw new Error(util.format('*** duplicate way %s', nodes));
@@ -188,12 +188,9 @@ module.exports = function () {
let addRelation = (row, cb) => {
let relation = new OSM.Relation(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID);
var name = null;
for (let key in row) {
let isNode = key.match(/^node:?(.*)/),
isWay = key.match(/^way:?(.*)/),
isRelation = key.match(/^relation:?(.*)/),
let isNode = key.match(/^node:(.*)/),
isWay = key.match(/^way:(.*)/),
isColonSeparated = key.match(/^(.*):(.*)/);
if (isNode) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => {
@@ -208,26 +205,14 @@ module.exports = function () {
if (!way) throw new Error(util.format('*** unknown relation way member "%s"', wayName));
relation.addMember('way', way.id, isWay[1]);
});
} else if (isRelation) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((relName) => {
let otherrelation = this.findRelationByName(relName);
if (!otherrelation) throw new Error(util.format('*** unknown relation relation member "%s"', relName));
relation.addMember('relation', otherrelation.id, isRelation[1]);
});
} else if (isColonSeparated && isColonSeparated[1] !== 'restriction') {
throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"', isColonSeparated[1], isColonSeparated[2]));
} else {
relation.addTag(key, row[key]);
if (key.match(/name/)) name = row[key];
}
}
relation.uid = this.OSM_UID;
if (name) {
this.nameRelationHash[name] = relation;
}
this.OSMDB.addRelation(relation);
cb();
+1 -1
View File
@@ -11,7 +11,7 @@ module.exports = function () {
var waypoints = [],
columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
symmetric = columnHeaders.every((ele, i) => ele === rowHeaders[i]);
if (symmetric) {
columnHeaders.forEach((nodeName) => {
+2 -4
View File
@@ -54,14 +54,12 @@ module.exports = function () {
this.Then(/^stdout should( not)? contain "(.*?)"$/, (not, str) => {
const contains = this.stdout.indexOf(str) > -1;
assert.ok(typeof not === 'undefined' ? contains : !contains,
'stdout ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
assert.ok(typeof not === 'undefined' ? contains : !contains);
});
this.Then(/^stderr should( not)? contain "(.*?)"$/, (not, str) => {
const contains = this.stderr.indexOf(str) > -1;
assert.ok(typeof not === 'undefined' ? contains : !contains,
'stderr ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
assert.ok(typeof not === 'undefined' ? contains : !contains);
});
this.Then(/^stdout should contain \/(.*)\/$/, (regexStr) => {
+2 -5
View File
@@ -28,16 +28,13 @@ module.exports = function() {
let uri = feature.getUri();
// setup cache for feature data
// if OSRM_PROFILE is set to force a specific profile, then
// include the profile name in the hash of the profile file
hash.hashOfFile(uri, this.OSRM_PROFILE, (err, hash) => {
hash.hashOfFile(uri, (err, hash) => {
if (err) return callback(err);
// shorten uri to be realtive to 'features/'
let featurePath = path.relative(path.resolve('./features'), uri);
// bicycle/bollards/{HASH}/
let featureID = path.join(featurePath, hash);
let featureID = path.join(featurePath, hash);
let featureCacheDirectory = this.getFeatureCacheDirectory(featureID);
let featureProcessedCacheDirectory = this.getFeatureProcessedCacheDirectory(featureCacheDirectory, this.osrmHash);
this.featureIDs[uri] = featureID;
-5
View File
@@ -144,10 +144,6 @@ module.exports = function () {
return this.nameWayHash[s.toString()] || this.nameWayHash[s.toString().split('').reverse().join('')];
};
this.findRelationByName = (s) => {
return this.nameRelationHash[s.toString()] || this.nameRelationHash[s.toString().split('').reverse().join('')];
};
this.makeOSMId = () => {
this.osmID = this.osmID + 1;
return this.osmID;
@@ -159,7 +155,6 @@ module.exports = function () {
this.locationHash = {};
this.shortcutsHash = {};
this.nameWayHash = {};
this.nameRelationHash = {};
this.osmID = 0;
};
-2
View File
@@ -44,8 +44,6 @@ module.exports = function () {
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
this.OSRM_PROFILE = process.env.OSRM_PROFILE;
if (this.PLATFORM_WINDOWS) {
this.TERMSIGNAL = 9;
+1 -1
View File
@@ -22,7 +22,7 @@ module.exports = function () {
});
this.BeforeFeature((feature, callback) => {
this.profile = this.OSRM_PROFILE || this.DEFAULT_PROFILE;
this.profile = this.DEFAULT_PROFILE;
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
this.setupFeatureCache(feature);
callback();
-3
View File
@@ -12,9 +12,6 @@ Feature: Alternative route
g h i j
"""
# enforce multiple cells for filterUnpackedPathsBySharing check
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
And the ways
| nodes |
| ab |
+1 -4
View File
@@ -31,10 +31,7 @@ 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
@4111
Scenario: Alternative Loop Paths with single node path
Given the node map
"""
+12 -48
View File
@@ -2,11 +2,11 @@
Feature: Approach parameter
Background:
Given a grid size of 10 meters
Given the profile "testbot"
And a grid size of 10 meters
Scenario: Start End same approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -22,8 +22,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End same approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -39,8 +38,7 @@ Feature: Approach parameter
| s | e | unrestricted curb | ab,bc,bc |
Scenario: Start End opposite approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -57,8 +55,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End opposite approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -80,8 +77,7 @@ Feature: Approach parameter
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -97,8 +93,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -114,8 +109,7 @@ Feature: Approach parameter
| s | e | unrestricted curb | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -132,8 +126,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -154,8 +147,7 @@ Feature: Approach parameter
##############
Scenario: UTurn test, router can't found a route because uturn unauthorized on the segment selected
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -176,8 +168,7 @@ Feature: Approach parameter
Scenario: UTurn test, router can find a route because he can use the roundabout
Given the profile "testbot"
And the node map
Given the node map
"""
h
s e / \
@@ -199,30 +190,3 @@ Feature: Approach parameter
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
Scenario: Start End same approach, option unrestricted for Start and curb for End, left-hand driving
Given the profile file
"""
local functions = require('testbot')
local testbot_process_way = functions.process_way
functions.process_way = function(profile, way, result)
testbot_process_way(profile, way, result)
result.is_left_hand_driving = true
end
return functions
"""
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
+11 -11
View File
@@ -67,8 +67,8 @@ Feature: Bearing parameter
| from | to | bearings | route | bearing |
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
| 0 | b | 170 170 | da,da | 0->180,180->0 |
| 0 | b | 189 189 | da,da | 0->180,180->0 |
| 0 | b | 170 170 | da,da | 0->0,0->0 |
| 0 | b | 189 189 | da,da | 0->0,0->0 |
| 0 | 1 | 90 270 | ab,cd,cd | 0->90,90->0,270->0 |
| 1 | 2 | 10 10 | bc,bc | 0->0,0->0 |
| 1 | 2 | 90 90 | ab,cd,ab,ab | 0->90,90->0,270->180,90->0 |
@@ -108,12 +108,12 @@ Feature: Bearing parameter
| ha | yes | ring |
When I route I should get
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,90->0 |
| 0 | a | 45 90 | jb,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,90->0 |
| 0 | q | 90 90 | kc,ring,ring,ring | 0->90,90->180,270->0,90->0 |
| 0 | a | 135 90 | ld,ring,ring,ring | 0->135,135->270,270->0,90->0 |
| 0 | a | 180 90 | me,ring,ring,ring | 0->180,180->270,270->0,90->0 |
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring | 0->0,0->90,90->0 |
| 0 | a | 45 90 | jb,ring,ring | 0->45,45->180,90->0 |
| 0 | q | 90 90 | kc,ring,ring | 0->90,90->180,90->0 |
| 0 | a | 135 90 | ld,ring,ring | 0->135,135->270,90->0 |
| 0 | a | 180 90 | me,ring,ring | 0->180,180->270,90->0 |
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
+1 -102
View File
@@ -6,7 +6,6 @@ Feature: Basic Distance Matrix
Background:
Given the profile "testbot"
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
Scenario: Testbot - Travel time matrix of minimal network
Given the node map
@@ -42,17 +41,6 @@ Feature: Basic Distance Matrix
| c | 30 | 20 | 0 | 30 |
| d | 60 | 50 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| c | 30 |
| d | 60 |
Scenario: Testbot - Travel time matrix with fuzzy match
Given the node map
"""
@@ -125,7 +113,7 @@ Feature: Basic Distance Matrix
| d | 20 | 30 | 0 | 30 |
| e | 30 | 40 | 10 | 0 |
Scenario: Testbot - Rectangular travel time matrix
Scenario: Testbot - Travel time matrix and with only one source
Given the node map
"""
a b c
@@ -144,46 +132,6 @@ Feature: Basic Distance Matrix
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
| e | 20 | 10 |
| f | 30 | 20 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 10 | 20 |
| b | 10 | 0 | 10 |
| e | 20 | 10 | 0 |
| f | 30 | 20 | 10 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel time 3x2 matrix
Given the node map
"""
@@ -360,52 +308,3 @@ Feature: Basic Distance Matrix
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
Scenario: Testbot - Travel time matrix with ties
Given the profile file
"""
local functions = require('testbot')
functions.process_segment = function(profile, segment)
segment.weight = 1
segment.duration = 1
end
functions.process_turn = function(profile, turn)
if turn.angle >= 0 then
turn.duration = 16
else
turn.duration = 4
end
turn.weight = 0
end
return functions
"""
And the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| ac |
| bd |
| dc |
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 1 | 5 | 10 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 1 |
| c | 15 |
| d | 10 |
-99
View File
@@ -1,99 +0,0 @@
@routing @testbot @exclude
Feature: Testbot - Exclude flags
Background:
Given the profile "testbot"
Given the node map
"""
a....b-----c-$-$-d
$ $ :
e.$.$.f.....g
"""
And the ways
| nodes | highway | toll | # |
| ab | primary | | always drivable |
| bc | motorway | | not drivable for exclude=motorway and exclude=motorway,toll |
| be | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
| ef | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
| fc | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
| cd | motorway | yes | not drivable for exclude=motorway exclude=toll and exclude=motorway,toll |
| fg | primary | | always drivable |
| gd | primary | | always drivable |
Scenario: Testbot - exclude nothing
When I route I should get
| from | to | route |
| a | d | ab,bc,cd,cd |
| a | g | ab,be,ef,fg,fg |
| a | c | ab,bc,bc |
| a | f | ab,be,ef,ef |
When I match I should get
| trace | matchings | duration |
| ad | ad | 115 |
When I request a travel time matrix I should get
| | a | d |
| a | 0 | 115 |
| d | 115 | 0 |
Scenario: Testbot - exclude motorway
Given the query options
| exclude | motorway |
When I route I should get
| from | to | route |
| a | d | ab,be,ef,fg,gd,gd |
| a | g | ab,be,ef,fg,fg |
| a | c | ab,be,ef,fc,fc |
| a | f | ab,be,ef,ef |
When I match I should get
| trace | matchings | duration |
| ad | ad | 125 |
When I request a travel time matrix I should get
| | a | d |
| a | 0 | 125 |
| d | 125 | 0 |
Scenario: Testbot - exclude toll
Given the query options
| exclude | toll |
When I route I should get
| from | to | route |
| a | d | |
| a | g | |
| a | c | ab,bc,bc |
| a | f | |
| f | d | fg,gd,gd |
Scenario: Testbot - exclude motorway and toll
Given the query options
| exclude | motorway,toll |
When I route I should get
| from | to | route |
| a | d | |
| a | g | |
| a | c | |
| a | f | |
| f | d | fg,gd,gd |
Scenario: Testbot - exclude with unsupported exclude combination
Given the query options
| exclude | TwoWords2 |
When I route I should get
| from | to | status | message |
| a | d | 400 | Exclude flag combination is not supported. |
Scenario: Testbot - exclude with invalid exclude class name
Given the query options
| exclude | foo |
When I route I should get
| from | to | status | message |
| a | d | 400 | Exclude flag combination is not supported. |
@@ -63,7 +63,6 @@ Feature: Multi level routing
| cm | primary |
| hj | primary |
| kp | primary |
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16"
When I route I should get
| from | to | route | time |
@@ -83,28 +82,6 @@ Feature: Multi level routing
| l | 144.7 | 124.7 | 0 | 60 |
| o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| f | 229.4 |
| l | 144.7 |
| o | 124.7 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get
| | a | o |
| a | 0 | 124.7 |
| f | 229.4 | 144.7 |
| l | 144.7 | 60 |
| o | 124.7 | 0 |
Scenario: Testbot - Multi level routing: horizontal road
Given the node map
+1
View File
@@ -167,3 +167,4 @@ Feature: Traffic - speeds
And the data has been extracted
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And it should exit successfully
-33
View File
@@ -379,36 +379,3 @@ Feature: Weight tests
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
@traffic @speed
Scenario: Updating speeds without affecting weights.
Given the profile file "testbot" initialized with
"""
profile.properties.weight_precision = 3
"""
And the node map
"""
a-----------b
\ /
c----d
"""
And the ways
| nodes | highway | maxspeed |
| ab | living_street | 5 |
| acdb | motorway | 100 |
# Note the comma on the last column - this indicates 'keep existing weight value'
And the speed file
"""
1,2,100,
1,3,5,,junk
3,4,5,,
4,2,5,
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
When I route I should get
| waypoints | route | distance | weights | times |
| a,b | acdb,acdb | 78.3m | 11.744,0 | 56.4s,0s |
@@ -1,95 +0,0 @@
#ifndef OSRM_CONTRACTOR_CONTRACT_EXCLUDABLE_GRAPH_HPP
#define OSRM_CONTRACTOR_CONTRACT_EXCLUDABLE_GRAPH_HPP
#include "contractor/contracted_edge_container.hpp"
#include "contractor/contractor_graph.hpp"
#include "contractor/graph_contractor.hpp"
#include "contractor/graph_contractor_adaptors.hpp"
#include "contractor/query_graph.hpp"
namespace osrm
{
namespace contractor
{
using GraphAndFilter = std::tuple<QueryGraph, std::vector<std::vector<bool>>>;
inline auto contractFullGraph(ContractorGraph contractor_graph,
std::vector<EdgeWeight> node_weights)
{
auto num_nodes = contractor_graph.GetNumberOfNodes();
contractGraph(contractor_graph, node_weights);
auto edges = toEdges<QueryEdge>(std::move(contractor_graph));
std::vector<bool> edge_filter(edges.size(), true);
return GraphAndFilter{QueryGraph{num_nodes, std::move(edges)}, {std::move(edge_filter)}};
}
inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
std::vector<EdgeWeight> node_weights,
const std::vector<std::vector<bool>> &filters)
{
if (filters.size() == 1)
{
if (std::all_of(filters.front().begin(), filters.front().end(), [](auto v) { return v; }))
{
return contractFullGraph(std::move(contractor_graph_), std::move(node_weights));
}
}
auto num_nodes = contractor_graph_.GetNumberOfNodes();
ContractedEdgeContainer edge_container;
ContractorGraph shared_core_graph;
std::vector<bool> is_shared_core;
{
ContractorGraph contractor_graph = std::move(contractor_graph_);
std::vector<bool> always_allowed(num_nodes, true);
for (const auto &filter : filters)
{
for (const auto node : util::irange<NodeID>(0, num_nodes))
{
always_allowed[node] = always_allowed[node] && filter[node];
}
}
// By not contracting all contractable nodes we avoid creating
// a very dense core. This increases the overall graph sizes a little bit
// but increases the final CH quality and contraction speed.
constexpr float BASE_CORE = 0.9;
is_shared_core =
contractGraph(contractor_graph, std::move(always_allowed), node_weights, BASE_CORE);
// Add all non-core edges to container
{
auto non_core_edges = toEdges<QueryEdge>(contractor_graph);
auto new_end =
std::remove_if(non_core_edges.begin(), non_core_edges.end(), [&](const auto &edge) {
return is_shared_core[edge.source] && is_shared_core[edge.target];
});
non_core_edges.resize(new_end - non_core_edges.begin());
edge_container.Insert(std::move(non_core_edges));
}
// Extract core graph for further contraction
shared_core_graph = contractor_graph.Filter(
[&is_shared_core](const NodeID node) { return is_shared_core[node]; });
}
for (const auto &filter : filters)
{
auto filtered_core_graph =
shared_core_graph.Filter([&filter](const NodeID node) { return filter[node]; });
contractGraph(filtered_core_graph, is_shared_core, is_shared_core, node_weights);
edge_container.Merge(toEdges<QueryEdge>(std::move(filtered_core_graph)));
}
return GraphAndFilter{QueryGraph{num_nodes, std::move(edge_container.edges)},
edge_container.MakeEdgeFilters()};
}
}
}
#endif
@@ -1,151 +0,0 @@
#ifndef OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
#define OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
#include "contractor/query_edge.hpp"
#include "util/integer_range.hpp"
#include "util/permutation.hpp"
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <climits>
#include <cstdint>
#include <numeric>
#include <vector>
namespace osrm
{
namespace contractor
{
struct ContractedEdgeContainer
{
private:
using MergedFlags = std::uint8_t;
static constexpr auto ALL_FLAGS = 0xFF;
static bool mergeCompare(const QueryEdge &lhs, const QueryEdge &rhs)
{
return std::tie(lhs.source,
lhs.target,
lhs.data.shortcut,
lhs.data.turn_id,
lhs.data.weight,
lhs.data.duration,
lhs.data.forward,
lhs.data.backward) < std::tie(rhs.source,
rhs.target,
rhs.data.shortcut,
rhs.data.turn_id,
rhs.data.weight,
rhs.data.duration,
rhs.data.forward,
rhs.data.backward);
}
static bool mergable(const QueryEdge &lhs, const QueryEdge &rhs)
{
// only true if both are equal
return !mergeCompare(lhs, rhs) && !mergeCompare(rhs, lhs);
}
public:
void Insert(std::vector<QueryEdge> new_edges)
{
BOOST_ASSERT(edges.size() == 0);
BOOST_ASSERT(flags.empty());
edges = std::move(new_edges);
flags.resize(edges.size(), ALL_FLAGS);
}
void Merge(std::vector<QueryEdge> new_edges)
{
BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT);
const MergedFlags flag = 1 << index++;
auto edge_iter = edges.cbegin();
auto edge_end = edges.cend();
auto flags_iter = flags.begin();
// Remove all edges that are contained in the old set of edges and set the appropriate flag.
auto new_end =
std::remove_if(new_edges.begin(), new_edges.end(), [&](const QueryEdge &edge) {
// check if the new edge would be sorted before the currend old edge
// if so it is not contained yet in the set of old edges
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
{
return false;
}
// find the first old edge that is equal or greater then the new edge
while (edge_iter != edge_end && mergeCompare(*edge_iter, edge))
{
BOOST_ASSERT(flags_iter != flags.end());
edge_iter++;
flags_iter++;
}
// all new edges will be sorted after the old edges
if (edge_iter == edge_end)
{
return false;
}
BOOST_ASSERT(edge_iter != edge_end);
if (mergable(edge, *edge_iter))
{
*flags_iter = *flags_iter | flag;
return true;
}
BOOST_ASSERT(mergeCompare(edge, *edge_iter));
return false;
});
// append new edges
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);
flags.resize(edges_size);
std::fill(flags.begin() + edges_size - new_edges_size, flags.end(), flag);
// enforce sorting for next merge step
std::vector<unsigned> ordering(edges_size);
std::iota(ordering.begin(), ordering.end(), 0);
tbb::parallel_sort(
ordering.begin(), ordering.end(), [&](const auto lhs_idx, const auto rhs_idx) {
return mergeCompare(edges[lhs_idx], edges[rhs_idx]);
});
auto permutation = util::orderingToPermutation(ordering);
util::inplacePermutation(edges.begin(), edges.end(), permutation);
util::inplacePermutation(flags.begin(), flags.end(), permutation);
BOOST_ASSERT(std::is_sorted(edges.begin(), edges.end(), mergeCompare));
}
auto MakeEdgeFilters() const
{
std::vector<std::vector<bool>> filters(index);
for (const auto flag_index : util::irange<std::size_t>(0, index))
{
MergedFlags mask = 1 << flag_index;
for (const auto flag : flags)
{
filters[flag_index].push_back(flag & mask);
}
}
return filters;
}
std::size_t index = 0;
std::vector<MergedFlags> flags;
std::vector<QueryEdge> edges;
};
}
}
#endif
+21 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -29,6 +29,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define CONTRACTOR_CONTRACTOR_HPP
#include "contractor/contractor_config.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "util/deallocating_vector.hpp"
#include "util/typedefs.hpp"
#include <string>
#include <vector>
#include <cstddef>
namespace osrm
{
@@ -39,6 +49,8 @@ namespace contractor
class Contractor
{
public:
using EdgeData = QueryEdge::EdgeData;
explicit Contractor(const ContractorConfig &config_) : config{config_} {}
Contractor(const Contractor &) = delete;
@@ -46,6 +58,14 @@ class Contractor
int Run();
protected:
void ContractGraph(const unsigned max_edge_id,
util::DeallocatingVector<extractor::EdgeBasedEdge> &edge_based_edge_list,
util::DeallocatingVector<QueryEdge> &contracted_edge_list,
std::vector<EdgeWeight> &&node_weights,
std::vector<bool> &is_core_node,
std::vector<float> &inout_node_levels) const;
private:
ContractorConfig config;
};
+7 -6
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -43,9 +43,12 @@ namespace contractor
struct ContractorConfig final : storage::IOConfig
{
ContractorConfig()
: IOConfig({".osrm.ebg", ".osrm.ebg_nodes", ".osrm.properties"},
{},
{".osrm.hsgr", ".osrm.enw"}),
: IOConfig(
{
".osrm",
},
{},
{".osrm.level", ".osrm.core", ".osrm.hsgr", ".osrm.enw"}),
requested_num_threads(0)
{
}
@@ -61,12 +64,10 @@ struct ContractorConfig final : storage::IOConfig
updater::UpdaterConfig updater_config;
// DEPRECATED to be removed in v6.0
bool use_cached_priority;
unsigned requested_num_threads;
// DEPRECATED to be removed in v6.0
// A percentage of vertices that will be contracted for the hierarchy.
// Offers a trade-off between preprocessing and query time.
// The remaining vertices form the core of the hierarchy
@@ -0,0 +1,50 @@
#ifndef OSRM_CONTRACTOR_DIJKSTRA_HPP
#define OSRM_CONTRACTOR_DIJKSTRA_HPP
#include "contractor/contractor_graph.hpp"
#include "contractor/contractor_heap.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
namespace osrm
{
namespace contractor
{
// allow access to the heap itself, add Dijkstra functionality on top
class ContractorDijkstra
{
public:
ContractorDijkstra(std::size_t heap_size);
// search the graph up
void Run(const unsigned number_of_targets,
const int node_limit,
const int weight_limit,
const NodeID forbidden_node,
const ContractorGraph &graph);
// adaption of the heap interface
void Clear();
bool WasInserted(const NodeID node) const;
void Insert(const NodeID node,
const ContractorHeap::WeightType weight,
const ContractorHeap::DataType &data);
// cannot be const due to node-hash access in the binary heap :(
ContractorHeap::WeightType GetKey(const NodeID node);
private:
void RelaxNode(const NodeID node,
const int node_weight,
const NodeID forbidden_node,
const ContractorGraph &graph);
ContractorHeap heap;
};
} // namespace contractor
} // namespace osrm
#endif // OSRM_CONTRACTOR_DIJKSTRA_HPP
+6 -4
View File
@@ -12,7 +12,8 @@ namespace contractor
struct ContractorEdgeData
{
ContractorEdgeData()
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0),
is_original_via_node_ID(false)
{
}
ContractorEdgeData(EdgeWeight weight,
@@ -23,17 +24,18 @@ struct ContractorEdgeData
bool forward,
bool backward)
: weight(weight), duration(duration), id(id),
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
forward(forward), backward(backward)
originalEdges(std::min((1u << 28) - 1u, original_edges)), shortcut(shortcut),
forward(forward), backward(backward), is_original_via_node_ID(false)
{
}
EdgeWeight weight;
EdgeWeight duration;
unsigned id;
unsigned originalEdges : 29;
unsigned originalEdges : 28;
bool shortcut : 1;
bool forward : 1;
bool backward : 1;
bool is_original_via_node_ID : 1;
};
using ContractorGraph = util::DynamicGraph<ContractorEdgeData>;
-26
View File
@@ -1,26 +0,0 @@
#ifndef OSRM_CONTRACTOR_SEARCH_HPP
#define OSRM_CONTRACTOR_SEARCH_HPP
#include "contractor/contractor_graph.hpp"
#include "contractor/contractor_heap.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
namespace osrm
{
namespace contractor
{
void search(ContractorHeap &heap,
const ContractorGraph &graph,
const unsigned number_of_targets,
const int node_limit,
const EdgeWeight weight_limit,
const NodeID forbidden_node);
} // namespace contractor
} // namespace osrm
#endif // OSRM_CONTRACTOR_DIJKSTRA_HPP
+45 -27
View File
@@ -14,56 +14,74 @@ namespace contractor
{
namespace files
{
// reads .osrm.core
template <typename CoreVectorT>
void readCoreMarker(const boost::filesystem::path &path, CoreVectorT &is_core_node)
{
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
"is_core_node must be a vector");
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
storage::serialization::read(reader, is_core_node);
}
// writes .osrm.core
template <typename CoreVectorT>
void writeCoreMarker(const boost::filesystem::path &path, const CoreVectorT &is_core_node)
{
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
"is_core_node must be a vector");
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
storage::serialization::write(writer, is_core_node);
}
// reads .osrm.hsgr file
template <typename QueryGraphT, typename EdgeFilterT>
inline void readGraph(const boost::filesystem::path &path,
unsigned &checksum,
QueryGraphT &graph,
std::vector<EdgeFilterT> &edge_filter)
template <typename QueryGraphT>
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
{
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
"edge_filter must be a container of vector<bool> or vector_view<bool>");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.ReadInto(checksum);
util::serialization::read(reader, graph);
auto count = reader.ReadElementCount64();
edge_filter.resize(count);
for (const auto index : util::irange<std::size_t>(0, count))
{
storage::serialization::read(reader, edge_filter[index]);
}
}
// writes .osrm.hsgr file
template <typename QueryGraphT, typename EdgeFilterT>
inline void writeGraph(const boost::filesystem::path &path,
unsigned checksum,
const QueryGraphT &graph,
const std::vector<EdgeFilterT> &edge_filter)
template <typename QueryGraphT>
inline void
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
{
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
"edge_filter must be a container of vector<bool> or vector_view<bool>");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteOne(checksum);
util::serialization::write(writer, graph);
writer.WriteElementCount64(edge_filter.size());
for (const auto &filter : edge_filter)
{
storage::serialization::write(writer, filter);
}
}
// reads .levels file
inline void readLevels(const boost::filesystem::path &path, std::vector<float> &node_levels)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
storage::serialization::read(reader, node_levels);
}
// writes .levels file
inline void writeLevels(const boost::filesystem::path &path, const std::vector<float> &node_levels)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, node_levels);
}
}
}
+409 -23
View File
@@ -1,41 +1,427 @@
#ifndef OSRM_CONTRACTOR_GRAPH_CONTRACTOR_HPP
#define OSRM_CONTRACTOR_GRAPH_CONTRACTOR_HPP
#include "contractor/contractor_dijkstra.hpp"
#include "contractor/contractor_graph.hpp"
#include "contractor/query_edge.hpp"
#include "util/deallocating_vector.hpp"
#include "util/integer_range.hpp"
#include "util/log.hpp"
#include "util/percent.hpp"
#include "util/timing_util.hpp"
#include "util/typedefs.hpp"
#include "util/xor_fast_hash.hpp"
#include "util/filtered_graph.hpp"
#include <boost/assert.hpp>
#include <tuple>
#include <tbb/enumerable_thread_specific.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <limits>
#include <memory>
#include <vector>
#if USE_STXXL_LIBRARY
#include <stxxl/vector>
#endif
namespace osrm
{
namespace contractor
{
std::vector<bool> contractGraph(ContractorGraph &graph,
std::vector<bool> node_is_uncontracted,
std::vector<bool> node_is_contractable,
std::vector<EdgeWeight> node_weights,
double core_factor = 1.0);
// Overload for contracting all nodes
inline auto contractGraph(ContractorGraph &graph,
std::vector<EdgeWeight> node_weights,
double core_factor = 1.0)
class GraphContractor
{
return contractGraph(graph, {}, {}, std::move(node_weights), core_factor);
}
private:
#if USE_STXXL_LIBRARY
template <typename T> using ExternalVector = stxxl::vector<T>;
#else
template <typename T> using ExternalVector = std::vector<T>;
#endif
// Overload no contracted nodes
inline auto contractGraph(ContractorGraph &graph,
std::vector<bool> node_is_contractable,
std::vector<EdgeWeight> node_weights,
double core_factor = 1.0)
{
return contractGraph(
graph, {}, std::move(node_is_contractable), std::move(node_weights), core_factor);
}
struct ContractorThreadData
{
ContractorDijkstra dijkstra;
std::vector<ContractorEdge> inserted_edges;
std::vector<NodeID> neighbours;
explicit ContractorThreadData(NodeID nodes) : dijkstra(nodes) {}
};
using NodeDepth = int;
struct ContractionStats
{
int edges_deleted_count;
int edges_added_count;
int original_edges_deleted_count;
int original_edges_added_count;
ContractionStats()
: edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0),
original_edges_added_count(0)
{
}
};
struct RemainingNodeData
{
RemainingNodeData() : id(0), is_independent(false) {}
NodeID id : 31;
bool is_independent : 1;
};
struct ThreadDataContainer
{
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
inline ContractorThreadData *GetThreadData()
{
bool exists = false;
auto &ref = data.local(exists);
if (!exists)
{
// ref = std::make_shared<ContractorThreadData>(number_of_nodes);
ref = std::make_shared<ContractorThreadData>(4000);
}
return ref.get();
}
int number_of_nodes;
using EnumerableThreadData =
tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
EnumerableThreadData data;
};
public:
GraphContractor(int nodes, std::vector<ContractorEdge> input_edge_list);
GraphContractor(int nodes,
std::vector<ContractorEdge> edges,
std::vector<float> node_levels_,
std::vector<EdgeWeight> node_weights_);
/* Flush all data from the contraction to disc and reorder stuff for better locality */
void FlushDataAndRebuildContractorGraph(ThreadDataContainer &thread_data_list,
std::vector<RemainingNodeData> &remaining_nodes,
std::vector<float> &node_priorities);
void Run(double core_factor = 1.0);
std::vector<bool> GetCoreMarker();
std::vector<float> GetNodeLevels();
template <class Edge> inline util::DeallocatingVector<Edge> GetEdges()
{
util::DeallocatingVector<Edge> edges;
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
util::Percent p(log, contractor_graph->GetNumberOfNodes());
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
if (contractor_graph->GetNumberOfNodes())
{
Edge new_edge;
for (const auto node : util::irange(0u, number_of_nodes))
{
p.PrintStatus(node);
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const NodeID target = contractor_graph->GetTarget(edge);
const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge);
if (!orig_node_id_from_new_node_id_map.empty())
{
new_edge.source = orig_node_id_from_new_node_id_map[node];
new_edge.target = orig_node_id_from_new_node_id_map[target];
}
else
{
new_edge.source = node;
new_edge.target = target;
}
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.source, "Source id invalid");
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
new_edge.data.weight = data.weight;
new_edge.data.duration = data.duration;
new_edge.data.shortcut = data.shortcut;
if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty())
{
// tranlate the _node id_ of the shortcutted node
new_edge.data.turn_id = orig_node_id_from_new_node_id_map[data.id];
}
else
{
new_edge.data.turn_id = data.id;
}
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
"edge id invalid");
new_edge.data.forward = data.forward;
new_edge.data.backward = data.backward;
edges.push_back(new_edge);
}
}
}
contractor_graph.reset();
orig_node_id_from_new_node_id_map.clear();
orig_node_id_from_new_node_id_map.shrink_to_fit();
BOOST_ASSERT(0 == orig_node_id_from_new_node_id_map.capacity());
edges.append(external_edge_list.begin(), external_edge_list.end());
external_edge_list.clear();
// sort and remove duplicates
tbb::parallel_sort(edges.begin(), edges.end());
auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin());
return edges;
}
private:
float EvaluateNodePriority(ContractorThreadData *const data,
const NodeDepth node_depth,
const NodeID node);
template <bool RUNSIMULATION>
bool
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
{
auto &dijkstra = data->dijkstra;
std::size_t inserted_edges_size = data->inserted_edges.size();
std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
constexpr bool SHORTCUT_ARC = true;
constexpr bool FORWARD_DIRECTION_ENABLED = true;
constexpr bool FORWARD_DIRECTION_DISABLED = false;
constexpr bool REVERSE_DIRECTION_ENABLED = true;
constexpr bool REVERSE_DIRECTION_DISABLED = false;
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
const NodeID source = contractor_graph->GetTarget(in_edge);
if (source == node)
continue;
if (RUNSIMULATION)
{
BOOST_ASSERT(stats != nullptr);
++stats->edges_deleted_count;
stats->original_edges_deleted_count += in_data.originalEdges;
}
if (!in_data.backward)
{
continue;
}
dijkstra.Clear();
dijkstra.Insert(source, 0, ContractorHeapData{});
EdgeWeight max_weight = 0;
unsigned number_of_targets = 0;
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
if (!out_data.forward)
{
continue;
}
const NodeID target = contractor_graph->GetTarget(out_edge);
if (node == target)
{
continue;
}
const EdgeWeight path_weight = in_data.weight + out_data.weight;
if (target == source)
{
if (path_weight < node_weights[node])
{
if (RUNSIMULATION)
{
// make sure to prune better, but keep inserting this loop if it should
// still be the best
// CAREFUL: This only works due to the independent node-setting. This
// guarantees that source is not connected to another node that is
// contracted
node_weights[source] = path_weight + 1;
BOOST_ASSERT(stats != nullptr);
stats->edges_added_count += 2;
stats->original_edges_added_count +=
2 * (out_data.originalEdges + in_data.originalEdges);
}
else
{
// CAREFUL: This only works due to the independent node-setting. This
// guarantees that source is not connected to another node that is
// contracted
node_weights[source] = path_weight; // make sure to prune better
inserted_edges.emplace_back(source,
target,
path_weight,
in_data.duration + out_data.duration,
out_data.originalEdges +
in_data.originalEdges,
node,
SHORTCUT_ARC,
FORWARD_DIRECTION_ENABLED,
REVERSE_DIRECTION_DISABLED);
inserted_edges.emplace_back(target,
source,
path_weight,
in_data.duration + out_data.duration,
out_data.originalEdges +
in_data.originalEdges,
node,
SHORTCUT_ARC,
FORWARD_DIRECTION_DISABLED,
REVERSE_DIRECTION_ENABLED);
}
}
continue;
}
max_weight = std::max(max_weight, path_weight);
if (!dijkstra.WasInserted(target))
{
dijkstra.Insert(target, INVALID_EDGE_WEIGHT, ContractorHeapData{0, true});
++number_of_targets;
}
}
if (RUNSIMULATION)
{
const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000;
dijkstra.Run(number_of_targets,
SIMULATION_SEARCH_SPACE_SIZE,
max_weight,
node,
*contractor_graph);
}
else
{
const int constexpr FULL_SEARCH_SPACE_SIZE = 2000;
dijkstra.Run(
number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, *contractor_graph);
}
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
if (!out_data.forward)
{
continue;
}
const NodeID target = contractor_graph->GetTarget(out_edge);
if (target == node)
continue;
const EdgeWeight path_weight = in_data.weight + out_data.weight;
const EdgeWeight weight = dijkstra.GetKey(target);
if (path_weight < weight)
{
if (RUNSIMULATION)
{
BOOST_ASSERT(stats != nullptr);
stats->edges_added_count += 2;
stats->original_edges_added_count +=
2 * (out_data.originalEdges + in_data.originalEdges);
}
else
{
inserted_edges.emplace_back(source,
target,
path_weight,
in_data.duration + out_data.duration,
out_data.originalEdges + in_data.originalEdges,
node,
SHORTCUT_ARC,
FORWARD_DIRECTION_ENABLED,
REVERSE_DIRECTION_DISABLED);
inserted_edges.emplace_back(target,
source,
path_weight,
in_data.duration + out_data.duration,
out_data.originalEdges + in_data.originalEdges,
node,
SHORTCUT_ARC,
FORWARD_DIRECTION_DISABLED,
REVERSE_DIRECTION_ENABLED);
}
}
}
}
// Check For One-Way Streets to decide on the creation of self-loops
if (!RUNSIMULATION)
{
std::size_t iend = inserted_edges.size();
for (std::size_t i = inserted_edges_size; i < iend; ++i)
{
bool found = false;
for (std::size_t other = i + 1; other < iend; ++other)
{
if (inserted_edges[other].source != inserted_edges[i].source)
{
continue;
}
if (inserted_edges[other].target != inserted_edges[i].target)
{
continue;
}
if (inserted_edges[other].data.weight != inserted_edges[i].data.weight)
{
continue;
}
if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut)
{
continue;
}
inserted_edges[other].data.forward |= inserted_edges[i].data.forward;
inserted_edges[other].data.backward |= inserted_edges[i].data.backward;
found = true;
break;
}
if (!found)
{
inserted_edges[inserted_edges_size++] = inserted_edges[i];
}
}
inserted_edges.resize(inserted_edges_size);
}
return true;
}
void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node);
bool UpdateNodeNeighbours(std::vector<float> &priorities,
std::vector<NodeDepth> &node_depth,
ContractorThreadData *const data,
const NodeID node);
bool IsNodeIndependent(const std::vector<float> &priorities,
ContractorThreadData *const data,
NodeID node) const;
// This bias function takes up 22 assembly instructions in total on X86
bool Bias(const NodeID a, const NodeID b) const;
std::shared_ptr<ContractorGraph> contractor_graph;
ExternalVector<QueryEdge> external_edge_list;
std::vector<NodeID> orig_node_id_from_new_node_id_map;
std::vector<float> node_levels;
// A list of weights for every node in the graph.
// The weight represents the cost for a u-turn on the segment in the base-graph in addition to
// its traversal.
// During contraction, self-loops are checked against this node weight to ensure that necessary
// self-loops are added.
std::vector<EdgeWeight> node_weights;
std::vector<bool> is_core_node;
util::XORFastHash<> fast_hash;
};
} // namespace contractor
} // namespace osrm
@@ -2,11 +2,7 @@
#define OSRM_CONTRACTOR_GRAPH_CONTRACTION_ADAPTORS_HPP_
#include "contractor/contractor_graph.hpp"
#include "util/log.hpp"
#include "util/percent.hpp"
#include <tbb/parallel_sort.h>
#include <vector>
@@ -17,7 +13,7 @@ namespace contractor
// Make sure to move in the input edge list!
template <typename InputEdgeContainer>
ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer input_edge_list)
std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge_list)
{
std::vector<ContractorEdge> edges;
edges.reserve(input_edge_list.size() * 2);
@@ -56,117 +52,9 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
false,
input_edge.data.backward ? true : false,
input_edge.data.forward ? true : false);
};
tbb::parallel_sort(edges.begin(), edges.end());
NodeID edge = 0;
for (NodeID i = 0; i < edges.size();)
{
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
const NodeID id = edges[i].data.id;
// remove eigenloops
if (source == target)
{
++i;
continue;
}
ContractorEdge forward_edge;
ContractorEdge reverse_edge;
forward_edge.source = reverse_edge.source = source;
forward_edge.target = reverse_edge.target = target;
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
forward_edge.data.id = reverse_edge.data.id = id;
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
// remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
{
if (edges[i].data.forward)
{
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
forward_edge.data.duration =
std::min(edges[i].data.duration, forward_edge.data.duration);
}
if (edges[i].data.backward)
{
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
reverse_edge.data.duration =
std::min(edges[i].data.duration, reverse_edge.data.duration);
}
++i;
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.weight == reverse_edge.data.weight)
{
if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT)
{
forward_edge.data.backward = true;
edges[edge++] = forward_edge;
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
{
edges[edge++] = forward_edge;
}
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
{
edges[edge++] = reverse_edge;
}
}
}
util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size();
edges.resize(edge);
return ContractorGraph{number_of_nodes, edges};
}
template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT graph)
{
std::vector<Edge> edges;
edges.reserve(graph.GetNumberOfEdges());
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
util::Percent p(log, graph.GetNumberOfNodes());
const NodeID number_of_nodes = graph.GetNumberOfNodes();
if (graph.GetNumberOfNodes())
{
Edge new_edge;
for (const auto node : util::irange(0u, number_of_nodes))
{
p.PrintStatus(node);
for (auto edge : graph.GetAdjacentEdgeRange(node))
{
const NodeID target = graph.GetTarget(edge);
const ContractorGraph::EdgeData &data = graph.GetEdgeData(edge);
new_edge.source = node;
new_edge.target = target;
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
new_edge.data.weight = data.weight;
new_edge.data.duration = data.duration;
new_edge.data.shortcut = data.shortcut;
new_edge.data.turn_id = data.id;
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
"edge id invalid");
new_edge.data.forward = data.forward;
new_edge.data.backward = data.backward;
edges.push_back(new_edge);
}
}
}
// sort and remove duplicates
tbb::parallel_sort(edges.begin(), edges.end());
auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin());
// FIXME not sure if we need this
edges.shrink_to_fit();
return edges;
}
-11
View File
@@ -21,17 +21,6 @@ struct QueryEdge
{
}
EdgeData(const NodeID turn_id,
const bool shortcut,
const EdgeWeight weight,
const EdgeWeight duration,
const bool forward,
const bool backward)
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
forward(forward), backward(backward)
{
}
template <class OtherT> EdgeData(const OtherT &other)
{
weight = other.weight;
+17 -53
View File
@@ -31,33 +31,16 @@ class CellCustomizer
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
template <typename GraphT>
void Customize(const GraphT &graph,
Heap &heap,
const partition::CellStorage &cells,
const std::vector<bool> &allowed_nodes,
CellMetric &metric,
LevelID level,
CellID id) const
void Customize(
const GraphT &graph, Heap &heap, partition::CellStorage &cells, LevelID level, CellID id)
{
auto cell = cells.GetCell(metric, level, id);
auto cell = cells.GetCell(level, id);
auto destinations = cell.GetDestinationNodes();
// for each source do forward search
for (auto source : cell.GetSourceNodes())
{
if (!allowed_nodes[source])
{
continue;
}
std::unordered_set<NodeID> destinations_set;
for (const auto destination : destinations)
{
if (allowed_nodes[destination])
{
destinations_set.insert(destination);
}
}
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
heap.Clear();
heap.Insert(source, 0, {false, 0});
@@ -68,7 +51,10 @@ class CellCustomizer
const EdgeWeight weight = heap.GetKey(node);
const EdgeDuration duration = heap.GetData(node).duration;
RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration);
if (level == 1)
RelaxNode<true>(graph, cells, heap, level, node, weight, duration);
else
RelaxNode<false>(graph, cells, heap, level, node, weight, duration);
destinations_set.erase(node);
}
@@ -94,11 +80,7 @@ class CellCustomizer
}
}
template <typename GraphT>
void Customize(const GraphT &graph,
const partition::CellStorage &cells,
const std::vector<bool> &allowed_nodes,
CellMetric &metric) const
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
{
Heap heap_exemplar(graph.GetNumberOfNodes());
HeapPtr heaps(heap_exemplar);
@@ -110,26 +92,22 @@ class CellCustomizer
auto &heap = heaps.local();
for (auto id = range.begin(), end = range.end(); id != end; ++id)
{
Customize(
graph, heap, cells, allowed_nodes, metric, level, id);
Customize(graph, heap, cells, level, id);
}
});
}
}
private:
template <typename GraphT>
template <bool first_level, typename GraphT>
void RelaxNode(const GraphT &graph,
const partition::CellStorage &cells,
const std::vector<bool> &allowed_nodes,
const CellMetric &metric,
Heap &heap,
LevelID level,
NodeID node,
EdgeWeight weight,
EdgeDuration duration) const
{
auto first_level = level == 1;
BOOST_ASSERT(heap.WasInserted(node));
if (!first_level)
@@ -145,7 +123,7 @@ class CellCustomizer
{
// Relax sub-cell nodes
auto subcell_id = partition.GetCell(level - 1, node);
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
auto subcell = cells.GetCell(level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin();
auto subcell_duration = subcell.GetOutDuration(node).begin();
for (auto subcell_weight : subcell.GetOutWeight(node))
@@ -153,22 +131,15 @@ class CellCustomizer
if (subcell_weight != INVALID_EDGE_WEIGHT)
{
const NodeID to = *subcell_destination;
if (!allowed_nodes[to])
{
continue;
}
const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true, to_duration});
heap.Insert(to, to_weight, {true, duration + *subcell_duration});
}
else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {true, to_duration};
heap.GetData(to) = {true, duration + *subcell_duration};
}
}
@@ -182,27 +153,20 @@ class CellCustomizer
for (auto edge : graph.GetInternalEdgeRange(level, node))
{
const NodeID to = graph.GetTarget(edge);
if (!allowed_nodes[to])
{
continue;
}
const auto &data = graph.GetEdgeData(edge);
if (data.forward &&
(first_level ||
partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
{
const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {false, duration + data.duration});
}
else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {false, to_duration};
heap.GetData(to) = {false, duration + data.duration};
}
}
}
-31
View File
@@ -1,31 +0,0 @@
#ifndef OSRM_CUSTOMIZER_CELL_METRIC_HPP
#define OSRM_CUSTOMIZER_CELL_METRIC_HPP
#include "storage/io_fwd.hpp"
#include "storage/shared_memory_ownership.hpp"
#include "util/typedefs.hpp"
#include "util/vector_view.hpp"
namespace osrm
{
namespace customizer
{
namespace detail
{
// Encapsulated one metric to make it easily replacable in CelLStorage
template <storage::Ownership Ownership> struct CellMetricImpl
{
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
Vector<EdgeWeight> weights;
Vector<EdgeDuration> durations;
};
}
using CellMetric = detail::CellMetricImpl<storage::Ownership::Container>;
using CellMetricView = detail::CellMetricImpl<storage::Ownership::View>;
}
}
#endif
+6 -7
View File
@@ -17,13 +17,12 @@ namespace customizer
struct CustomizationConfig final : storage::IOConfig
{
CustomizationConfig()
: IOConfig({".osrm.ebg",
".osrm.partition",
".osrm.cells",
".osrm.ebg_nodes",
".osrm.properties"},
{},
{".osrm.cell_metrics", ".osrm.mldgr"}),
: IOConfig(
{
".osrm",
},
{},
{".osrm.ebg", ".osrm.partition", ".osrm.cells", ".osrm.mldgr"}),
requested_num_threads(0)
{
}
-59
View File
@@ -1,59 +0,0 @@
#ifndef OSRM_CUSTOMIZER_FILES_HPP
#define OSRM_CUSTOMIZER_FILES_HPP
#include "customizer/serialization.hpp"
#include "storage/io.hpp"
#include "util/integer_range.hpp"
namespace osrm
{
namespace customizer
{
namespace files
{
// reads .osrm.cell_metrics file
template <typename CellMetricT>
inline void readCellMetrics(const boost::filesystem::path &path, std::vector<CellMetricT> &metrics)
{
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
std::is_same<CellMetric, CellMetricT>::value,
"");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
auto num_metrics = reader.ReadElementCount64();
metrics.resize(num_metrics);
for (auto &metric : metrics)
{
serialization::read(reader, metric);
}
}
// writes .osrm.cell_metrics file
template <typename CellMetricT>
inline void writeCellMetrics(const boost::filesystem::path &path,
const std::vector<CellMetricT> &metrics)
{
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
std::is_same<CellMetric, CellMetricT>::value,
"");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteElementCount64(metrics.size());
for (const auto &metric : metrics)
{
serialization::write(writer, metric);
}
}
}
}
}
#endif
-34
View File
@@ -1,34 +0,0 @@
#ifndef OSRM_CUSTOMIZER_SERIALIZATION_HPP
#define OSRM_CUSTOMIZER_SERIALIZATION_HPP
#include "partition/cell_storage.hpp"
#include "storage/io.hpp"
#include "storage/serialization.hpp"
#include "storage/shared_memory_ownership.hpp"
namespace osrm
{
namespace customizer
{
namespace serialization
{
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, detail::CellMetricImpl<Ownership> &metric)
{
storage::serialization::read(reader, metric.weights);
storage::serialization::read(reader, metric.durations);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer, const detail::CellMetricImpl<Ownership> &metric)
{
storage::serialization::write(writer, metric.weights);
storage::serialization::write(writer, metric.durations);
}
}
}
}
#endif
+21 -7
View File
@@ -17,6 +17,13 @@ struct Algorithm final
{
};
}
// Contraction Hiearchy with core
namespace corech
{
struct Algorithm final
{
};
}
// Multi-Level Dijkstra
namespace mld
{
@@ -28,6 +35,7 @@ struct Algorithm final
// Algorithm names
template <typename AlgorithmT> const char *name();
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
@@ -48,9 +56,6 @@ template <typename AlgorithmT> struct HasManyToManySearch final : std::false_typ
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
{
};
template <typename AlgorithmT> struct HasExcludeFlags final : std::false_type
{
};
// Algorithms supported by Contraction Hierarchies
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
@@ -71,7 +76,19 @@ template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
{
};
template <> struct HasExcludeFlags<ch::Algorithm> final : std::true_type
// Algorithms supported by Contraction Hierarchies with core
// the rest is disabled because of performance reasons
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
{
};
@@ -94,9 +111,6 @@ template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
{
};
template <> struct HasExcludeFlags<mld::Algorithm> final : std::true_type
{
};
}
}
}
+3 -5
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -68,7 +68,6 @@ struct BaseParameters
std::vector<boost::optional<double>> radiuses;
std::vector<boost::optional<Bearing>> bearings;
std::vector<boost::optional<Approach>> approaches;
std::vector<std::string> exclude;
// Adds hints to response which can be included in subsequent requests, see `hints` above.
bool generate_hints = true;
@@ -78,10 +77,9 @@ struct BaseParameters
std::vector<boost::optional<double>> radiuses_ = {},
std::vector<boost::optional<Bearing>> bearings_ = {},
std::vector<boost::optional<Approach>> approaches_ = {},
bool generate_hints_ = true,
std::vector<std::string> exclude = {})
bool generate_hints_ = true)
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
approaches(approaches_), generate_hints(generate_hints_)
{
}
-9
View File
@@ -36,15 +36,6 @@ 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);
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+5 -11
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -88,17 +88,11 @@ struct RouteParameters : public BaseParameters
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
Args... args_)
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one
// below.
: BaseParameters{std::forward<Args>(args_)...},
steps{steps_},
alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u},
annotations{false},
annotations_type{AnnotationsType::None},
geometries{geometries_},
overview{overview_},
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{false},
annotations_type{AnnotationsType::None}, geometries{geometries_}, overview{overview_},
continue_straight{continue_straight_}
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one below.
{
}
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+14 -36
View File
@@ -3,7 +3,6 @@
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
#include "engine/datafacade/shared_memory_allocator.hpp"
#include "engine/datafacade_factory.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
@@ -22,50 +21,37 @@ namespace osrm
namespace engine
{
namespace detail
{
// We need this wrapper type since template-template specilization of FacadeT is broken on clang
// when it is combined with an templated alias (DataFacade in this case).
// See https://godbolt.org/g/ZS6Xmt for an example.
template <typename AlgorithmT, typename FacadeT> class DataWatchdogImpl;
template <typename AlgorithmT>
class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>> final
// This class monitors the shared memory region that contains the pointers to
// the data and layout regions that should be used. This region is updated
// once a new dataset arrives.
template <typename AlgorithmT> class DataWatchdog final
{
using mutex_type = typename storage::SharedMonitor<storage::SharedDataTimestamp>::mutex_type;
using Facade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
using FacadeT = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
public:
DataWatchdogImpl() : active(true), timestamp(0)
DataWatchdog() : active(true), timestamp(0)
{
// create the initial facade before launching the watchdog thread
{
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
facade_factory =
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
std::make_shared<datafacade::SharedMemoryAllocator>(barrier.data().region));
facade = std::make_shared<const FacadeT>(
std::make_unique<datafacade::SharedMemoryAllocator>(barrier.data().region));
timestamp = barrier.data().timestamp;
}
watcher = std::thread(&DataWatchdogImpl::Run, this);
watcher = std::thread(&DataWatchdog::Run, this);
}
~DataWatchdogImpl()
~DataWatchdog()
{
active = false;
barrier.notify_all();
watcher.join();
}
std::shared_ptr<const Facade> Get(const api::BaseParameters &params) const
{
return facade_factory.Get(params);
}
std::shared_ptr<const Facade> Get(const api::TileParameters &params) const
{
return facade_factory.Get(params);
}
std::shared_ptr<const FacadeT> Get() const { return facade; }
private:
void Run()
@@ -82,9 +68,8 @@ class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacad
if (timestamp != barrier.data().timestamp)
{
auto region = barrier.data().region;
facade_factory =
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
std::make_shared<datafacade::SharedMemoryAllocator>(region));
facade = std::make_shared<const FacadeT>(
std::make_unique<datafacade::SharedMemoryAllocator>(region));
timestamp = barrier.data().timestamp;
util::Log() << "updated facade to region " << region << " with timestamp "
<< timestamp;
@@ -98,16 +83,9 @@ class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacad
std::thread watcher;
bool active;
unsigned timestamp;
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT> facade_factory;
std::shared_ptr<const FacadeT> facade;
};
}
// This class monitors the shared memory region that contains the pointers to
// the data and layout regions that should be used. This region is updated
// once a new dataset arrives.
template <typename AlgorithmT, template <typename A> class FacadeT>
using DataWatchdog = detail::DataWatchdogImpl<AlgorithmT, FacadeT<AlgorithmT>>;
}
}
#endif
@@ -8,7 +8,6 @@
#include "partition/cell_storage.hpp"
#include "partition/multi_level_partition.hpp"
#include "util/filtered_graph.hpp"
#include "util/integer_range.hpp"
namespace osrm
@@ -20,15 +19,17 @@ namespace datafacade
// Namespace local aliases for algorithms
using CH = routing_algorithms::ch::Algorithm;
using CoreCH = routing_algorithms::corech::Algorithm;
using MLD = routing_algorithms::mld::Algorithm;
using EdgeRange = util::range<EdgeID>;
template <typename AlgorithmT> class AlgorithmDataFacade;
template <> class AlgorithmDataFacade<CH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
using EdgeRange = util::filtered_range<EdgeID, util::vector_view<bool>>;
// search graph access
virtual unsigned GetNumberOfNodes() const = 0;
@@ -41,6 +42,10 @@ template <> class AlgorithmDataFacade<CH>
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
virtual EdgeID BeginEdges(const NodeID n) const = 0;
virtual EdgeID EndEdges(const NodeID n) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
// searches for a specific edge
@@ -56,11 +61,18 @@ template <> class AlgorithmDataFacade<CH>
const std::function<bool(EdgeData)> filter) const = 0;
};
template <> class AlgorithmDataFacade<CoreCH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
virtual bool IsCoreNode(const NodeID id) const = 0;
};
template <> class AlgorithmDataFacade<MLD>
{
public:
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
using EdgeRange = util::range<EdgeID>;
// search graph access
virtual unsigned GetNumberOfNodes() const = 0;
@@ -73,14 +85,16 @@ template <> class AlgorithmDataFacade<MLD>
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
virtual EdgeID BeginEdges(const NodeID n) const = 0;
virtual EdgeID EndEdges(const NodeID n) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual const partition::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
virtual const partition::CellStorageView &GetCellStorage() const = 0;
virtual const customizer::CellMetricView &GetCellMetric() const = 0;
virtual EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const = 0;
// searches for a specific edge
@@ -12,7 +12,6 @@
#include "customizer/edge_based_graph.hpp"
#include "extractor/datasources.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/intersection_bearings_container.hpp"
@@ -32,7 +31,6 @@
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/filtered_graph.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_bearing.hpp"
@@ -70,7 +68,7 @@ template <>
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
{
private:
using QueryGraph = util::FilteredGraphView<contractor::QueryGraphView>;
using QueryGraph = contractor::QueryGraphView;
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
@@ -79,9 +77,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
void InitializeGraphPointer(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
memory_block, storage::DataLayout::CH_GRAPH_NODE_LIST);
@@ -89,34 +85,24 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
auto filter_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::CH_EDGE_FILTER_0 + exclude_index);
auto edge_filter_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, filter_block_id);
util::vector_view<GraphNode> node_list(
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
util::vector_view<GraphEdge> edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
util::vector_view<bool> edge_filter(edge_filter_ptr,
data_layout.num_entries[filter_block_id]);
m_query_graph = QueryGraph({node_list, edge_list}, edge_filter);
m_query_graph = QueryGraph(node_list, edge_list);
}
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_, std::size_t exclude_index)
std::shared_ptr<ContiguousBlockAllocator> allocator_)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
}
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeGraphPointer(data_layout, memory_block, exclude_index);
InitializeGraphPointer(data_layout, memory_block);
}
// search graph access
@@ -136,6 +122,10 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
return m_query_graph.GetEdgeData(e);
}
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph.BeginEdges(n); }
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph.EndEdges(n); }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return m_query_graph.GetAdjacentEdgeRange(node);
@@ -166,6 +156,45 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
: public datafacade::AlgorithmDataFacade<CoreCH>
{
private:
util::vector_view<bool> m_is_core_node;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto core_marker_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
util::vector_view<bool> is_core_node(
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
m_is_core_node = std::move(is_core_node);
}
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
}
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeCoreInformationPointer(data_layout, memory_block);
}
bool IsCoreNode(const NodeID id) const override final
{
BOOST_ASSERT(id < m_is_core_node.size());
return m_is_core_node[id];
}
};
/**
* This base class implements the Datafacade interface for accessing
* data that's stored in a single large block of memory (RAM).
@@ -183,7 +212,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using RTreeNode = SharedRTree::TreeNode;
extractor::ClassData exclude_mask;
std::string m_timestamp;
extractor::ProfileProperties *m_profile_properties;
extractor::Datasources *m_datasources;
@@ -218,14 +246,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout, char *memory_block)
{
m_profile_properties = data_layout.GetBlockPtr<extractor::ProfileProperties>(
memory_block, storage::DataLayout::PROPERTIES);
exclude_mask = m_profile_properties->excludable_classes[exclude_index];
}
void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block)
@@ -294,21 +318,36 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
char *memory_ptr)
{
const auto edge_based_node_list_ptr = layout.GetBlockPtr<extractor::EdgeBasedNode>(
memory_ptr, storage::DataLayout::EDGE_BASED_NODE_DATA_LIST);
util::vector_view<extractor::EdgeBasedNode> edge_based_node_data_list(
edge_based_node_list_ptr,
layout.num_entries[storage::DataLayout::EDGE_BASED_NODE_DATA_LIST]);
const auto via_geometry_list_ptr =
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST);
util::vector_view<GeometryID> geometry_ids(
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]);
const auto annotation_data_list_ptr =
layout.GetBlockPtr<extractor::NodeBasedEdgeAnnotation>(
memory_ptr, storage::DataLayout::ANNOTATION_DATA_LIST);
util::vector_view<extractor::NodeBasedEdgeAnnotation> annotation_data(
annotation_data_list_ptr,
layout.num_entries[storage::DataLayout::ANNOTATION_DATA_LIST]);
const auto name_id_list_ptr =
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST);
util::vector_view<NameID> name_ids(name_id_list_ptr,
layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
edge_based_node_data = extractor::EdgeBasedNodeDataView(
std::move(edge_based_node_data_list), std::move(annotation_data));
const auto component_id_list_ptr =
layout.GetBlockPtr<ComponentID>(memory_ptr, storage::DataLayout::COMPONENT_ID_LIST);
util::vector_view<ComponentID> component_ids(
component_id_list_ptr, layout.num_entries[storage::DataLayout::COMPONENT_ID_LIST]);
const auto travel_mode_list_ptr = layout.GetBlockPtr<extractor::TravelMode>(
memory_ptr, storage::DataLayout::TRAVEL_MODE_LIST);
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
const auto classes_list_ptr =
layout.GetBlockPtr<extractor::ClassData>(memory_ptr, storage::DataLayout::CLASSES_LIST);
util::vector_view<extractor::ClassData> classes(
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
std::move(name_ids),
std::move(component_ids),
std::move(travel_modes),
std::move(classes));
}
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
@@ -400,6 +439,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
auto num_entries = data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST];
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::vector_view<NodeID> geometry_node_list(geometries_node_list_ptr, num_entries);
@@ -499,9 +539,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
m_entry_class_table = std::move(entry_class_table);
}
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeChecksumPointer(data_layout, memory_block);
InitializeNodeInformationPointers(data_layout, memory_block);
@@ -512,7 +550,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
InitializeTimestampPointer(data_layout, memory_block);
InitializeNamePointers(data_layout, memory_block);
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
InitializeProfilePropertiesPointer(data_layout, memory_block, exclude_index);
InitializeProfilePropertiesPointer(data_layout, memory_block);
InitializeRTreePointers(data_layout, memory_block);
InitializeIntersectionClassPointers(data_layout, memory_block);
}
@@ -520,11 +558,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
public:
// allows switching between process_memory/shared_memory datafacade, based on the type of
// allocator
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_,
const std::size_t exclude_index)
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
}
// node and edge information access
@@ -765,11 +802,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return edge_based_node_data.GetClassData(id);
}
bool ExcludeNode(const NodeID id) const override final
{
return (edge_based_node_data.GetClassData(id) & exclude_mask) > 0;
}
std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final
{
auto indexes = extractor::getClassIndexes(class_data);
@@ -880,10 +912,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
m_lane_description_offsets[lane_description_id + 1]);
}
bool IsLeftHandDriving(const NodeID id) const override final
bool IsLeftHandDriving() const override final
{
// TODO: can be moved to a data block indexed by GeometryID
return edge_based_node_data.IsLeftHandDriving(id);
return m_profile_properties->left_hand_driving;
}
};
@@ -895,10 +926,23 @@ class ContiguousInternalMemoryDataFacade<CH>
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, exclude_index)
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator)
{
}
};
template <>
class ContiguousInternalMemoryDataFacade<CoreCH> final
: public ContiguousInternalMemoryDataFacade<CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacade<CH>(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator)
{
}
@@ -909,24 +953,19 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
// MLD data
partition::MultiLevelPartitionView mld_partition;
partition::CellStorageView mld_cell_storage;
customizer::CellMetricView mld_cell_metric;
using QueryGraph = customizer::MultiLevelEdgeBasedGraphView;
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
QueryGraph query_graph;
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeMLDDataPointers(data_layout, memory_block, exclude_index);
InitializeMLDDataPointers(data_layout, memory_block);
InitializeGraphPointer(data_layout, memory_block);
}
void InitializeMLDDataPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
void InitializeMLDDataPointers(storage::DataLayout &data_layout, char *memory_block)
{
if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0)
{
@@ -953,32 +992,15 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
partition::MultiLevelPartitionView{level_data, partition, cell_to_children};
}
const auto weights_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::MLD_CELL_WEIGHTS_0 + exclude_index);
const auto durations_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::MLD_CELL_DURATIONS_0 + exclude_index);
if (data_layout.GetBlockSize(weights_block_id) > 0)
{
auto mld_cell_weights_ptr =
data_layout.GetBlockPtr<EdgeWeight>(memory_block, weights_block_id);
auto mld_cell_durations_ptr =
data_layout.GetBlockPtr<EdgeDuration>(memory_block, durations_block_id);
auto weight_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS_0);
auto duration_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS_0);
BOOST_ASSERT(weight_entries_count == duration_entries_count);
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
duration_entries_count);
mld_cell_metric = customizer::CellMetricView{std::move(weights), std::move(durations)};
}
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0)
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_WEIGHTS) > 0)
{
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0);
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS) > 0);
auto mld_cell_weights_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::MLD_CELL_WEIGHTS);
auto mld_cell_durations_ptr = data_layout.GetBlockPtr<EdgeDuration>(
memory_block, storage::DataLayout::MLD_CELL_DURATIONS);
auto mld_source_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
auto mld_destination_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
@@ -988,6 +1010,10 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr<std::uint64_t>(
memory_block, storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
auto weight_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS);
auto duration_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS);
auto source_boundary_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
auto destination_boundary_entries_count =
@@ -996,6 +1022,11 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
auto cell_level_offsets_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
BOOST_ASSERT(weight_entries_count == duration_entries_count);
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
duration_entries_count);
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
source_boundary_entries_count);
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
@@ -1005,7 +1036,9 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
cell_level_offsets_entries_count);
mld_cell_storage = partition::CellStorageView{std::move(source_boundary),
mld_cell_storage = partition::CellStorageView{std::move(weights),
std::move(durations),
std::move(source_boundary),
std::move(destination_boundary),
std::move(cells),
std::move(level_offsets)};
@@ -1039,10 +1072,10 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
std::shared_ptr<ContiguousBlockAllocator> allocator_)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
}
const partition::MultiLevelPartitionView &GetMultiLevelPartition() const override
@@ -1052,8 +1085,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
const partition::CellStorageView &GetCellStorage() const override { return mld_cell_storage; }
const customizer::CellMetricView &GetCellMetric() const override { return mld_cell_metric; }
// search graph access
unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); }
@@ -1071,6 +1102,10 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
return query_graph.GetEdgeData(e);
}
EdgeID BeginEdges(const NodeID n) const override final { return query_graph.BeginEdges(n); }
EdgeID EndEdges(const NodeID n) const override final { return query_graph.EndEdges(n); }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return query_graph.GetAdjacentEdgeRange(node);
@@ -1095,10 +1130,9 @@ class ContiguousInternalMemoryDataFacade<MLD> final
{
private:
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, exclude_index)
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator)
{
}
@@ -94,8 +94,6 @@ class BaseDataFacade
virtual extractor::ClassData GetClassData(const NodeID id) const = 0;
virtual bool ExcludeNode(const NodeID id) const = 0;
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
@@ -190,7 +188,7 @@ class BaseDataFacade
virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0;
virtual bool IsLeftHandDriving(const NodeID id) const = 0;
virtual bool IsLeftHandDriving() const = 0;
};
}
}
-134
View File
@@ -1,134 +0,0 @@
#ifndef OSRM_ENGINE_DATAFACADE_FACTORY_HPP
#define OSRM_ENGINE_DATAFACADE_FACTORY_HPP
#include "extractor/class_data.hpp"
#include "extractor/profile_properties.hpp"
#include "engine/algorithm.hpp"
#include "engine/api/base_parameters.hpp"
#include "engine/api/tile_parameters.hpp"
#include "util/integer_range.hpp"
#include "storage/shared_datatype.hpp"
#include <array>
#include <memory>
#include <unordered_map>
namespace osrm
{
namespace engine
{
// This class selects the right facade for
template <template <typename A> class FacadeT, typename AlgorithmT> class DataFacadeFactory
{
static constexpr auto has_exclude_flags = routing_algorithms::HasExcludeFlags<AlgorithmT>{};
public:
using Facade = FacadeT<AlgorithmT>;
DataFacadeFactory() = default;
template <typename AllocatorT>
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator)
: DataFacadeFactory(allocator, has_exclude_flags)
{
}
template <typename ParameterT> std::shared_ptr<const Facade> Get(const ParameterT &params) const
{
return Get(params, has_exclude_flags);
}
private:
// Algorithm with exclude flags
template <typename AllocatorT>
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::true_type)
{
for (const auto index : util::irange<std::size_t>(0, facades.size()))
{
facades[index] = std::make_shared<const Facade>(allocator, index);
}
properties = allocator->GetLayout().template GetBlockPtr<extractor::ProfileProperties>(
allocator->GetMemory(), storage::DataLayout::PROPERTIES);
for (const auto index : util::irange<std::size_t>(0, properties->class_names.size()))
{
const std::string name = properties->GetClassName(index);
if (!name.empty())
{
name_to_class[name] = extractor::getClassData(index);
}
}
}
// Algorithm without exclude flags
template <typename AllocatorT>
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::false_type)
{
facades[0] = std::make_shared<const Facade>(allocator, 0);
}
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::false_type) const
{
return facades[0];
}
// Default for non-exclude flags: return only facade
std::shared_ptr<const Facade> Get(const api::BaseParameters &params, std::false_type) const
{
if (!params.exclude.empty())
{
return {};
}
return facades[0];
}
// TileParameters don't drive from BaseParameters and generally don't have use for exclude flags
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::true_type) const
{
return facades[0];
}
// Selection logic for finding the corresponding datafacade for the given parameters
std::shared_ptr<const Facade> Get(const api::BaseParameters &params, std::true_type) const
{
if (params.exclude.empty())
return facades[0];
extractor::ClassData mask = 0;
for (const auto &name : params.exclude)
{
auto class_mask_iter = name_to_class.find(name);
if (class_mask_iter == name_to_class.end())
{
return {};
}
else
{
mask |= class_mask_iter->second;
}
}
auto exclude_iter = std::find(
properties->excludable_classes.begin(), properties->excludable_classes.end(), mask);
if (exclude_iter != properties->excludable_classes.end())
{
auto exclude_index =
std::distance(properties->excludable_classes.begin(), exclude_iter);
return facades[exclude_index];
}
return {};
}
std::array<std::shared_ptr<const Facade>, extractor::MAX_EXCLUDABLE_CLASSES> facades;
std::unordered_map<std::string, extractor::ClassData> name_to_class;
const extractor::ProfileProperties *properties = nullptr;
};
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More