Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c7293f2024 | |||
| ddc8aed25d | |||
| 5f7410057c | |||
| d55d46e64e | |||
| a83150d311 | |||
| b073bf36f3 | |||
| aaea94f776 | |||
| 055079192c | |||
| c542fc2087 | |||
| 64b9b6e888 | |||
| c58052ca04 | |||
| df4d1cb9e6 | |||
| 3349964b96 | |||
| 443ebc2551 | |||
| e6b1e3564a | |||
| 3aeb39ba95 | |||
| 51fbb4fcbd | |||
| f618531cbb | |||
| 3f737fce46 | |||
| 11df411da7 | |||
| 5f208b913c | |||
| 3131bffe11 | |||
| 4f3a7c1ec3 | |||
| 321d1988a0 | |||
| b707fcdadc | |||
| 4285660c72 | |||
| 111e689b09 | |||
| ebbb497af2 | |||
| dd9ad9fa08 | |||
| dc55edbeb1 | |||
| 1c59563c9c | |||
| f4e1f6a752 | |||
| 8c1e014d42 | |||
| b27fa42b0a | |||
| 73e008e1b0 | |||
| 45fe4b80dd | |||
| 65732db266 | |||
| 55a7e1082f | |||
| 34d5ba8fdd | |||
| ec26756084 | |||
| 0f55f24bfe | |||
| 07f2c8fd4c | |||
| 3289d53617 | |||
| 1ea5e44094 | |||
| ee208cd450 | |||
| 4370fd126d | |||
| 15a2fdd1f8 | |||
| 0eedcf69bc | |||
| 62abea30f5 | |||
| 3364be1860 | |||
| a5eeca9b51 | |||
| 1a09ff6005 | |||
| 2794a52902 | |||
| cb796e4cfc | |||
| 522ec4fc2e | |||
| 15dc5899b0 | |||
| 7e932ffbc3 | |||
| 810596bb83 | |||
| acabf0075c | |||
| 1ed72db210 | |||
| 6bdf95dfb4 | |||
| 785ae89cd8 | |||
| 16680191de |
+21
-39
@@ -17,6 +17,7 @@ notifications:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- "5.7"
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
@@ -48,43 +49,15 @@ matrix:
|
||||
|
||||
# Debug Builds
|
||||
- os: linux
|
||||
compiler: "format-taginfo-docs"
|
||||
env: NODE=6
|
||||
sudo: false
|
||||
before_install:
|
||||
install:
|
||||
- source $NVM_DIR/nvm.sh
|
||||
- nvm install $NODE
|
||||
- nvm use $NODE
|
||||
- npm --version
|
||||
- npm install --ignore-scripts
|
||||
- npm link --ignore-scripts
|
||||
script:
|
||||
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
- ${MASON} install clang-format 3.8.1
|
||||
- PATH=$(${MASON} prefix clang-format 3.8.1)/bin:${PATH} ./scripts/format.sh && ./scripts/error_on_dirty.sh
|
||||
# See issue 4043
|
||||
#- npm run docs && ./scripts/error_on_dirty.sh
|
||||
after_success:
|
||||
|
||||
- os: linux
|
||||
compiler: "gcc-6-debug-cov"
|
||||
compiler: "gcc-6-debug-cov-asan"
|
||||
addons: &gcc6
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
|
||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
- os: linux
|
||||
compiler: "gcc-6-debug-asan"
|
||||
addons: &gcc6
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
|
||||
|
||||
- os: linux
|
||||
compiler: "clang-4.0-debug"
|
||||
addons: &clang40
|
||||
@@ -175,7 +148,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
@@ -198,7 +171,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
@@ -221,7 +194,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
@@ -244,7 +217,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
@@ -274,6 +247,10 @@ before_install:
|
||||
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
||||
fi
|
||||
fi
|
||||
- |
|
||||
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
||||
${MASON} install clang-format 3.8.1 && PATH=$(${MASON} prefix clang-format 3.8.1)/bin:${PATH} ./scripts/format.sh
|
||||
fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
sudo mdutil -i off /
|
||||
@@ -286,12 +263,11 @@ before_install:
|
||||
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
|
||||
- echo "Using ${JOBS} jobs"
|
||||
- yarn install --ignore-scripts
|
||||
- yarn check --ignore-scripts --integrity
|
||||
# Bootstrap cmake to be able to run mason
|
||||
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}.tar.gz"
|
||||
- CMAKE_DIR="mason_packages/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}"
|
||||
- mkdir -p ${CMAKE_DIR}
|
||||
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${CMAKE_DIR} || travis_terminate 1
|
||||
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${CMAKE_DIR} || exit 1
|
||||
- export PATH=${CMAKE_DIR}/bin:${PATH}
|
||||
- ${MASON} install tbb 2017_20161128 && export LD_LIBRARY_PATH=$(${MASON} prefix tbb 2017_20161128)/lib/:${LD_LIBRARY_PATH}
|
||||
- ${MASON} install ccache ${CCACHE_VERSION} && export PATH=$(${MASON} prefix ccache ${CCACHE_VERSION})/bin:${PATH}
|
||||
@@ -299,12 +275,12 @@ before_install:
|
||||
if [[ ! -z ${CLANG_VERSION} ]]; then
|
||||
export CCOMPILER='clang'
|
||||
export CXXCOMPILER='clang++'
|
||||
${MASON} install clang++ ${CLANG_VERSION} && export PATH=$(${MASON} prefix clang++ ${CLANG_VERSION})/bin:${PATH} || travis_terminate 1
|
||||
${MASON} install clang++ ${CLANG_VERSION} && export PATH=$(${MASON} prefix clang++ ${CLANG_VERSION})/bin:${PATH}
|
||||
# we only enable lto for release builds
|
||||
# and therefore don't need to us ld.gold or llvm tools for linking
|
||||
# for debug builds
|
||||
if [[ ${BUILD_TYPE} == 'Release' ]]; then
|
||||
${MASON} install binutils 2.27 && export PATH=$(${MASON} prefix binutils 2.27)/bin:${PATH} || travis_terminate 1
|
||||
${MASON} install binutils 2.27 && export PATH=$(${MASON} prefix binutils 2.27)/bin:${PATH}
|
||||
fi
|
||||
fi
|
||||
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
|
||||
@@ -314,6 +290,10 @@ before_install:
|
||||
- mkdir ${OSRM_BUILD_DIR}
|
||||
|
||||
install:
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
fi
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
@@ -343,6 +323,8 @@ install:
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
# building docs only works with npm3+ not with yarn or npm2
|
||||
#- yarn run docs
|
||||
|
||||
script:
|
||||
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
|
||||
@@ -360,6 +342,6 @@ script:
|
||||
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
|
||||
npm run nodejs-tests
|
||||
fi
|
||||
- |
|
||||
- popd
|
||||
- yarn test
|
||||
|
||||
|
||||
+19
-21
@@ -1,29 +1,27 @@
|
||||
# 5.8.0
|
||||
- Changes from 5.7
|
||||
- API:
|
||||
- new parameter `approaches` for `route`, `table`, `trip` and `nearest` requests. This parameter keep waypoints on the curb side.
|
||||
'approaches' accepts both 'curb' and 'unrestricted' values.
|
||||
Note : the curb side depend on the `ProfileProperties::left_hand_driving`, it's a global property set once by the profile. If you are working with a planet dataset, the api will be wrong in some countries, and right in others.
|
||||
- NodeJs Bindings
|
||||
- new parameter `approaches` for `route`, `table`, `trip` and `nearest` requests.
|
||||
- Tools
|
||||
- `osrm-partition` now ensures it is called before `osrm-contract` and removes inconsitent .hsgr files automatically.
|
||||
- Features
|
||||
- Added conditional restriction support with `parse-conditional-restrictions=true|false` to osrm-extract. This option saves conditional turn restrictions to the .restrictions file for parsing by contract later. Added `parse-conditionals-from-now=utc time stamp` and `--time-zone-file=/path/to/file` to osrm-contract
|
||||
- Files
|
||||
- .osrm.nodes file was renamed to .nbg_nodes and .ebg_nodes was added
|
||||
- Guidance
|
||||
- #4075 Changed counting of exits on service roundabouts
|
||||
- Bugfixes
|
||||
- Fixed a copy/paste issue assigning wrong directions in similar turns (left over right)
|
||||
- #4074: fixed a bug that would announce entering highway ramps as u-turns
|
||||
# 5.7.2
|
||||
- Changes from 5.7.1:
|
||||
- Bug fixes:
|
||||
- Fixes segmentation fault caused by the fix for 3977
|
||||
|
||||
# 5.7.1
|
||||
- Bugfixes
|
||||
- #4030 Roundabout edge-case crashes post-processing
|
||||
- Changes from 5.7.0:
|
||||
- Bug fixes:
|
||||
- Fixes 3995: Negative duration caused by rounding issues.
|
||||
- Fixes 3977: Fixes exit number in roundabout if starting inside the roundabout
|
||||
- Fixes 3981: The NodeJS documentation was outdated and incomplete.
|
||||
- Fixes 4010: Performance regression while parsing CSV files. Now 5x faster.
|
||||
- Fixes 3919: Turn penalties on the cyclabilty metric were disabled.
|
||||
- Fixes 3992: Table plugin not checking for valid phantom nodes
|
||||
- Fixes 4013: `continue_straight` interaction with bearing constraints
|
||||
- Fixes 4063: Potential overflow in custom profiles for restricted ways
|
||||
- Fixes 4030: Roundabout edge-case crashes post-processing
|
||||
|
||||
# 5.7.0
|
||||
- Changes from 5.6
|
||||
- Bug fixes:
|
||||
- Fixed 505: Invalid distance value for distance as routing weight.
|
||||
- Fixed 3958: Fix traffic light penalties for non-turns
|
||||
- Fixed 3933: crash when collapsing instructions
|
||||
- Algorithm:
|
||||
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
|
||||
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
|
||||
|
||||
+12
-15
@@ -54,8 +54,8 @@ if (POLICY CMP0048)
|
||||
endif()
|
||||
project(OSRM C CXX)
|
||||
set(OSRM_VERSION_MAJOR 5)
|
||||
set(OSRM_VERSION_MINOR 8)
|
||||
set(OSRM_VERSION_PATCH 0)
|
||||
set(OSRM_VERSION_MINOR 7)
|
||||
set(OSRM_VERSION_PATCH 2)
|
||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||
|
||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
@@ -447,6 +447,10 @@ if(ENABLE_MASON)
|
||||
add_dependency_includes(${MASON_PACKAGE_tbb_INCLUDE_DIRS})
|
||||
set(TBB_LIBRARIES ${MASON_PACKAGE_tbb_LDFLAGS})
|
||||
|
||||
mason_use(libshp2 VERSION ${MASON_LIBSHP_VERSION})
|
||||
set(LIBSHAPEFILE_INCLUDE_DIR ${MASON_PACKAGE_libshp2_INCLUDE_DIRS})
|
||||
set(LIBSHAPEFILE_LIBRARY ${MASON_PACKAGE_libshp2_LDFLAGS})
|
||||
|
||||
if(NOT MASON_PACKAGE_tbb_LIBRARY_DIRS)
|
||||
message(FATAL_ERROR "MASON_PACKAGE_tbb_LIBRARY_DIRS is empty, rpath will not work")
|
||||
endif()
|
||||
@@ -473,8 +477,6 @@ if(ENABLE_MASON)
|
||||
# expat and bzip2 are used from mason rather than the system
|
||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include)
|
||||
|
||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include)
|
||||
|
||||
else()
|
||||
|
||||
find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
@@ -544,9 +546,6 @@ else()
|
||||
find_package(Osmium REQUIRED COMPONENTS io)
|
||||
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
|
||||
|
||||
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
|
||||
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
|
||||
|
||||
endif()
|
||||
|
||||
# prefix compilation with ccache by default if available and on clang or gcc
|
||||
@@ -638,8 +637,7 @@ set(UPDATER_LIBRARIES
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_RT_LIBRARY}
|
||||
${MAYBE_COVERAGE_LIBRARIES}
|
||||
${ZLIB_LIBRARY})
|
||||
${MAYBE_COVERAGE_LIBRARIES})
|
||||
set(CONTRACTOR_LIBRARIES
|
||||
${BOOST_BASE_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
@@ -667,7 +665,6 @@ set(UTIL_LIBRARIES
|
||||
${STXXL_LIBRARY}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_COVERAGE_LIBRARIES})
|
||||
|
||||
# Libraries
|
||||
target_link_libraries(osrm ${ENGINE_LIBRARIES})
|
||||
target_link_libraries(osrm_update ${UPDATER_LIBRARIES})
|
||||
@@ -679,7 +676,7 @@ target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
||||
|
||||
# BUILD_COMPONENTS
|
||||
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-components ${TBB_LIBRARIES} ${BOOST_BASE_LIBRARIES} ${UTIL_LIBRARIES})
|
||||
target_link_libraries(osrm-components ${TBB_LIBRARIES} ${BOOST_BASE_LIBRARIES})
|
||||
install(TARGETS osrm-components DESTINATION bin)
|
||||
|
||||
if(BUILD_TOOLS)
|
||||
@@ -689,12 +686,12 @@ if(BUILD_TOOLS)
|
||||
|
||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||
|
||||
find_package(Shapefile)
|
||||
find_package(Shapefile) # package libshp-dev
|
||||
if(SHAPEFILE_FOUND AND (Boost_VERSION VERSION_GREATER 106000 OR ENABLE_MASON))
|
||||
add_executable(osrm-extract-conditionals src/tools/extract-conditionals.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_include_directories(osrm-extract-conditionals PRIVATE ${LIBSHAPEFILE_INCLUDE_DIR})
|
||||
target_link_libraries(osrm-extract-conditionals ${OSMIUM_LIBRARIES} ${BOOST_BASE_LIBRARIES} ${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${UTIL_LIBRARIES} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARY} ${EXPAT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
${LIBSHAPEFILE_LIBRARY} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARY} ${EXPAT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
install(TARGETS osrm-extract-conditionals DESTINATION bin)
|
||||
endif()
|
||||
endif()
|
||||
@@ -716,8 +713,8 @@ set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
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)
|
||||
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/phantom_node.hpp)
|
||||
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp include/util/exception.hpp)
|
||||
set(ExtractorHeader include/extractor/extractor.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)
|
||||
|
||||
@@ -69,15 +69,6 @@ In case Docker complains about not being able to connect to the Docker daemon ma
|
||||
|
||||
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
|
||||
|
||||
We support the following images on Docker Cloud:
|
||||
|
||||
Name | Description
|
||||
-----|------
|
||||
`latest` | `master` compiled with release flag
|
||||
`latest-assertions` | `master` compiled with with release flag, assertions enabled and debug symbols
|
||||
`latest-debug` | `master` compiled with debug flag
|
||||
`<tag>` | specific tag compiled with release flag
|
||||
`<tag>-debug` | specific tag compiled with debug flag
|
||||
|
||||
### Building from Source
|
||||
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
# Vendored NodeJs.cmake to bootstrap our C++ build without
|
||||
# having the user to install Node modules via `npm install`.
|
||||
#
|
||||
# Update via: ../node_modules/.bin/ncmake update
|
||||
|
||||
|
||||
# Defaults for standard Node.js builds
|
||||
set(NODEJS_DEFAULT_URL https://nodejs.org/download/release)
|
||||
set(NODEJS_DEFAULT_VERSION installed)
|
||||
set(NODEJS_VERSION_FALLBACK latest)
|
||||
set(NODEJS_DEFAULT_NAME node)
|
||||
set(NODEJS_DEFAULT_CHECKSUM SHASUMS256.txt)
|
||||
set(NODEJS_DEFAULT_CHECKTYPE SHA256)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Find a path by walking upward from a base directory until the path is
|
||||
# found. Sets the variable ${PATH} to False if the path can't
|
||||
# be determined
|
||||
function(find_path_parent NAME BASE PATH)
|
||||
set(ROOT ${BASE})
|
||||
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
|
||||
set(DRIVE "^[A-Za-z]?:?/$")
|
||||
while(NOT ROOT MATCHES ${DRIVE} AND NOT EXISTS ${ROOT}/${NAME})
|
||||
get_filename_component(ROOT ${ROOT} DIRECTORY)
|
||||
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
|
||||
endwhile()
|
||||
if(ROOT MATCHES ${DRIVE})
|
||||
set(${PATH} False PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Shortcut for finding standard node module locations
|
||||
macro(find_nodejs_module NAME BASE PATH)
|
||||
find_path_parent(node_modules/${NAME} ${BASE} ${PATH})
|
||||
endmacro()
|
||||
|
||||
# Download with a bit of nice output (without spewing progress)
|
||||
function(download_file URL)
|
||||
message(STATUS "Downloading: ${URL}")
|
||||
file(DOWNLOAD
|
||||
${URL}
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Embedded win_delay_load_hook file so that this file can be copied
|
||||
# into projects directly (recommended practice)
|
||||
function(nodejs_generate_delayload_hook OUTPUT)
|
||||
file(WRITE ${OUTPUT} "")
|
||||
file(APPEND ${OUTPUT} "/*\n")
|
||||
file(APPEND ${OUTPUT} " * When this file is linked to a DLL, it sets up a delay-load hook that\n")
|
||||
file(APPEND ${OUTPUT} " * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe'\n")
|
||||
file(APPEND ${OUTPUT} " * dynamically. Instead of trying to locate the .exe file it'll just return\n")
|
||||
file(APPEND ${OUTPUT} " * a handle to the process image.\n")
|
||||
file(APPEND ${OUTPUT} " *\n")
|
||||
file(APPEND ${OUTPUT} " * This allows compiled addons to work when node.exe or iojs.exe is renamed.\n")
|
||||
file(APPEND ${OUTPUT} " */\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifdef _MSC_VER\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifndef DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
|
||||
file(APPEND ${OUTPUT} "#define DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifndef WIN32_LEAN_AND_MEAN\n")
|
||||
file(APPEND ${OUTPUT} "#define WIN32_LEAN_AND_MEAN\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#include <windows.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <Shlwapi.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <delayimp.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <string.h>\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) {\n")
|
||||
file(APPEND ${OUTPUT} " if (event != dliNotePreLoadLibrary) return NULL;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " if (_stricmp(info->szDll, \"iojs.exe\") != 0 &&\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.exe\") != 0 &&\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.dll\") != 0)\n")
|
||||
file(APPEND ${OUTPUT} " return NULL;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get a handle to the current process executable.\n")
|
||||
file(APPEND ${OUTPUT} " HMODULE processModule = GetModuleHandle(NULL);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get the path to the executable.\n")
|
||||
file(APPEND ${OUTPUT} " TCHAR processPath[_MAX_PATH];\n")
|
||||
file(APPEND ${OUTPUT} " GetModuleFileName(processModule, processPath, _MAX_PATH);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get the name of the current executable.\n")
|
||||
file(APPEND ${OUTPUT} " LPSTR processName = PathFindFileName(processPath);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // If the current process is node or iojs, then just return the proccess \n")
|
||||
file(APPEND ${OUTPUT} " // module.\n")
|
||||
file(APPEND ${OUTPUT} " if (_stricmp(processName, \"node.exe\") == 0 ||\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(processName, \"iojs.exe\") == 0) {\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
|
||||
file(APPEND ${OUTPUT} " }\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // If it is another process, attempt to load 'node.dll' from the same \n")
|
||||
file(APPEND ${OUTPUT} " // directory.\n")
|
||||
file(APPEND ${OUTPUT} " PathRemoveFileSpec(processPath);\n")
|
||||
file(APPEND ${OUTPUT} " PathAppend(processPath, \"node.dll\");\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " HMODULE nodeDllModule = GetModuleHandle(processPath);\n")
|
||||
file(APPEND ${OUTPUT} " if(nodeDllModule != NULL) {\n")
|
||||
file(APPEND ${OUTPUT} " // This application has a node.dll in the same directory as the executable,\n")
|
||||
file(APPEND ${OUTPUT} " // use that.\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) nodeDllModule;\n")
|
||||
file(APPEND ${OUTPUT} " }\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Fallback to the current executable, which must statically link to \n")
|
||||
file(APPEND ${OUTPUT} " // node.lib\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
|
||||
file(APPEND ${OUTPUT} "}\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "PfnDliHook __pfnDliNotifyHook2 = load_exe_hook;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
endfunction()
|
||||
|
||||
# Sets up a project to build Node.js native modules
|
||||
# - Downloads required dependencies and unpacks them to the build directory.
|
||||
# Internet access is required the first invocation but not after (
|
||||
# provided the download is successful)
|
||||
# - Sets up several variables for building against the downloaded
|
||||
# dependencies
|
||||
# - Guarded to prevent multiple executions, so a single project hierarchy
|
||||
# will only call this once
|
||||
function(nodejs_init)
|
||||
# Prevents this function from executing more than once
|
||||
if(NODEJS_INIT)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Regex patterns used by the init function for component extraction
|
||||
set(HEADERS_MATCH "^([A-Fa-f0-9]+)[ \t]+([^-]+)-(headers|v?[0-9.]+)-(headers|v?[0-9.]+)([.]tar[.]gz)$")
|
||||
set(LIB32_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-x86)?(/)?([^/]*)(.lib)$")
|
||||
set(LIB64_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-)?(x64/)(.*)(.lib)$")
|
||||
|
||||
# Parse function arguments
|
||||
cmake_parse_arguments(nodejs_init
|
||||
"" "URL;NAME;VERSION;CHECKSUM;CHECKTYPE" "" ${ARGN}
|
||||
)
|
||||
|
||||
# Allow the download URL to be overridden by command line argument
|
||||
# NODEJS_URL
|
||||
if(NODEJS_URL)
|
||||
set(URL ${NODEJS_URL})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(URL ${NODEJS_DEFAULT_URL})
|
||||
if(nodejs_init_URL)
|
||||
set(URL ${nodejs_init_URL})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow name to be overridden by command line argument NODEJS_NAME
|
||||
if(NODEJS_NAME)
|
||||
set(NAME ${NODEJS_NAME})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(NAME ${NODEJS_DEFAULT_NAME})
|
||||
if(nodejs_init_NAME)
|
||||
set(NAME ${nodejs_init_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the checksum file to be overridden by command line argument
|
||||
# NODEJS_CHECKSUM
|
||||
if(NODEJS_CHECKSUM)
|
||||
set(CHECKSUM ${NODEJS_CHECKSUM})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(CHECKSUM ${NODEJS_DEFAULT_CHECKSUM})
|
||||
if(nodejs_init_CHECKSUM)
|
||||
set(CHECKSUM ${nodejs_init_CHECKSUM})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the checksum type to be overriden by the command line argument
|
||||
# NODEJS_CHECKTYPE
|
||||
if(NODEJS_CHECKTYPE)
|
||||
set(CHECKTYPE ${NODEJS_CHECKTYPE})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(CHECKTYPE ${NODEJS_DEFAULT_CHECKTYPE})
|
||||
if(nodejs_init_CHECKTYPE)
|
||||
set(CHECKTYPE ${nodejs_init_CHECKTYPE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the version to be overridden by the command line argument
|
||||
# NODEJS_VERSION
|
||||
if(NODEJS_VERSION)
|
||||
set(VERSION ${NODEJS_VERSION})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(VERSION ${NODEJS_DEFAULT_VERSION})
|
||||
if(nodejs_init_VERSION)
|
||||
set(VERSION ${nodejs_init_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# "installed" is a special version that tries to use the currently
|
||||
# installed version (determined by running node)
|
||||
set(NODEJS_INSTALLED False CACHE BOOL "Node.js install status" FORCE)
|
||||
if(VERSION STREQUAL "installed")
|
||||
if(NOT NAME STREQUAL ${NODEJS_DEFAULT_NAME})
|
||||
message(FATAL_ERROR
|
||||
"'Installed' version identifier can only be used with"
|
||||
"the core Node.js library"
|
||||
)
|
||||
endif()
|
||||
# Fall back to the "latest" version if node isn't installed
|
||||
set(VERSION ${NODEJS_VERSION_FALLBACK})
|
||||
find_program(NODEJS_BINARY NAMES node nodejs)
|
||||
if(NODEJS_BINARY)
|
||||
execute_process(
|
||||
COMMAND ${NODEJS_BINARY} --version
|
||||
RESULT_VARIABLE INSTALLED_VERSION_RESULT
|
||||
OUTPUT_VARIABLE INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(INSTALLED_VERSION_RESULT STREQUAL "0")
|
||||
set(NODEJS_INSTALLED True CACHE BOOL
|
||||
"Node.js install status" FORCE
|
||||
)
|
||||
set(VERSION ${INSTALLED_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create a temporary download directory
|
||||
set(TEMP ${CMAKE_CURRENT_BINARY_DIR}/temp)
|
||||
if(EXISTS ${TEMP})
|
||||
file(REMOVE_RECURSE ${TEMP})
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${TEMP})
|
||||
|
||||
# Unless the target is special version "latest", the parameters
|
||||
# necessary to construct the root path are known
|
||||
if(NOT VERSION STREQUAL "latest")
|
||||
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
|
||||
# Extract checksums from the existing checksum file
|
||||
set(CHECKSUM_TARGET ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# If we're trying to determine the version or we haven't saved the
|
||||
# checksum file for this version, download it from the specified server
|
||||
if(VERSION STREQUAL "latest" OR
|
||||
(DEFINED ROOT AND NOT EXISTS ${ROOT}/CHECKSUM))
|
||||
if(DEFINED ROOT)
|
||||
# Clear away the old checksum in case the new one is different
|
||||
# and/or it fails to download
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
download_file(
|
||||
${URL}/${VERSION}/${CHECKSUM}
|
||||
${TEMP}/CHECKSUM
|
||||
INACTIVITY_TIMEOUT 10
|
||||
STATUS CHECKSUM_STATUS
|
||||
)
|
||||
list(GET CHECKSUM_STATUS 0 CHECKSUM_STATUS)
|
||||
if(CHECKSUM_STATUS GREATER 0)
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download checksum file"
|
||||
)
|
||||
endif()
|
||||
# Extract checksums from the temporary file
|
||||
set(CHECKSUM_TARGET ${TEMP}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# Extract the version, name, header archive and archive checksum
|
||||
# from the file. This first extract is what defines / specifies the
|
||||
# actual version number and name.
|
||||
file(STRINGS
|
||||
${CHECKSUM_TARGET} HEADERS_CHECKSUM
|
||||
REGEX ${HEADERS_MATCH}
|
||||
LIMIT_COUNT 1
|
||||
)
|
||||
if(NOT HEADERS_CHECKSUM)
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
if(DEFINED ROOT)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
message(FATAL_ERROR "Unable to extract header archive checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${HEADERS_MATCH} HEADERS_CHECKSUM ${HEADERS_CHECKSUM})
|
||||
set(HEADERS_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(NAME ${CMAKE_MATCH_2})
|
||||
if(CMAKE_MATCH_3 STREQUAL "headers")
|
||||
set(VERSION ${CMAKE_MATCH_4})
|
||||
else()
|
||||
set(VERSION ${CMAKE_MATCH_3})
|
||||
endif()
|
||||
set(HEADERS_ARCHIVE
|
||||
${CMAKE_MATCH_2}-${CMAKE_MATCH_3}-${CMAKE_MATCH_4}${CMAKE_MATCH_5}
|
||||
)
|
||||
# Make sure that the root directory exists, and that the checksum
|
||||
# file has been moved over from temp
|
||||
if(DEFINED ROOT)
|
||||
set(OLD_ROOT ${ROOT})
|
||||
endif()
|
||||
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
|
||||
if(DEFINED OLD_ROOT AND NOT ROOT STREQUAL "${OLD_ROOT}")
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
message(FATAL_ERROR "Version/Name mismatch")
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${ROOT})
|
||||
if(EXISTS ${TEMP}/CHECKSUM)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
file(RENAME ${TEMP}/CHECKSUM ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# Now that its fully resolved, report the name and version of Node.js being
|
||||
# used
|
||||
message(STATUS "NodeJS: Using ${NAME}, version ${VERSION}")
|
||||
|
||||
# Download the headers for the version being used
|
||||
# Theoretically, these could be found by searching the installed
|
||||
# system, but in practice, this can be error prone. They're provided
|
||||
# on the download servers, so just use the ones there.
|
||||
if(NOT EXISTS ${ROOT}/include)
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${HEADERS_ARCHIVE}
|
||||
${TEMP}/${HEADERS_ARCHIVE}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${HEADERS_CHECKSUM}
|
||||
STATUS HEADERS_STATUS
|
||||
)
|
||||
list(GET HEADERS_STATUS 0 HEADERS_STATUS)
|
||||
if(HEADER_STATUS GREATER 0)
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
message(FATAL_ERROR "Unable to download Node.js headers")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xfz ${TEMP}/${HEADERS_ARCHIVE}
|
||||
WORKING_DIRECTORY ${TEMP}
|
||||
)
|
||||
|
||||
# This adapts the header extraction to support a number of different
|
||||
# header archive contents in addition to the one used by the
|
||||
# default Node.js library
|
||||
unset(NODEJS_HEADERS_PATH CACHE)
|
||||
find_path(NODEJS_HEADERS_PATH
|
||||
NAMES src include
|
||||
PATHS
|
||||
${TEMP}/${NAME}-${VERSION}-headers
|
||||
${TEMP}/${NAME}-${VERSION}
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}-headers
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}
|
||||
${TEMP}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(NOT NODEJS_HEADERS_PATH)
|
||||
message(FATAL_ERROR "Unable to find extracted headers folder")
|
||||
endif()
|
||||
|
||||
# Move the headers into a standard location with a standard layout
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
if(EXISTS ${NODEJS_HEADERS_PATH}/include/node)
|
||||
file(RENAME ${NODEJS_HEADERS_PATH}/include/node ${ROOT}/include)
|
||||
elseif(EXISTS ${NODEJS_HEADERS_PATH}/src)
|
||||
file(MAKE_DIRECTORY ${ROOT}/include)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/src)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find core headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/src/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/uv/include)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find libuv headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/uv/include/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/v8/include)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find v8 headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/v8/include/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/zlib)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find zlib headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/zlib/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${NODEJS_HEADERS_PATH})
|
||||
unset(NODEJS_HEADERS_PATH CACHE)
|
||||
endif()
|
||||
|
||||
# Only download the libraries on windows, since its the only place
|
||||
# its necessary. Note, this requires rerunning CMake if moving
|
||||
# a module from one platform to another (should happen automatically
|
||||
# with most generators)
|
||||
if(WIN32)
|
||||
# Download the win32 library for linking
|
||||
file(STRINGS
|
||||
${ROOT}/CHECKSUM LIB32_CHECKSUM
|
||||
LIMIT_COUNT 1
|
||||
REGEX ${LIB32_MATCH}
|
||||
)
|
||||
if(NOT LIB32_CHECKSUM)
|
||||
message(FATAL_ERROR "Unable to extract x86 library checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${LIB32_MATCH} LIB32_CHECKSUM ${LIB32_CHECKSUM})
|
||||
set(LIB32_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(LIB32_PATH win-x86)
|
||||
set(LIB32_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
|
||||
set(LIB32_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB32_NAME})
|
||||
if(NOT EXISTS ${ROOT}/${LIB32_PATH})
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${LIB32_TARGET}
|
||||
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${LIB32_CHECKSUM}
|
||||
STATUS LIB32_STATUS
|
||||
)
|
||||
list(GET LIB32_STATUS 0 LIB32_STATUS)
|
||||
if(LIB32_STATUS GREATER 0)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download Node.js windows library (32-bit)"
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${ROOT}/${LIB32_PATH})
|
||||
file(MAKE_DIRECTORY ${ROOT}/${LIB32_PATH})
|
||||
file(RENAME
|
||||
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
|
||||
${ROOT}/${LIB32_PATH}/${LIB32_NAME}
|
||||
)
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
|
||||
endif()
|
||||
|
||||
# Download the win64 library for linking
|
||||
file(STRINGS
|
||||
${ROOT}/CHECKSUM LIB64_CHECKSUM
|
||||
LIMIT_COUNT 1
|
||||
REGEX ${LIB64_MATCH}
|
||||
)
|
||||
if(NOT LIB64_CHECKSUM)
|
||||
message(FATAL_ERROR "Unable to extract x64 library checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${LIB64_MATCH} LIB64_CHECKSUM ${LIB64_CHECKSUM})
|
||||
set(LIB64_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(LIB64_PATH win-x64)
|
||||
set(LIB64_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
|
||||
set(LIB64_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB64_NAME})
|
||||
if(NOT EXISTS ${ROOT}/${LIB64_PATH})
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${LIB64_TARGET}
|
||||
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${LIB64_CHECKSUM}
|
||||
STATUS LIB64_STATUS
|
||||
)
|
||||
list(GET LIB64_STATUS 0 LIB64_STATUS)
|
||||
if(LIB64_STATUS GREATER 0)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download Node.js windows library (64-bit)"
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${ROOT}/${LIB64_PATH})
|
||||
file(MAKE_DIRECTORY ${ROOT}/${LIB64_PATH})
|
||||
file(RENAME
|
||||
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
|
||||
${ROOT}/${LIB64_PATH}/${LIB64_NAME}
|
||||
)
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The downloaded headers should always be set for inclusion
|
||||
list(APPEND INCLUDE_DIRS ${ROOT}/include)
|
||||
|
||||
# Look for the NAN module, and add it to the includes
|
||||
find_nodejs_module(
|
||||
nan
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
NODEJS_NAN_DIR
|
||||
)
|
||||
if(NODEJS_NAN_DIR)
|
||||
list(APPEND INCLUDE_DIRS ${NODEJS_NAN_DIR})
|
||||
endif()
|
||||
|
||||
# Under windows, we need a bunch of libraries (due to the way
|
||||
# dynamic linking works)
|
||||
if(WIN32)
|
||||
# Generate and use a delay load hook to allow the node binary
|
||||
# name to be changed while still loading native modules
|
||||
set(DELAY_LOAD_HOOK ${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c)
|
||||
nodejs_generate_delayload_hook(${DELAY_LOAD_HOOK})
|
||||
set(SOURCES ${DELAY_LOAD_HOOK})
|
||||
|
||||
# Necessary flags to get delayload working correctly
|
||||
list(APPEND LINK_FLAGS
|
||||
"-IGNORE:4199"
|
||||
"-DELAYLOAD:iojs.exe"
|
||||
"-DELAYLOAD:node.exe"
|
||||
"-DELAYLOAD:node.dll"
|
||||
)
|
||||
|
||||
# Core system libraries used by node
|
||||
list(APPEND LIBRARIES
|
||||
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
|
||||
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
|
||||
odbc32.lib Shlwapi.lib DelayImp.lib
|
||||
)
|
||||
|
||||
# Also link to the node stub itself (downloaded above)
|
||||
if(CMAKE_CL_64)
|
||||
list(APPEND LIBRARIES ${ROOT}/${LIB64_PATH}/${LIB64_NAME})
|
||||
else()
|
||||
list(APPEND LIBRARIES ${ROOT}/${LIB32_PATH}/${LIB32_NAME})
|
||||
endif()
|
||||
else()
|
||||
# Non-windows platforms should use these flags
|
||||
list(APPEND DEFINITIONS _LARGEFILE_SOURCE _FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
||||
# Special handling for OSX / clang to allow undefined symbols
|
||||
# Define is required by node on OSX
|
||||
if(APPLE)
|
||||
list(APPEND LINK_FLAGS "-undefined dynamic_lookup")
|
||||
list(APPEND DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
|
||||
endif()
|
||||
|
||||
# Export all settings for use as arguments in the rest of the build
|
||||
set(NODEJS_VERSION ${VERSION} PARENT_SCOPE)
|
||||
set(NODEJS_SOURCES ${SOURCES} PARENT_SCOPE)
|
||||
set(NODEJS_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
|
||||
set(NODEJS_LIBRARIES ${LIBRARIES} PARENT_SCOPE)
|
||||
set(NODEJS_LINK_FLAGS ${LINK_FLAGS} PARENT_SCOPE)
|
||||
set(NODEJS_DEFINITIONS ${DEFINITIONS} PARENT_SCOPE)
|
||||
|
||||
# Prevents this function from executing more than once
|
||||
set(NODEJS_INIT TRUE PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Helper function for defining a node module
|
||||
# After nodejs_init, all of the settings and dependencies necessary to do
|
||||
# this yourself are defined, but this helps make sure everything is configured
|
||||
# correctly. Feel free to use it as a model to do this by hand (or to
|
||||
# tweak this configuration if you need something custom).
|
||||
function(add_nodejs_module NAME)
|
||||
# Validate name parameter (must be a valid C identifier)
|
||||
string(MAKE_C_IDENTIFIER ${NAME} ${NAME}_SYMBOL_CHECK)
|
||||
if(NOT "${NAME}" STREQUAL "${${NAME}_SYMBOL_CHECK}")
|
||||
message(FATAL_ERROR
|
||||
"Module name must be a valid C identifier. "
|
||||
"Suggested alternative: '${${NAME}_SYMBOL_CHECK}'"
|
||||
)
|
||||
endif()
|
||||
# Make sure node is initialized (variables set) before defining the module
|
||||
if(NOT NODEJS_INIT)
|
||||
message(FATAL_ERROR
|
||||
"Node.js has not been initialized. "
|
||||
"Call nodejs_init before adding any modules"
|
||||
)
|
||||
endif()
|
||||
# In order to match node-gyp, we need to build into type specific folders
|
||||
# ncmake takes care of this, but be sure to set CMAKE_BUILD_TYPE yourself
|
||||
# if invoking CMake directly
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
||||
message(FATAL_ERROR
|
||||
"Configuration type must be specified. "
|
||||
"Set CMAKE_BUILD_TYPE or use a different generator"
|
||||
)
|
||||
endif()
|
||||
|
||||
# A node module is a shared library
|
||||
add_library(${NAME} SHARED ${NODEJS_SOURCES} ${ARGN})
|
||||
# Add compiler defines for the module
|
||||
# Two helpful ones:
|
||||
# MODULE_NAME must match the name of the build library, define that here
|
||||
# ${NAME}_BUILD is for symbol visibility under windows
|
||||
string(TOUPPER "${NAME}_BUILD" ${NAME}_BUILD_DEF)
|
||||
target_compile_definitions(${NAME}
|
||||
PRIVATE MODULE_NAME=${NAME}
|
||||
PRIVATE ${${NAME}_BUILD_DEF}
|
||||
PUBLIC ${NODEJS_DEFINITIONS}
|
||||
)
|
||||
# This properly defines includes for the module
|
||||
target_include_directories(${NAME} PUBLIC ${NODEJS_INCLUDE_DIRS})
|
||||
|
||||
# Add link flags to the module
|
||||
target_link_libraries(${NAME} ${NODEJS_LIBRARIES})
|
||||
|
||||
# Set required properties for the module to build properly
|
||||
# Correct naming, symbol visiblity and C++ standard
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
OUTPUT_NAME ${NAME}
|
||||
PREFIX ""
|
||||
SUFFIX ".node"
|
||||
MACOSX_RPATH ON
|
||||
C_VISIBILITY_PRESET hidden
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
CMAKE_CXX_STANDARD_REQUIRED TRUE
|
||||
CXX_STANDARD 11
|
||||
LINK_FLAGS "${NODEJS_LINK_FLAGS}"
|
||||
)
|
||||
|
||||
# Make sure we're buiilding in a build specific output directory
|
||||
# Only necessary on single-target generators (Make, Ninja)
|
||||
# Multi-target generators do this automatically
|
||||
# This (luckily) mirrors node-gyp conventions
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(TARGET ${NAME} PROPERTY
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
+1
-1
@@ -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 --tags ~@alternative --tags ~@matrix --tags ~@trip --tags --require features/support --require features/step_definitions -f progress'
|
||||
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@matrix --tags ~@trip --require features/support --require features/step_definitions -f progress'
|
||||
}
|
||||
|
||||
+11
-18
@@ -1,9 +1,15 @@
|
||||
FROM alpine:3.5
|
||||
|
||||
ARG DOCKER_TAG
|
||||
|
||||
RUN mkdir /src
|
||||
COPY . /src
|
||||
|
||||
RUN mkdir /opt
|
||||
WORKDIR /opt
|
||||
|
||||
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
case ${DOCKER_TAG} in *"-debug"*) BUILD_TYPE="Debug";; *) BUILD_TYPE="Release";; esac && \
|
||||
\
|
||||
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
||||
apk update && \
|
||||
apk upgrade && \
|
||||
@@ -17,26 +23,13 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
cd build && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .. && \
|
||||
make -j${NPROC} && \
|
||||
make install
|
||||
|
||||
ARG DOCKER_TAG
|
||||
RUN mkdir /src
|
||||
COPY . /src
|
||||
WORKDIR /src
|
||||
|
||||
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
|
||||
make install && \
|
||||
\
|
||||
echo "Building OSRM ${DOCKER_TAG}" && \
|
||||
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
|
||||
echo "Building OSRM gitsha $(cat /opt/OSRM_GITSHA)" && \
|
||||
cd /src && \
|
||||
mkdir build && \
|
||||
cd build && \
|
||||
BUILD_TYPE="Release" && \
|
||||
ENABLE_ASSERTIONS="Off" && \
|
||||
BUILD_TOOLS="Off" && \
|
||||
case ${DOCKER_TAG} in *"-debug"*) BUILD_TYPE="Debug";; esac && \
|
||||
case ${DOCKER_TAG} in *"-assertions"*) BUILD_TYPE="RelWithDebInfo" && ENABLE_ASSERTIONS="On" && BUILD_TOOLS="On";; esac && \
|
||||
echo "Building ${BUILD_TYPE} with ENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} BUILD_TOOLS=${BUILD_TOOLS}" && \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} -DBUILD_TOOLS=${BUILD_TOOLS} -DENABLE_LTO=On && \
|
||||
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_LTO=On .. && \
|
||||
make -j${NPROC} install && \
|
||||
cd ../profiles && \
|
||||
cp -r * /opt && \
|
||||
|
||||
+1
-3
@@ -30,7 +30,6 @@ To pass parameters to each location some options support an array like encoding:
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. |
|
||||
|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. |
|
||||
|
||||
Where the elements follow the following format:
|
||||
|
||||
@@ -39,7 +38,6 @@ Where the elements follow the following format:
|
||||
|bearing |`{value},{range}` `integer 0 .. 360,integer 0 .. 180` |
|
||||
|radius |`double >= 0` or `unlimited` (default) |
|
||||
|hint |Base64 `string` |
|
||||
|approach |`curb` or `unrestricted` (default) |
|
||||
|
||||
```
|
||||
{option}={element};{element}[;{element} ... ]
|
||||
@@ -302,7 +300,7 @@ The area to search is chosen such that the correct candidate should be considere
|
||||
Each `Waypoint` object has the following additional properties:
|
||||
- `matchings_index`: Index to the `Route` object in `matchings` the sub-trace was matched to.
|
||||
- `waypoint_index`: Index of the waypoint inside the matched route.
|
||||
- `alternatives_count`: Number of probable alternative matchings for this trace point. A value of zero indicate that this point was matched unambiguously. Split the trace at these points for incremental map matching.
|
||||
- `alternatives_count`: number of alternative routes leading to the destination from this trace point. 0 means there are no other routes reaching destination. Greater values mean that there are different routes available and different route can be selected if you provide more coordinates.
|
||||
- `matchings`: An array of `Route` objects that assemble the trace. Each `Route` object has the following additional properties:
|
||||
- `confidence`: Confidence of the matching. `float` value between 0 and 1. 1 is very confident that the matching is correct.
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ Returns the fastest route between two or more coordinates while visiting the way
|
||||
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
|
||||
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
|
||||
`null`/`true`/`false`
|
||||
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
|
||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||
|
||||
**Examples**
|
||||
@@ -79,7 +78,6 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
|
||||
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
|
||||
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
|
||||
Must be an integer greater than or equal to `1`. (optional, default `1`)
|
||||
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
|
||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||
|
||||
**Examples**
|
||||
@@ -118,7 +116,6 @@ tables.
|
||||
location with given index as source. Default is to use all.
|
||||
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
|
||||
#coordinates`) to use location with given index as destination. Default is to use all.
|
||||
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
|
||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||
|
||||
**Examples**
|
||||
@@ -257,7 +254,6 @@ Right now, the following combinations are possible:
|
||||
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
|
||||
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
|
||||
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
|
||||
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
|
||||
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
|
||||
|
||||
**Examples**
|
||||
|
||||
+23
-23
@@ -29,40 +29,40 @@ The following global properties can be set in your profile:
|
||||
|
||||
Attribute | Type | Notes
|
||||
------------------------------|----------|----------------------------------------------------------------------------
|
||||
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
|
||||
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
|
||||
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
|
||||
use_turn_restrictions | Boolean | Are turn instructions followed? (default `false`)
|
||||
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
|
||||
weight_name | String | Name used in output for the routing weight property (default 'duration')
|
||||
weight_precision | Unsigned | Decimal precision of edge weights (default 1)
|
||||
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance)
|
||||
use_turn_restrictions | Boolean | Are turn instructions followed?
|
||||
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed?
|
||||
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
|
||||
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 `segment_function` will be called for all segments (default `false`)
|
||||
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that segment_function will be called for all segments
|
||||
|
||||
## way_function
|
||||
|
||||
Given an OpenStreetMap way, the `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 to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
|
||||
Given an OpenStreetMap way, the 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 to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
|
||||
|
||||
All other calculations stem from that, including the returned timings in driving directions, but also, less directly, it feeds into the actual routing decisions the engine will take (a way with a slow traversal speed, may be less favoured than a way with fast traversal speed, but it depends how long it is, and... what it connects to in the rest of the network graph)
|
||||
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `way_function`. Instead a `way_function` will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
|
||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the way_function. Instead a way_function will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
|
||||
|
||||
The following attributes can be set on the result in `way_function`:
|
||||
The following attributes can be set on the result in way_function:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------------------------------|----------|--------------------------------------------------------------------------
|
||||
forward_speed | Float | Speed on this way in km/h. Mandatory.
|
||||
forward_speed | Float | Speed on this way in km/h
|
||||
backward_speed | Float | " "
|
||||
forward_rate | Float | Routing weight, expressed as meters/*weight* (e.g. for a fastest-route weighting, you would want this to be meters/second, so set it to forward_speed/3.6)
|
||||
backward_rate | Float | " "
|
||||
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
|
||||
forward_mode | Enum | Mode of travel (e.g. car, ferry). Defined in include/extractor/travel_mode.hpp
|
||||
backward_mode | Enum | " "
|
||||
duration | Float | Alternative setter for duration of the whole way in both directions
|
||||
weight | Float | Alternative setter for weight of the whole way in both directions
|
||||
turn_lanes_forward | String | Directions for individual lanes (normalised OSM `turn:lanes` value)
|
||||
turn_lanes_forward | String | Directions for individual lanes (normalised OSM turn:lanes value)
|
||||
turn_lanes_backward | String | " "
|
||||
forward_restricted | Boolean | Is this a restricted access road? (e.g. private, or deliveries only; used to enable high turn penalty, so that way is only chosen for start/end of route)
|
||||
backward_restricted | Boolean | " "
|
||||
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if `false`, prevents snapping the start point to this way)
|
||||
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if false, prevents snapping the start point to this way)
|
||||
roundabout | Boolean | Is this part of a roundabout?
|
||||
circular | Boolean | Is this part of a non-roundabout circular junction?
|
||||
name | String | Name of the way
|
||||
@@ -70,7 +70,7 @@ ref | String | Road number
|
||||
pronunciation | String | Name pronunciation
|
||||
road_classification.motorway_class | Boolean | Guidance: way is a motorway
|
||||
road_classification.link_class | Boolean | Guidance: way is a slip/link road
|
||||
road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in `include/extractor/guidance/road_classification.hpp`
|
||||
road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in include/extractor/guidance/road_classification.hpp
|
||||
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
||||
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
||||
|
||||
@@ -87,16 +87,16 @@ Forks can be emitted between roads of similar priority category only. Obvious ch
|
||||
|
||||
## node_function
|
||||
|
||||
The following attributes can be set on the result in `node_function`:
|
||||
The following attributes can be set on the result in node_function:
|
||||
|
||||
Attribute | Type | Notes
|
||||
----------------|---------|-------------------------------------------------------
|
||||
barrier | Boolean | Is it an impassable barrier?
|
||||
traffic_lights | Boolean | Is it a traffic light (incurs delay in `turn_function`)?
|
||||
traffic_lights | Boolean | Is it a traffic light (incurs delay in turn_function)?
|
||||
|
||||
## segment_function
|
||||
|
||||
The following attributes can be read and set on the result in `segment_function`:
|
||||
The following attributes can be read and set on the result in segment_function:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
@@ -110,15 +110,15 @@ duration | Read/write | Float | Duration for this segment
|
||||
|
||||
## turn_function
|
||||
|
||||
The following attributes can be read and set on the result in `turn_function`:
|
||||
The following attributes can be read and set on the result in turn_function:
|
||||
|
||||
Attribute | Read/write? | Type | Notes
|
||||
-------------------|-------------|---------|------------------------------------------------------
|
||||
direction_modifier | Read | Enum | Geometry of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
||||
turn_type | Read | Enum | Priority of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
||||
direction_modifier | Read | Enum | Geometry of turn. Defined in include/extractor/guidance/turn_instruction.hpp
|
||||
turn_type | Read | Enum | Priority of turn. Defined in include/extractor/guidance/turn_instruction.hpp
|
||||
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `way_function`)
|
||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in `way_function`)
|
||||
angle | Read | Float | Angle of turn in degrees (`0-360`: `0`=u-turn, `180`=straight on)
|
||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in way_function)
|
||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in way_function)
|
||||
angle | Read | Float | Angle of turn in degrees (0-360: 0=u-turn, 180=straight on)
|
||||
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
||||
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
||||
|
||||
@@ -2,9 +2,38 @@
|
||||
Feature: Turn Penalties
|
||||
|
||||
Background:
|
||||
Given the profile "bicycle"
|
||||
Given the profile "turnbot"
|
||||
Given a grid size of 200 meters
|
||||
|
||||
Scenario: Bike - turns should incur a delay that depend on the angle
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
c d e
|
||||
b j f
|
||||
a s g
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| sj |
|
||||
| ja |
|
||||
| jb |
|
||||
| jc |
|
||||
| jd |
|
||||
| je |
|
||||
| jf |
|
||||
| jg |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time | distance |
|
||||
| s | a | sj,ja,ja | 63s +-1 | 483m +-1 |
|
||||
| s | b | sj,jb,jb | 50s +-1 | 400m +-1 |
|
||||
| s | c | sj,jc,jc | 54s +-1 | 483m +-1 |
|
||||
| s | d | sj,jd,jd | 40s +-1 | 400m +-1 |
|
||||
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
|
||||
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
|
||||
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
|
||||
|
||||
Scenario: Bicycle - Turn penalties on cyclability
|
||||
Given the profile file
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
@routing @approach
|
||||
Feature: Approach parameter
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
And a grid size of 10 meters
|
||||
|
||||
Scenario: Start End same approach, option unrestricted for Start and End
|
||||
Given 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 unrestricted | ab,bc |
|
||||
|
||||
Scenario: Start End same approach, option unrestricted for Start and curb for End
|
||||
Given 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,bc |
|
||||
|
||||
Scenario: Start End opposite approach, option unrestricted for Start and End
|
||||
Given the node map
|
||||
"""
|
||||
s
|
||||
a------b------c
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| s | e | unrestricted unrestricted | ab,bc |
|
||||
|
||||
Scenario: Start End opposite approach, option unrestricted for Start and curb for End
|
||||
Given the node map
|
||||
"""
|
||||
s
|
||||
a------b------c
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| s | e | unrestricted curb | ab,bc |
|
||||
|
||||
###############
|
||||
# Oneway Test #
|
||||
###############
|
||||
|
||||
|
||||
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and End
|
||||
Given the node map
|
||||
"""
|
||||
s e
|
||||
a------b------c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| ab | yes |
|
||||
| bc | yes |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| 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 node map
|
||||
"""
|
||||
s e
|
||||
a------b------c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| ab | yes |
|
||||
| bc | yes |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| s | e | unrestricted curb | ab,bc |
|
||||
|
||||
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and End
|
||||
Given the node map
|
||||
"""
|
||||
s
|
||||
a------b------c
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| ab | yes |
|
||||
| bc | yes |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| 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 node map
|
||||
"""
|
||||
s
|
||||
a------b------c
|
||||
e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| ab | yes |
|
||||
| bc | yes |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| s | e | unrestricted curb | ab,bc |
|
||||
|
||||
##############
|
||||
# UTurn Test #
|
||||
##############
|
||||
|
||||
Scenario: UTurn test, router can't found a route because uturn unauthorized on the segment selected
|
||||
Given the node map
|
||||
"""
|
||||
s e
|
||||
a------b------c
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction |
|
||||
| restriction | bc | bc | c | no_u_turn |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| s | e | unrestricted curb | |
|
||||
|
||||
|
||||
Scenario: UTurn test, router can found a route because he can use the roundabout
|
||||
Given the node map
|
||||
"""
|
||||
h
|
||||
s e / \
|
||||
a------b------c g
|
||||
\ /
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
| ab | |
|
||||
| bc | |
|
||||
| cfghc | roundabout |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction |
|
||||
| restriction | bc | bc | c | no_u_turn |
|
||||
|
||||
When I route I should get
|
||||
| from | to | approaches | route |
|
||||
| s | e | unrestricted curb | ab,bc,bc |
|
||||
@@ -1,741 +0,0 @@
|
||||
@routing @car @restrictions
|
||||
Feature: Car - Turn restrictions
|
||||
# Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction
|
||||
# Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
|
||||
|
||||
Background: Use car routing
|
||||
Given the profile "car"
|
||||
Given a grid size of 200 meters
|
||||
Given the origin -9.2972,10.3811
|
||||
# coordinate in Guinée, a country that observes GMT year round
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - ignores unrecognized restriction
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | only_right_turn @ (has_pygmies > 10 p) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p |
|
||||
\ |
|
||||
j
|
||||
| \
|
||||
s m
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| nj |
|
||||
| js |
|
||||
| pjm |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| 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 |
|
||||
| n | m | nj,pjm,pjm |
|
||||
| s | m | js,pjm,pjm |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - ignores except restriction
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | no |
|
||||
| jp | no |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional | except |
|
||||
| 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 | # |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | # |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| e | s | ej,js,js |
|
||||
| e | n | ej,nj,nj |
|
||||
| e | p | ej,jp,jp |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - Conditional restriction is on
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 10am utc, wed
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p |
|
||||
\ |
|
||||
j
|
||||
| \
|
||||
s m
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| jp | yes |
|
||||
| mj | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| 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 |
|
||||
| n | p | nj,js,js,jp,jp |
|
||||
| m | p | mj,jp,jp |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - only_right_turn
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | # |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| e | s | ej,js,js |
|
||||
| e | n | ej,nj,nj |
|
||||
| e | p | ej,jp,jp |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - Conditional restriction is on
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 10am utc, wed
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p j e
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| ej | yes |
|
||||
| jp | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| 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
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
p |
|
||||
\ |
|
||||
j
|
||||
| \
|
||||
s m
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| nj | no |
|
||||
| js | no |
|
||||
| jp | yes |
|
||||
| mj | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| 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 |
|
||||
| n | p | nj,js,js,jp,jp |
|
||||
| m | p | mj,jp,jp |
|
||||
|
||||
# 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=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"
|
||||
|
||||
# """
|
||||
# a h
|
||||
# d
|
||||
# b g
|
||||
# e
|
||||
# c f
|
||||
# """
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 38.9113 | -77.0091 |
|
||||
| b | 38.9108 | -77.0091 |
|
||||
| c | 38.9104 | -77.0091 |
|
||||
| d | 38.9110 | -77.0096 |
|
||||
| e | 38.9106 | -77.0086 |
|
||||
| f | 38.9105 | -77.0090 |
|
||||
| g | 38.9108 | -77.0090 |
|
||||
| h | 38.9113 | -77.0090 |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway | name |
|
||||
| ab | yes | cap south |
|
||||
| bc | yes | cap south |
|
||||
| fg | yes | cap north |
|
||||
| gh | yes | cap north |
|
||||
| db | no | florida nw |
|
||||
| bg | no | florida |
|
||||
| ge | no | florida ne |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ab | bg | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
|
||||
| restriction | fg | bg | g | no_left_turn @ (Mo-Fr 06:00-10:00) |
|
||||
| restriction | bg | bc | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | e | cap south,florida nw,florida nw,florida ne | depart,turn right,continue uturn,arrive |
|
||||
| f | d | cap north,florida,florida nw | depart,turn left,arrive |
|
||||
| e | c | florida ne,florida nw,cap south,cap south | depart,continue uturn,turn right,arrive |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - DC North capitol situation, one on two off
|
||||
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"
|
||||
|
||||
# """
|
||||
# a h
|
||||
# d
|
||||
# b g
|
||||
# e
|
||||
# c f
|
||||
# """
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 38.9113 | -77.0091 |
|
||||
| b | 38.9108 | -77.0091 |
|
||||
| c | 38.9104 | -77.0091 |
|
||||
| d | 38.9110 | -77.0096 |
|
||||
| e | 38.9106 | -77.0086 |
|
||||
| f | 38.9105 | -77.0090 |
|
||||
| g | 38.9108 | -77.0090 |
|
||||
| h | 38.9113 | -77.0090 |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway | name |
|
||||
| ab | yes | cap south |
|
||||
| bc | yes | cap south |
|
||||
| fg | yes | cap north |
|
||||
| gh | yes | cap north |
|
||||
| db | no | florida nw |
|
||||
| bg | no | florida |
|
||||
| ge | no | florida ne |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ab | bg | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
|
||||
| restriction | fg | bg | g | no_left_turn @ (Mo-Fr 06:00-10:00) |
|
||||
| restriction | bg | bc | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | e | cap south,florida,florida ne | depart,turn left,arrive |
|
||||
| f | d | cap north,florida ne,florida ne,florida nw | depart,turn sharp right,continue uturn,arrive |
|
||||
| e | c | florida ne,cap south,cap south | depart,turn left,arrive |
|
||||
|
||||
@only_turning @conditionals
|
||||
Scenario: Car - Restriction is always off when point not found in timezone files
|
||||
# same test as the following one, but given a different time zone file
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 9am UTC, 10am BST
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493802000"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493802000"
|
||||
|
||||
# """
|
||||
# a
|
||||
# e
|
||||
# b
|
||||
# d
|
||||
# c
|
||||
# """
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 51.5250 | -0.1166 |
|
||||
| b | 51.5243 | -0.1159 |
|
||||
| c | 51.5238 | -0.1152 |
|
||||
| d | 51.5241 | -0.1167 |
|
||||
| e | 51.5247 | -0.1153 |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | albic |
|
||||
| bc | albic |
|
||||
| db | dobe |
|
||||
| be | dobe |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ab | be | b | only_left_turn @ (Mo-Fr 07:00-11:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | c | albic,albic | depart,arrive |
|
||||
| a | e | albic,dobe,dobe | depart,turn left,arrive |
|
||||
|
||||
@only_turning @conditionals
|
||||
Scenario: Car - Somewhere in london, the UK, GMT timezone
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 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"
|
||||
|
||||
# """
|
||||
# a
|
||||
# e
|
||||
# b
|
||||
# d
|
||||
# c
|
||||
# """
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 51.5250 | -0.1166 |
|
||||
| b | 51.5243 | -0.1159 |
|
||||
| c | 51.5238 | -0.1152 |
|
||||
| d | 51.5241 | -0.1167 |
|
||||
| e | 51.5247 | -0.1153 |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | albic |
|
||||
| bc | albic |
|
||||
| db | dobe |
|
||||
| be | dobe |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ab | be | b | only_left_turn @ (Mo-Fr 07:00-11:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | c | albic,dobe,dobe,albic,albic | depart,turn left,continue uturn,turn left,arrive |
|
||||
| a | e | albic,dobe,dobe | depart,turn left,arrive |
|
||||
|
||||
@only_turning @conditionals
|
||||
Scenario: Car - Somewhere in London, the UK, GMT timezone
|
||||
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"
|
||||
|
||||
# """
|
||||
# a
|
||||
# e
|
||||
# b
|
||||
# d
|
||||
# c
|
||||
# """
|
||||
Given the node locations
|
||||
| node | lat | lon |
|
||||
| a | 51.5250 | -0.1166 |
|
||||
| b | 51.5243 | -0.1159 |
|
||||
| c | 51.5238 | -0.1152 |
|
||||
| d | 51.5241 | -0.1167 |
|
||||
| e | 51.5247 | -0.1153 |
|
||||
|
||||
And the ways
|
||||
| nodes | name |
|
||||
| ab | albic |
|
||||
| bc | albic |
|
||||
| db | dobe |
|
||||
| be | dobe |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ab | be | b | only_left_turn @ (Mo-Fr 07:00-11:00) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| a | c | albic,dobe,dobe,albic,albic | depart,turn left,continue uturn,turn left,arrive |
|
||||
| a | e | albic,dobe,dobe | depart,turn left,arrive |
|
||||
@@ -60,8 +60,8 @@ Feature: Basic Routing
|
||||
| bc | | 101 |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | summary |
|
||||
| a,c | road,, | road, 101 |
|
||||
| waypoints | route | summary |
|
||||
| a,c | road, | road, 101 |
|
||||
|
||||
Scenario: Only Refs
|
||||
Given the node map
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
@routing @via
|
||||
Feature: Via points
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
|
||||
# See issue #1896
|
||||
Scenario: Via point at a dead end with barrier
|
||||
Given the profile "car"
|
||||
Given the node map
|
||||
"""
|
||||
a b c
|
||||
1
|
||||
d
|
||||
|
||||
|
||||
f e
|
||||
"""
|
||||
|
||||
And the nodes
|
||||
| node | barrier |
|
||||
| d | bollard |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abc |
|
||||
| bd |
|
||||
| afed |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,1,c | abc,bd,bd,bd,bd,abc,abc |
|
||||
| c,1,a | abc,bd,bd,bd,bd,abc,abc |
|
||||
@@ -769,6 +769,32 @@ Feature: Basic Roundabout
|
||||
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
|
||||
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |
|
||||
|
||||
@4030 @4075
|
||||
Scenario: Service roundabout with service exits
|
||||
# Counting of service exits must be adjusted in #4075
|
||||
Given the node map
|
||||
"""
|
||||
e
|
||||
f a d
|
||||
g b1c
|
||||
h
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | junction |
|
||||
| abcda | service | roundabout |
|
||||
| de | service | |
|
||||
| af | service | |
|
||||
| bg | tertiary | |
|
||||
| bh | service | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| 1 | e | abcda,de,de | depart,roundabout-exit-1,arrive |
|
||||
| 1 | f | abcda,af,af | depart,roundabout-exit-1,arrive |
|
||||
| 1 | g | abcda,bg,bg | depart,roundabout-exit-1,arrive |
|
||||
| 1 | h | abcda,bh,bh | depart,roundabout-exit-1,arrive |
|
||||
|
||||
Scenario: CCW and CW roundabouts with overlaps
|
||||
Given the node map
|
||||
"""
|
||||
@@ -794,55 +820,3 @@ Feature: Basic Roundabout
|
||||
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
|
||||
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |
|
||||
|
||||
@4030 @4075
|
||||
Scenario: Service roundabout with service exits
|
||||
Given the node map
|
||||
"""
|
||||
g a d f
|
||||
h b1c e
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | highway | junction |
|
||||
| abcda | service | roundabout |
|
||||
| ce | service | |
|
||||
| df | service | |
|
||||
| ag | tertiary | |
|
||||
| bh | service | |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns |
|
||||
| 1 | e | abcda,ce,ce | depart,roundabout-exit-1,arrive |
|
||||
| 1 | f | abcda,df,df | depart,roundabout-exit-2,arrive |
|
||||
| 1 | g | abcda,ag,ag | depart,roundabout-exit-3,arrive |
|
||||
| 1 | h | abcda,bh,bh | depart,roundabout-exit-4,arrive |
|
||||
|
||||
Scenario: Collapsing a sliproad step after roundabouts
|
||||
Given the node map
|
||||
"""
|
||||
a r j
|
||||
╱ ╲ ╱ ╲ │
|
||||
e——b——1——d———s u——f——g—h——l
|
||||
╲ ╱ ╲ ╱ `i
|
||||
c t │
|
||||
│ │ │
|
||||
m v k
|
||||
"""
|
||||
|
||||
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 | | yes | sliproad |
|
||||
| jhik | tertiary | | | crossroad |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns | distance |
|
||||
| e | k | ebds,ebds,ds,ufghl,jhik,jhik | depart,rotary-exit-1,rotary-exit-1,rstur-exit-2,turn right,arrive | 189.1m |
|
||||
| 1 | k | ebds,ds,ufghl,jhik,jhik | depart,rotary-exit-1,rstur-exit-2,turn right,arrive | 159.1m |
|
||||
|
||||
@@ -134,7 +134,7 @@ Feature: Turn Lane Guidance
|
||||
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,left;uturn:false straight;right:true, | a,b,c |
|
||||
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,left;uturn:false straight;right:true, | a,b,d |
|
||||
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,left;uturn:true straight;right:false, | a,b,e |
|
||||
| 1 | a | 90,2 270,2 | in,in,in | depart,continue uturn,arrive | ,left;uturn:true straight;right:false, | _,b,a |
|
||||
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,left;uturn:true straight;right:false, | _,b,a |
|
||||
|
||||
|
||||
#this next test requires decision on how to announce lanes for going straight if there is no turn
|
||||
@@ -629,7 +629,7 @@ Feature: Turn Lane Guidance
|
||||
When I route I should get
|
||||
| waypoints | route | turns | lanes |
|
||||
| a,f | road,left,left | depart,turn left,arrive | ,left:true left:true left:true straight:false straight:false, |
|
||||
| a,e | road,road,road | depart,continue uturn,arrive | ,left:true left:false left:false straight:false straight:false, |
|
||||
| a,e | road,road,road | depart,turn uturn,arrive | ,left:true left:false left:false straight:false straight:false, |
|
||||
| a,g | road,straight,straight | depart,new name straight,arrive | ,left:false left:false left:false straight:true straight:true, |
|
||||
|
||||
@todo @roundabout
|
||||
|
||||
@@ -1260,62 +1260,3 @@ Feature: Simple Turns
|
||||
| waypoints | route | turns |
|
||||
| a,d | Goethe,Fried,Fried | depart,continue left,arrive |
|
||||
| a,g | Goethe,Fried,Fried | depart,turn right,arrive |
|
||||
|
||||
# Conflicting roads (https://www.openstreetmap.org/export#map=19/37.57805/-77.46049)
|
||||
Scenario: Turning at forklike structure
|
||||
Given the node map
|
||||
"""
|
||||
c d
|
||||
- - - b - - - a
|
||||
-
|
||||
e
|
||||
"""
|
||||
And the ways
|
||||
| nodes | name | oneway | highway |
|
||||
| abc | foo | no | residential |
|
||||
| bd | bar | yes | residential |
|
||||
| eb | some | yes | tertiary_link |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | foo,bar,bar | depart,turn slight right,arrive |
|
||||
|
||||
Scenario: UTurn onto ramp
|
||||
Given the node map
|
||||
"""
|
||||
a - - - b - c
|
||||
.|
|
||||
_________________ de
|
||||
h-g-----------------------f
|
||||
"""
|
||||
And the ways
|
||||
| nodes | name | ref | oneway | highway |
|
||||
| abc | Road | | yes | primary |
|
||||
| ce | other | | yes | primary |
|
||||
| cdg | | | yes | motorway_link |
|
||||
| fgh | | C 42 | yes | motorway |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | ref | turns |
|
||||
| a,h | Road,,, | ,,C 42,C 42 | depart,on ramp right,merge slight left,arrive |
|
||||
|
||||
Scenario: UTurn onto ramp (same ref)
|
||||
Given the node map
|
||||
"""
|
||||
a - - - b - c
|
||||
.|
|
||||
_________________ de
|
||||
h-g-----------------------f
|
||||
"""
|
||||
And the ways
|
||||
| nodes | name | ref | oneway | highway |
|
||||
| abc | Road | C 42 | yes | primary |
|
||||
| ce | other | | yes | primary |
|
||||
| cdg | | | yes | motorway_link |
|
||||
| fgh | | C 42 | yes | motorway |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | ref | turns |
|
||||
| a,h | Road,,, | C 42,,C 42,C 42 | depart,on ramp right,merge slight left,arrive |
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# Broken see issue #4065
|
||||
@contract @options @edge-weight-updates-over-factor @todo
|
||||
@contract @options @edge-weight-updates-over-factor
|
||||
Feature: osrm-contract command line option: edge-weight-updates-over-factor
|
||||
|
||||
Background: Log edge weight updates over given factor
|
||||
|
||||
@@ -32,7 +32,9 @@ Feature: Raster - weights
|
||||
|
||||
Scenario: Weighting not based on raster sources
|
||||
Given the profile "testbot"
|
||||
When I route I should get
|
||||
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||
And I run "osrm-contract {processed_file}"
|
||||
And I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 36 km/h |
|
||||
| a | c | ab,bc,bc | 36 km/h |
|
||||
@@ -42,7 +44,10 @@ Feature: Raster - weights
|
||||
|
||||
Scenario: Weighting based on raster sources
|
||||
Given the profile "rasterbot"
|
||||
When I route I should get
|
||||
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||
Then stdout should contain "evaluating segment"
|
||||
And I run "osrm-contract {processed_file}"
|
||||
And I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 8 km/h |
|
||||
| b | a | ab,ab | 22 km/h |
|
||||
@@ -58,7 +63,10 @@ Feature: Raster - weights
|
||||
|
||||
Scenario: Weighting based on raster sources
|
||||
Given the profile "rasterbotinterp"
|
||||
When I route I should get
|
||||
When I run "osrm-extract {osm_file} -p {profile_file}"
|
||||
Then stdout should contain "evaluating segment"
|
||||
And I run "osrm-contract {processed_file}"
|
||||
And I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 8 km/h |
|
||||
| a | c | ad,dc,dc | 15 km/h |
|
||||
|
||||
@@ -38,7 +38,7 @@ module.exports = function () {
|
||||
callback();
|
||||
});
|
||||
|
||||
this.Given(/^the origin ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)$/, (lon, lat, callback) => {
|
||||
this.Given(/^the origin ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)$/, (lat, lon, callback) => {
|
||||
this.setOrigin([parseFloat(lon), parseFloat(lat)]);
|
||||
callback();
|
||||
});
|
||||
@@ -67,7 +67,7 @@ module.exports = function () {
|
||||
if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name));
|
||||
this.addOSMNode(name, lonLat[0], lonLat[1], null);
|
||||
} else if (name.match(/[0-9]/) ) {
|
||||
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s', name));
|
||||
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name);
|
||||
this.addLocation(name, lonLat[0], lonLat[1], null);
|
||||
}
|
||||
cb();
|
||||
@@ -89,7 +89,7 @@ module.exports = function () {
|
||||
|
||||
let addNodeLocations = (row, cb) => {
|
||||
let name = row.node;
|
||||
if (this.findNodeByName(name)) throw new Error(util.format('*** duplicate node %s', name));
|
||||
if (this.findNodeByName(name)) throw new Error(util.format('*** duplicate node %s'), name);
|
||||
|
||||
if (name.match(/[a-z]/)) {
|
||||
let id = row.id && parseInt(row.id);
|
||||
@@ -194,19 +194,19 @@ module.exports = function () {
|
||||
isColonSeparated = key.match(/^(.*):(.*)/);
|
||||
if (isNode) {
|
||||
row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => {
|
||||
if (nodeName.length !== 1) throw new Error(util.format('*** invalid relation node member "%s"', nodeName));
|
||||
if (nodeName.length !== 1) throw new Error(util.format('*** invalid relation node member "%s"'), nodeName);
|
||||
let node = this.findNodeByName(nodeName);
|
||||
if (!node) throw new Error(util.format('*** unknown relation node member "%s"', nodeName));
|
||||
if (!node) throw new Error(util.format('*** unknown relation node member "%s"'), nodeName);
|
||||
relation.addMember('node', node.id, isNode[1]);
|
||||
});
|
||||
} else if (isWay) {
|
||||
row[key].split(',').map(function(v) { return v.trim(); }).forEach((wayName) => {
|
||||
let way = this.findWayByName(wayName);
|
||||
if (!way) throw new Error(util.format('*** unknown relation way member "%s"', wayName));
|
||||
if (!way) throw new Error(util.format('*** unknown relation way member "%s"'), wayName);
|
||||
relation.addMember('way', way.id, isWay[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]));
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ module.exports = function () {
|
||||
for (var i=0; i<row.trace.length; i++) {
|
||||
var n = row.trace[i],
|
||||
node = this.findNodeByName(n);
|
||||
if (!node) throw new Error(util.format('*** unknown waypoint node "%s"', n));
|
||||
if (!node) throw new Error(util.format('*** unknown waypoint node "%s"'), n);
|
||||
trace.push(node);
|
||||
}
|
||||
if (row.timestamps) {
|
||||
|
||||
@@ -6,10 +6,10 @@ module.exports = function () {
|
||||
if (e) return callback(e);
|
||||
var testRow = (row, ri, cb) => {
|
||||
var inNode = this.findNodeByName(row.in);
|
||||
if (!inNode) throw new Error(util.format('*** unknown in-node "%s"', row.in));
|
||||
if (!inNode) throw new Error(util.format('*** unknown in-node "%s"'), row.in);
|
||||
|
||||
var outNode = this.findNodeByName(row.out);
|
||||
if (!outNode) throw new Error(util.format('*** unknown out-node "%s"', row.out));
|
||||
if (!outNode) throw new Error(util.format('*** unknown out-node "%s"'), row.out);
|
||||
|
||||
this.requestNearest(inNode, this.queryParams, (err, response) => {
|
||||
if (err) return cb(err);
|
||||
|
||||
@@ -121,7 +121,7 @@ module.exports = function () {
|
||||
|
||||
r.which = dir;
|
||||
|
||||
this.requestRoute((dir === 'forw' ? [a, b] : [b, a]), [], [], this.queryParams, (err, res, body) => {
|
||||
this.requestRoute((dir === 'forw' ? [a, b] : [b, a]), [], this.queryParams, (err, res, body) => {
|
||||
if (err) return callback(err);
|
||||
|
||||
r.query = this.query;
|
||||
|
||||
@@ -243,8 +243,8 @@ module.exports = function () {
|
||||
processedCacheFile: this.processedCacheFile, environment: this.environment};
|
||||
let queue = d3.queue(1);
|
||||
queue.defer(this.extractData.bind(this), p);
|
||||
queue.defer(this.partitionData.bind(this), p);
|
||||
queue.defer(this.contractData.bind(this), p);
|
||||
queue.defer(this.partitionData.bind(this), p);
|
||||
queue.defer(this.customizeData.bind(this), p);
|
||||
queue.awaitAll(callback);
|
||||
};
|
||||
|
||||
@@ -39,8 +39,7 @@ module.exports = function () {
|
||||
this.WAY_SPACING = 100;
|
||||
this.DEFAULT_GRID_SIZE = 100; // meters
|
||||
// get algorithm name from the command line profile argument
|
||||
this.ROUTING_ALGORITHM = process.argv[process.argv.indexOf('-p') + 1].match('mld') ? 'MLD' : 'CH';
|
||||
this.TIMEZONE_NAMES = this.PLATFORM_WINDOWS ? 'win' : 'iana';
|
||||
this.ROUTING_ALGORITHM = process.argv[process.argv.indexOf('-p') + 1] === 'mld' ? 'MLD' : 'CH';
|
||||
|
||||
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
|
||||
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
|
||||
|
||||
@@ -46,9 +46,8 @@ module.exports = function () {
|
||||
return waypoints.map(w => [w.lon, w.lat].map(ensureDecimal).join(','));
|
||||
};
|
||||
|
||||
this.requestRoute = (waypoints, bearings, approaches, userParams, callback) => {
|
||||
this.requestRoute = (waypoints, bearings, userParams, callback) => {
|
||||
if (bearings.length && bearings.length !== waypoints.length) throw new Error('*** number of bearings does not equal the number of waypoints');
|
||||
if (approaches.length && approaches.length !== waypoints.length) throw new Error('*** number of approaches does not equal the number of waypoints');
|
||||
|
||||
var defaults = {
|
||||
output: 'json',
|
||||
@@ -68,9 +67,6 @@ module.exports = function () {
|
||||
}).join(';');
|
||||
}
|
||||
|
||||
if (approaches.length) {
|
||||
params.approaches = approaches.join(';');
|
||||
}
|
||||
return this.requestPath('route', params, callback);
|
||||
};
|
||||
|
||||
@@ -167,10 +163,6 @@ module.exports = function () {
|
||||
('out' in s.intersections[0] ? s.intersections[0].bearings[s.intersections[0].out] : 0));
|
||||
};
|
||||
|
||||
this.approachList = (instructions) => {
|
||||
return this.extractInstructionList(instructions, s => s.approaches || '');
|
||||
};
|
||||
|
||||
this.annotationList = (instructions) => {
|
||||
if (!('annotation' in instructions.legs[0]))
|
||||
return '';
|
||||
|
||||
@@ -15,8 +15,7 @@ module.exports = function () {
|
||||
'{profile_file}': this.profileFile,
|
||||
'{rastersource_file}': this.rasterCacheFile,
|
||||
'{speeds_file}': this.speedsCacheFile,
|
||||
'{penalties_file}': this.penaltiesCacheFile,
|
||||
'{timezone_names}': this.TIMEZONE_NAMES
|
||||
'{penalties_file}': this.penaltiesCacheFile
|
||||
};
|
||||
|
||||
for (let k in table) {
|
||||
|
||||
@@ -35,7 +35,7 @@ module.exports = function () {
|
||||
if (err) return cb(err);
|
||||
if (body && body.length) {
|
||||
let destinations, pronunciations, instructions, refs, bearings, turns, modes, times,
|
||||
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
|
||||
distances, summary, intersections, lanes, locations, annotation, weight_name, weights;
|
||||
|
||||
let json = JSON.parse(body);
|
||||
|
||||
@@ -60,7 +60,6 @@ module.exports = function () {
|
||||
annotation = this.annotationList(json.routes[0]);
|
||||
weight_name = this.weightName(json.routes[0]);
|
||||
weights = this.weightList(json.routes[0]);
|
||||
approaches = this.approachList(json.routes[0]);
|
||||
}
|
||||
|
||||
if (headers.has('status')) {
|
||||
@@ -147,10 +146,7 @@ module.exports = function () {
|
||||
if (headers.has('locations')){
|
||||
got.locations = (locations || '').trim();
|
||||
}
|
||||
/*
|
||||
if (headers.has('approaches')){
|
||||
got.approaches = (approaches || '').trim();
|
||||
}*/
|
||||
|
||||
// if header matches 'a:*', parse out the values for *
|
||||
// and return in that header
|
||||
headers.forEach((k) => {
|
||||
@@ -180,7 +176,6 @@ module.exports = function () {
|
||||
putValue('weight_name', weight_name);
|
||||
putValue('weights', weights);
|
||||
putValue('weight', weight);
|
||||
putValue('approach', approaches);
|
||||
|
||||
for (var key in row) {
|
||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||
@@ -215,31 +210,25 @@ module.exports = function () {
|
||||
|
||||
var params = this.overwriteParams(defaultParams, userParams),
|
||||
waypoints = [],
|
||||
bearings = [],
|
||||
approaches = [];
|
||||
bearings = [];
|
||||
|
||||
if (row.bearings) {
|
||||
got.bearings = row.bearings;
|
||||
bearings = row.bearings.split(' ').filter(b => !!b);
|
||||
}
|
||||
|
||||
if (row.approaches) {
|
||||
got.approaches = row.approaches;
|
||||
approaches = row.approaches.split(' ').filter(b => !!b);
|
||||
}
|
||||
|
||||
if (row.from && row.to) {
|
||||
var fromNode = this.findNodeByName(row.from);
|
||||
if (!fromNode) return cb(new Error(util.format('*** unknown from-node "%s"', row.from)));
|
||||
if (!fromNode) return cb(new Error(util.format('*** unknown from-node "%s"'), row.from));
|
||||
waypoints.push(fromNode);
|
||||
|
||||
var toNode = this.findNodeByName(row.to);
|
||||
if (!toNode) return cb(new Error(util.format('*** unknown to-node "%s"', row.to)));
|
||||
if (!toNode) return cb(new Error(util.format('*** unknown to-node "%s"'), row.to));
|
||||
waypoints.push(toNode);
|
||||
|
||||
got.from = row.from;
|
||||
got.to = row.to;
|
||||
this.requestRoute(waypoints, bearings, approaches, params, afterRequest);
|
||||
this.requestRoute(waypoints, bearings, params, afterRequest);
|
||||
} else if (row.waypoints) {
|
||||
row.waypoints.split(',').forEach((n) => {
|
||||
var node = this.findNodeByName(n.trim());
|
||||
@@ -247,7 +236,7 @@ module.exports = function () {
|
||||
waypoints.push(node);
|
||||
});
|
||||
got.waypoints = row.waypoints;
|
||||
this.requestRoute(waypoints, bearings, approaches, params, afterRequest);
|
||||
this.requestRoute(waypoints, bearings, params, afterRequest);
|
||||
} else {
|
||||
return cb(new Error('*** no waypoints'));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ Feature: Testbot - Handle ferry routes
|
||||
i j k l
|
||||
m n o p
|
||||
q r s t
|
||||
u v w x
|
||||
"""
|
||||
|
||||
And the ways
|
||||
@@ -27,14 +26,11 @@ Feature: Testbot - Handle ferry routes
|
||||
| op | primary | | |
|
||||
| qr | primary | | |
|
||||
| st | primary | | |
|
||||
| uv | primary | | |
|
||||
| wx | primary | | |
|
||||
| bc | | ferry | 0:01 |
|
||||
| fg | | ferry | 0:10 |
|
||||
| jk | | ferry | 1:00 |
|
||||
| no | | ferry | 24:00 |
|
||||
| rs | | ferry | 96:00 |
|
||||
| vw | | ferry | P5D |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time |
|
||||
@@ -43,7 +39,6 @@ Feature: Testbot - Handle ferry routes
|
||||
| j | k | jk,jk | 3600s +-1 |
|
||||
| n | o | no,no | 86400s +-1 |
|
||||
| r | s | rs,rs | 345600s +-1 |
|
||||
| v | w | vw,vw | 419430s +-1|
|
||||
|
||||
@todo
|
||||
Scenario: Testbot - Week long ferry routes
|
||||
|
||||
@@ -2,22 +2,15 @@
|
||||
Feature: Traffic - speeds
|
||||
|
||||
Background: Use specific speeds
|
||||
# __ a
|
||||
# / /
|
||||
#c----b / g
|
||||
# \ |\/
|
||||
# \ e/\_.f
|
||||
# \ | /
|
||||
# d./
|
||||
Given the node locations
|
||||
| node | lat | lon | id |
|
||||
| a | 0.1 | 0.1 | 1 |
|
||||
| b | 0.05 | 0.1 | 2 |
|
||||
| c | 0.0 | 0.1 | 3 |
|
||||
| d | 0.05 | 0.03 | 4 |
|
||||
| e | 0.05 | 0.066 | 5 |
|
||||
| f | 0.075 | 0.066 | 6 |
|
||||
| g | 0.075 | 0.1 | 7 |
|
||||
| node | lat | lon |
|
||||
| a | 0.1 | 0.1 |
|
||||
| b | 0.05 | 0.1 |
|
||||
| c | 0.0 | 0.1 |
|
||||
| d | 0.05 | 0.03 |
|
||||
| e | 0.05 | 0.066 |
|
||||
| f | 0.075 | 0.066 |
|
||||
| g | 0.075 | 0.1 |
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ab | primary |
|
||||
@@ -89,7 +82,7 @@ Feature: Traffic - speeds
|
||||
api_version = 1
|
||||
properties.traffic_signal_penalty = 0
|
||||
properties.u_turn_penalty = 0
|
||||
properties.weight_precision = 2
|
||||
properties.weight_precision = 3
|
||||
"""
|
||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
@@ -106,15 +99,15 @@ Feature: Traffic - speeds
|
||||
| annotations | datasources |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed | weights | a:datasources |
|
||||
| a | b | ab,ab | 1 km/h | 20020.73,0 | 1:0 |
|
||||
| a | c | ab,bc,bc | 2 km/h | 20020.73,741.51,0 | 1:1:0 |
|
||||
| b | c | bc,bc | 27 km/h | 741.51,0 | 1:0 |
|
||||
| a | d | ab,eb,de,de | 2 km/h | 20020.73,378.17,400.41,0 | 1:0:0 |
|
||||
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
|
||||
| g | b | ab,ab | 1 km/h | 10010.37,0 | 1:0 |
|
||||
| a | g | ab,ab | 1 km/h | 10010.36,0 | 1 |
|
||||
| g | a | ab,ab | 1 km/h | 10010.36,0 | 1:1 |
|
||||
| from | to | route | speed | weights | a:datasources |
|
||||
| a | b | ab,ab | 1 km/h | 20020.735,0 | 1:0 |
|
||||
| a | c | ab,bc,bc | 2 km/h | 20020.735,741.509,0 | 1:1:0 |
|
||||
| b | c | bc,bc | 27 km/h | 741.509,0 | 1:0 |
|
||||
| a | d | ab,eb,de,de | 2 km/h | 20020.735,378.169,400.415,0 | 1:0:0 |
|
||||
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
|
||||
| g | b | ab,ab | 1 km/h | 10010.365,0 | 1:0 |
|
||||
| a | g | ab,ab | 1 km/h | 10010.37,0 | 1 |
|
||||
| g | a | ab,ab | 1 km/h | 10010.37,0 | 1:1 |
|
||||
|
||||
|
||||
Scenario: Speeds that isolate a single node (a)
|
||||
@@ -168,4 +161,3 @@ 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
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
@routing @speed @traffic
|
||||
Feature: Traffic - speeds edge cases
|
||||
Scenario: Weighting based on speed file weights that cause segment weight overflows
|
||||
Given the node map
|
||||
"""
|
||||
a-----b
|
||||
"""
|
||||
And the ways
|
||||
| nodes | highway |
|
||||
| ab | primary |
|
||||
And the profile file "testbot" extended with
|
||||
"""
|
||||
api_version = 1
|
||||
properties.traffic_signal_penalty = 0
|
||||
properties.u_turn_penalty = 0
|
||||
properties.weight_precision = 2
|
||||
"""
|
||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
"""
|
||||
1,2,1,0.001
|
||||
2,1,1,0.001
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed | weights | a:datasources |
|
||||
| a | b | ab,ab | 1 km/h | 41943.02,0 | 1 |
|
||||
@@ -1,36 +0,0 @@
|
||||
@routing @testbot @turn_penalty
|
||||
Feature: Turn Penalties
|
||||
|
||||
Background:
|
||||
Given the profile "turnbot"
|
||||
Given a grid size of 200 meters
|
||||
|
||||
|
||||
Scenario: Turns should incur a delay that depend on the angle
|
||||
Given the node map
|
||||
"""
|
||||
c d e
|
||||
b j f
|
||||
a s g
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| sj |
|
||||
| ja |
|
||||
| jb |
|
||||
| jc |
|
||||
| jd |
|
||||
| je |
|
||||
| jf |
|
||||
| jg |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | time | distance |
|
||||
| s | a | sj,ja,ja | 63s +-1 | 483m +-1 |
|
||||
| s | b | sj,jb,jb | 50s +-1 | 400m +-1 |
|
||||
| s | c | sj,jc,jc | 54s +-1 | 483m +-1 |
|
||||
| s | d | sj,jd,jd | 40s +-1 | 400m +-1 |
|
||||
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
|
||||
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
|
||||
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
|
||||
@@ -224,6 +224,34 @@ Feature: Via points
|
||||
| a,d,c | abc,bd,bd,bd,abc,abc |
|
||||
| c,d,a | abc,bd,bd,bd,abc,abc |
|
||||
|
||||
# See issue #1896
|
||||
Scenario: Via point at a dead end with barrier
|
||||
Given the profile "car"
|
||||
Given the node map
|
||||
"""
|
||||
a b c
|
||||
1
|
||||
d
|
||||
|
||||
|
||||
f e
|
||||
"""
|
||||
|
||||
And the nodes
|
||||
| node | barrier |
|
||||
| d | bollard |
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| abc |
|
||||
| bd |
|
||||
| afed |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route |
|
||||
| a,1,c | abc,bd,bd,bd,bd,abc,abc |
|
||||
| c,1,a | abc,bd,bd,bd,bd,abc,abc |
|
||||
|
||||
Scenario: Via points on ring on the same oneway, forces one of the vertices to be top node
|
||||
Given the node map
|
||||
"""
|
||||
@@ -321,9 +349,9 @@ Feature: Via points
|
||||
| ab |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | bearings | route | turns |
|
||||
| 1,a | 90,2 270,2 | ab,ab,ab | depart,continue uturn,arrive |
|
||||
| 1,b | 270,2 90,2 | ab,ab,ab | depart,continue uturn,arrive |
|
||||
| waypoints | bearings | route | turns |
|
||||
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
|
||||
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
|
||||
|
||||
Scenario: Continue Straight in presence of Bearings
|
||||
Given the node map
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
Feature: Check zero speed updates
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Matching on restricted way, single segment
|
||||
Given the query options
|
||||
| geometries | geojson |
|
||||
@@ -111,8 +108,8 @@ Feature: Check zero speed updates
|
||||
"""
|
||||
|
||||
When I route I should get
|
||||
| from | to | bearings | code |
|
||||
| 1 | 2 | 270 270 | NoSegment |
|
||||
| from | to | bearings | code |
|
||||
| 1 | 2 | 270 270 | NoRoute |
|
||||
|
||||
|
||||
Scenario: Via routing on restricted oneway
|
||||
|
||||
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "contractor/contractor_config.hpp"
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/edge_based_node_segment.hpp"
|
||||
#include "extractor/edge_based_node.hpp"
|
||||
#include "util/deallocating_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -66,8 +66,13 @@ class Contractor
|
||||
std::vector<bool> &is_core_node,
|
||||
std::vector<float> &inout_node_levels) const;
|
||||
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
|
||||
void WriteNodeLevels(std::vector<float> &&node_levels) const;
|
||||
void ReadNodeLevels(std::vector<float> &contraction_order) const;
|
||||
void WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||
util::DeallocatingVector<QueryEdge> contracted_edge_list);
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<extractor::EdgeBasedEdge> &edges,
|
||||
std::vector<extractor::EdgeBasedNode> &nodes) const;
|
||||
|
||||
private:
|
||||
ContractorConfig config;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef OSRM_CONTRACTOR_CONTRACTOR_HEAP_HPP_
|
||||
#define OSRM_CONTRACTOR_CONTRACTOR_HEAP_HPP_
|
||||
|
||||
#include "util/query_heap.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/xor_fast_hash_storage.hpp"
|
||||
|
||||
@@ -18,11 +18,11 @@ struct ContractorHeapData
|
||||
bool target = false;
|
||||
};
|
||||
|
||||
using ContractorHeap = util::QueryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
ContractorHeapData,
|
||||
util::XORFastHashStorage<NodeID, NodeID>>;
|
||||
using ContractorHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
ContractorHeapData,
|
||||
util::XORFastHashStorage<NodeID, NodeID>>;
|
||||
|
||||
} // namespace contractor
|
||||
} // namespace osrm
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "util/serialization.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/serialization.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -44,24 +43,6 @@ writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGr
|
||||
writer.WriteOne(checksum);
|
||||
util::serialization::write(writer, graph);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
#include "util/query_heap.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
|
||||
#include <tbb/enumerable_thread_specific.h>
|
||||
|
||||
@@ -24,7 +24,7 @@ class CellCustomizer
|
||||
|
||||
public:
|
||||
using Heap =
|
||||
util::QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
|
||||
util::BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
|
||||
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
|
||||
|
||||
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
||||
|
||||
@@ -50,19 +50,14 @@ class BaseAPI
|
||||
{
|
||||
if (parameters.generate_hints)
|
||||
{
|
||||
// TODO: check forward/reverse
|
||||
return json::makeWaypoint(
|
||||
phantom.location,
|
||||
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string(),
|
||||
Hint{phantom, facade.GetCheckSum()});
|
||||
return json::makeWaypoint(phantom.location,
|
||||
facade.GetNameForID(phantom.name_id).to_string(),
|
||||
Hint{phantom, facade.GetCheckSum()});
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: check forward/reverse
|
||||
return json::makeWaypoint(
|
||||
phantom.location,
|
||||
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))
|
||||
.to_string());
|
||||
return json::makeWaypoint(phantom.location,
|
||||
facade.GetNameForID(phantom.name_id).to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ENGINE_API_BASE_PARAMETERS_HPP
|
||||
#define ENGINE_API_BASE_PARAMETERS_HPP
|
||||
|
||||
#include "engine/approach.hpp"
|
||||
#include "engine/bearing.hpp"
|
||||
#include "engine/hint.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
@@ -56,7 +55,6 @@ namespace api
|
||||
* optional per coordinate
|
||||
* - bearings: limits the search for segments in the road network to given bearing(s) in degree
|
||||
* towards true north in clockwise direction, optional per coordinate
|
||||
* - approaches: force the phantom node to start towards the node with the road country side.
|
||||
*
|
||||
* \see OSRM, Coordinate, Hint, Bearing, RouteParame, RouteParameters, TableParameters,
|
||||
* NearestParameters, TripParameters, MatchParameters and TileParameters
|
||||
@@ -67,7 +65,6 @@ struct BaseParameters
|
||||
std::vector<boost::optional<Hint>> hints;
|
||||
std::vector<boost::optional<double>> radiuses;
|
||||
std::vector<boost::optional<Bearing>> bearings;
|
||||
std::vector<boost::optional<Approach>> approaches;
|
||||
|
||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||
bool generate_hints = true;
|
||||
@@ -76,10 +73,9 @@ struct BaseParameters
|
||||
const std::vector<boost::optional<Hint>> hints_ = {},
|
||||
std::vector<boost::optional<double>> radiuses_ = {},
|
||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||
bool generate_hints_ = true)
|
||||
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
||||
approaches(approaches_), generate_hints(generate_hints_)
|
||||
generate_hints(generate_hints_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -89,7 +85,6 @@ struct BaseParameters
|
||||
return (hints.empty() || hints.size() == coordinates.size()) &&
|
||||
(bearings.empty() || bearings.size() == coordinates.size()) &&
|
||||
(radiuses.empty() || radiuses.size() == coordinates.size()) &&
|
||||
(approaches.empty() || approaches.size() == coordinates.size()) &&
|
||||
std::all_of(bearings.begin(),
|
||||
bearings.end(),
|
||||
[](const boost::optional<Bearing> bearing_and_range) {
|
||||
|
||||
@@ -41,27 +41,26 @@ class RouteAPI : public BaseAPI
|
||||
{
|
||||
}
|
||||
|
||||
void MakeResponse(const InternalManyRoutesResult &raw_routes,
|
||||
util::json::Object &response) const
|
||||
void MakeResponse(const InternalRouteResult &raw_route, util::json::Object &response) const
|
||||
{
|
||||
BOOST_ASSERT(!raw_routes.routes.empty());
|
||||
|
||||
util::json::Array jsRoutes;
|
||||
|
||||
for (const auto &route : raw_routes.routes)
|
||||
auto number_of_routes = raw_route.has_alternative() ? 2UL : 1UL;
|
||||
util::json::Array routes;
|
||||
routes.values.resize(number_of_routes);
|
||||
routes.values[0] = MakeRoute(raw_route.segment_end_coordinates,
|
||||
raw_route.unpacked_path_segments,
|
||||
raw_route.source_traversed_in_reverse,
|
||||
raw_route.target_traversed_in_reverse);
|
||||
if (raw_route.has_alternative())
|
||||
{
|
||||
if (!route.is_valid())
|
||||
continue;
|
||||
|
||||
jsRoutes.values.push_back(MakeRoute(route.segment_end_coordinates,
|
||||
route.unpacked_path_segments,
|
||||
route.source_traversed_in_reverse,
|
||||
route.target_traversed_in_reverse));
|
||||
std::vector<std::vector<PathData>> wrapped_leg(1);
|
||||
wrapped_leg.front() = std::move(raw_route.unpacked_alternative);
|
||||
routes.values[1] = MakeRoute(raw_route.segment_end_coordinates,
|
||||
wrapped_leg,
|
||||
raw_route.alt_source_traversed_in_reverse,
|
||||
raw_route.alt_target_traversed_in_reverse);
|
||||
}
|
||||
|
||||
response.values["waypoints"] =
|
||||
BaseAPI::MakeWaypoints(raw_routes.routes[0].segment_end_coordinates);
|
||||
response.values["routes"] = std::move(jsRoutes);
|
||||
response.values["waypoints"] = BaseAPI::MakeWaypoints(raw_route.segment_end_coordinates);
|
||||
response.values["routes"] = std::move(routes);
|
||||
response.values["code"] = "Ok";
|
||||
}
|
||||
|
||||
@@ -165,10 +164,6 @@ class RouteAPI : public BaseAPI
|
||||
* to find a via point.
|
||||
* The same exit will be emitted, though, if we should start routing at S, making
|
||||
* the overall response consistent.
|
||||
*
|
||||
* ⚠ CAUTION: order of post-processing steps is important
|
||||
* - postProcess must be called before collapseTurnInstructions that expects
|
||||
* post-processed roundabouts without Exit instructions
|
||||
*/
|
||||
|
||||
guidance::trimShortSegments(steps, leg_geometry);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2016, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef OSRM_ENGINE_APPROACH_HPP
|
||||
#define OSRM_ENGINE_APPROACH_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
|
||||
enum class Approach : std::uint8_t
|
||||
{
|
||||
CURB = 0,
|
||||
UNRESTRICTED = 1
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
|
||||
#include "engine/algorithm.hpp"
|
||||
#include "engine/approach.hpp"
|
||||
#include "engine/geospatial_query.hpp"
|
||||
|
||||
#include "customizer/edge_based_graph.hpp"
|
||||
@@ -14,8 +13,6 @@
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
@@ -217,7 +214,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
unsigned m_check_sum;
|
||||
util::vector_view<util::Coordinate> m_coordinate_list;
|
||||
extractor::PackedOSMIDsView m_osmnodeid_list;
|
||||
util::PackedVectorView<OSMNodeID> m_osmnodeid_list;
|
||||
util::NameTable m_names_table;
|
||||
util::vector_view<std::uint32_t> m_lane_description_offsets;
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> m_lane_description_masks;
|
||||
@@ -225,7 +222,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
util::vector_view<TurnPenalty> m_turn_duration_penalties;
|
||||
extractor::SegmentDataView segment_data;
|
||||
extractor::TurnDataView turn_data;
|
||||
extractor::EdgeBasedNodeDataView edge_based_node_data;
|
||||
|
||||
util::vector_view<char> m_datasource_name_data;
|
||||
util::vector_view<std::size_t> m_datasource_name_offsets;
|
||||
@@ -290,69 +286,50 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
"Is any data loaded into shared memory?" + SOURCE_REF);
|
||||
}
|
||||
|
||||
auto tree_nodes_ptr =
|
||||
auto tree_ptr =
|
||||
data_layout.GetBlockPtr<RTreeNode>(memory_block, storage::DataLayout::R_SEARCH_TREE);
|
||||
auto tree_level_sizes_ptr = data_layout.GetBlockPtr<std::uint64_t>(
|
||||
memory_block, storage::DataLayout::R_SEARCH_TREE_LEVELS);
|
||||
m_static_rtree.reset(
|
||||
new SharedRTree(tree_nodes_ptr,
|
||||
new SharedRTree(tree_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE],
|
||||
tree_level_sizes_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE_LEVELS],
|
||||
file_index_path,
|
||||
m_coordinate_list));
|
||||
m_geospatial_query.reset(
|
||||
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
|
||||
}
|
||||
|
||||
void InitializeNodeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
||||
void InitializeNodeInformationPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
const auto coordinate_list_ptr =
|
||||
layout.GetBlockPtr<util::Coordinate>(memory_ptr, storage::DataLayout::COORDINATE_LIST);
|
||||
const auto coordinate_list_ptr = data_layout.GetBlockPtr<util::Coordinate>(
|
||||
memory_block, storage::DataLayout::COORDINATE_LIST);
|
||||
m_coordinate_list.reset(coordinate_list_ptr,
|
||||
layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
|
||||
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
|
||||
|
||||
const auto osmnodeid_ptr = layout.GetBlockPtr<extractor::PackedOSMIDsView::block_type>(
|
||||
memory_ptr, storage::DataLayout::OSM_NODE_ID_LIST);
|
||||
m_osmnodeid_list = extractor::PackedOSMIDsView(
|
||||
util::vector_view<extractor::PackedOSMIDsView::block_type>(
|
||||
osmnodeid_ptr, layout.num_entries[storage::DataLayout::OSM_NODE_ID_LIST]),
|
||||
// We (ab)use the number of coordinates here because we know we have the same amount of
|
||||
// ids
|
||||
layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
|
||||
}
|
||||
for (unsigned i = 0; i < m_coordinate_list.size(); ++i)
|
||||
{
|
||||
BOOST_ASSERT(GetCoordinateOfNode(i).IsValid());
|
||||
}
|
||||
|
||||
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
|
||||
char *memory_ptr)
|
||||
{
|
||||
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 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]);
|
||||
|
||||
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]);
|
||||
|
||||
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
|
||||
std::move(name_ids),
|
||||
std::move(component_ids),
|
||||
std::move(travel_modes));
|
||||
const auto osmnodeid_list_ptr = data_layout.GetBlockPtr<std::uint64_t>(
|
||||
memory_block, storage::DataLayout::OSM_NODE_ID_LIST);
|
||||
m_osmnodeid_list.reset(osmnodeid_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::OSM_NODE_ID_LIST]);
|
||||
// We (ab)use the number of coordinates here because we know we have the same amount of ids
|
||||
m_osmnodeid_list.set_number_of_entries(
|
||||
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
|
||||
}
|
||||
|
||||
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
||||
{
|
||||
auto via_geometry_list_ptr =
|
||||
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::VIA_NODE_LIST);
|
||||
util::vector_view<GeometryID> geometry_ids(
|
||||
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
|
||||
|
||||
const auto travel_mode_list_ptr =
|
||||
layout.GetBlockPtr<extractor::TravelMode>(memory_ptr, storage::DataLayout::TRAVEL_MODE);
|
||||
util::vector_view<extractor::TravelMode> travel_modes(
|
||||
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
|
||||
|
||||
const auto lane_data_id_ptr =
|
||||
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
|
||||
util::vector_view<LaneDataID> lane_data_ids(
|
||||
@@ -364,6 +341,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
util::vector_view<extractor::guidance::TurnInstruction> turn_instructions(
|
||||
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
||||
|
||||
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]);
|
||||
|
||||
const auto entry_class_id_list_ptr =
|
||||
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
|
||||
util::vector_view<EntryClassID> entry_class_ids(
|
||||
@@ -379,8 +361,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
|
||||
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||
|
||||
turn_data = extractor::TurnDataView(std::move(turn_instructions),
|
||||
turn_data = extractor::TurnDataView(std::move(geometry_ids),
|
||||
std::move(name_ids),
|
||||
std::move(turn_instructions),
|
||||
std::move(lane_data_ids),
|
||||
std::move(travel_modes),
|
||||
std::move(entry_class_ids),
|
||||
std::move(pre_turn_bearings),
|
||||
std::move(post_turn_bearings));
|
||||
@@ -439,47 +424,35 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
util::vector_view<unsigned> geometry_begin_indices(
|
||||
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);
|
||||
util::vector_view<NodeID> geometry_node_list(
|
||||
geometries_node_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]);
|
||||
|
||||
auto geometries_fwd_weight_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentWeightVector::block_type>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
|
||||
extractor::SegmentDataView::SegmentWeightVector geometry_fwd_weight_list(
|
||||
util::vector_view<extractor::SegmentDataView::SegmentWeightVector::block_type>(
|
||||
geometries_fwd_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]),
|
||||
num_entries);
|
||||
auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
|
||||
util::vector_view<EdgeWeight> geometry_fwd_weight_list(
|
||||
geometries_fwd_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
|
||||
|
||||
auto geometries_rev_weight_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentWeightVector::block_type>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
|
||||
extractor::SegmentDataView::SegmentWeightVector geometry_rev_weight_list(
|
||||
util::vector_view<extractor::SegmentDataView::SegmentWeightVector::block_type>(
|
||||
geometries_rev_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]),
|
||||
num_entries);
|
||||
auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
|
||||
util::vector_view<EdgeWeight> geometry_rev_weight_list(
|
||||
geometries_rev_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
|
||||
|
||||
auto geometries_fwd_duration_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentDurationVector::block_type>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
|
||||
extractor::SegmentDataView::SegmentDurationVector geometry_fwd_duration_list(
|
||||
util::vector_view<extractor::SegmentDataView::SegmentDurationVector::block_type>(
|
||||
geometries_fwd_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]),
|
||||
num_entries);
|
||||
auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
|
||||
util::vector_view<EdgeWeight> geometry_fwd_duration_list(
|
||||
geometries_fwd_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
|
||||
|
||||
auto geometries_rev_duration_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentDurationVector::block_type>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
|
||||
extractor::SegmentDataView::SegmentDurationVector geometry_rev_duration_list(
|
||||
util::vector_view<extractor::SegmentDataView::SegmentDurationVector::block_type>(
|
||||
geometries_rev_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]),
|
||||
num_entries);
|
||||
auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
|
||||
util::vector_view<EdgeWeight> geometry_rev_duration_list(
|
||||
geometries_rev_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]);
|
||||
|
||||
auto datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
|
||||
memory_block, storage::DataLayout::DATASOURCES_LIST);
|
||||
@@ -535,7 +508,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
InitializeChecksumPointer(data_layout, memory_block);
|
||||
InitializeNodeInformationPointers(data_layout, memory_block);
|
||||
InitializeEdgeBasedNodeDataInformationPointers(data_layout, memory_block);
|
||||
InitializeEdgeInformationPointers(data_layout, memory_block);
|
||||
InitializeTurnPenalties(data_layout, memory_block);
|
||||
InitializeGeometryPointers(data_layout, memory_block);
|
||||
@@ -564,10 +536,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const override final
|
||||
{
|
||||
return m_osmnodeid_list[id];
|
||||
return m_osmnodeid_list.at(id);
|
||||
}
|
||||
|
||||
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
|
||||
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
|
||||
{
|
||||
|
||||
auto range = segment_data.GetForwardGeometry(id);
|
||||
@@ -626,6 +598,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
return std::vector<DatasourceID>{range.begin(), range.end()};
|
||||
}
|
||||
|
||||
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return turn_data.GetGeometryID(id);
|
||||
}
|
||||
|
||||
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
|
||||
@@ -644,6 +621,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
return turn_data.GetTurnInstruction(id);
|
||||
}
|
||||
|
||||
extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return turn_data.GetTravelMode(id);
|
||||
}
|
||||
|
||||
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
const util::Coordinate north_east) const override final
|
||||
{
|
||||
@@ -655,61 +637,54 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const Approach approach) const override final
|
||||
const float max_distance) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(
|
||||
input_coordinate, max_distance, approach);
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodesInRange(
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
||||
input_coordinate, max_distance, bearing, bearing_range);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const Approach approach) const override final
|
||||
const double max_distance) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, approach);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const Approach approach) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(
|
||||
input_coordinate, max_results, max_distance, approach);
|
||||
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(
|
||||
input_coordinate, max_results, bearing, bearing_range, approach);
|
||||
input_coordinate, max_results, bearing, bearing_range);
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
@@ -717,81 +692,60 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodes(
|
||||
input_coordinate, max_results, max_distance, bearing, bearing_range, approach);
|
||||
input_coordinate, max_results, max_distance, bearing, bearing_range);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const override final
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, approach);
|
||||
input_coordinate);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const override final
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate, const double max_distance) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, approach);
|
||||
input_coordinate, max_distance);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
||||
input_coordinate, max_distance, bearing, bearing_range);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const int bearing_range) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, bearing, bearing_range, approach);
|
||||
input_coordinate, bearing, bearing_range);
|
||||
}
|
||||
|
||||
unsigned GetCheckSum() const override final { return m_check_sum; }
|
||||
|
||||
GeometryID GetGeometryIndex(const NodeID id) const override final
|
||||
NameID GetNameIndexFromEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return edge_based_node_data.GetGeometryID(id);
|
||||
}
|
||||
|
||||
ComponentID GetComponentID(const NodeID id) const override final
|
||||
{
|
||||
return edge_based_node_data.GetComponentID(id);
|
||||
}
|
||||
|
||||
extractor::TravelMode GetTravelMode(const NodeID id) const override final
|
||||
{
|
||||
return edge_based_node_data.GetTravelMode(id);
|
||||
}
|
||||
|
||||
NameID GetNameIndex(const NodeID id) const override final
|
||||
{
|
||||
return edge_based_node_data.GetNameID(id);
|
||||
return turn_data.GetNameID(id);
|
||||
}
|
||||
|
||||
StringView GetNameForID(const NameID id) const override final
|
||||
@@ -899,11 +853,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
m_lane_description_masks.begin() +
|
||||
m_lane_description_offsets[lane_description_id + 1]);
|
||||
}
|
||||
|
||||
bool IsLeftHandDriving() const override final
|
||||
{
|
||||
return m_profile_properties->left_hand_driving;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
// Exposes all data access interfaces to the algorithms via base class ptr
|
||||
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "extractor/edge_based_node_segment.hpp"
|
||||
#include "extractor/edge_based_node.hpp"
|
||||
#include "extractor/external_memory_node.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "engine/approach.hpp"
|
||||
#include "engine/phantom_node.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
@@ -41,7 +40,7 @@ using StringView = util::StringView;
|
||||
class BaseDataFacade
|
||||
{
|
||||
public:
|
||||
using RTreeLeaf = extractor::EdgeBasedNodeSegment;
|
||||
using RTreeLeaf = extractor::EdgeBasedNode;
|
||||
BaseDataFacade() {}
|
||||
virtual ~BaseDataFacade() {}
|
||||
|
||||
@@ -52,9 +51,7 @@ class BaseDataFacade
|
||||
|
||||
virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const = 0;
|
||||
|
||||
virtual GeometryID GetGeometryIndex(const NodeID id) const = 0;
|
||||
|
||||
virtual ComponentID GetComponentID(const NodeID id) const = 0;
|
||||
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const = 0;
|
||||
|
||||
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const = 0;
|
||||
|
||||
@@ -85,7 +82,7 @@ class BaseDataFacade
|
||||
virtual extractor::guidance::TurnInstruction
|
||||
GetTurnInstructionForEdgeID(const EdgeID id) const = 0;
|
||||
|
||||
virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0;
|
||||
virtual extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const = 0;
|
||||
|
||||
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
const util::Coordinate north_east) const = 0;
|
||||
@@ -94,61 +91,51 @@ class BaseDataFacade
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const float max_distance,
|
||||
const Approach approach) const = 0;
|
||||
const float max_distance) const = 0;
|
||||
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const Approach approach) const = 0;
|
||||
virtual std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const Approach approach) const = 0;
|
||||
const double max_distance) const = 0;
|
||||
|
||||
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const = 0;
|
||||
const double max_distance) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const int bearing_range) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const int bearing_range) const = 0;
|
||||
|
||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||
virtual extractor::guidance::TurnLaneDescription
|
||||
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
|
||||
|
||||
virtual NameID GetNameIndex(const NodeID id) const = 0;
|
||||
virtual NameID GetNameIndexFromEdgeID(const EdgeID id) const = 0;
|
||||
|
||||
virtual StringView GetNameForID(const NameID id) const = 0;
|
||||
|
||||
@@ -181,8 +168,6 @@ class BaseDataFacade
|
||||
virtual EntryClassID GetEntryClassID(const EdgeID eid) const = 0;
|
||||
|
||||
virtual util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const = 0;
|
||||
|
||||
virtual bool IsLeftHandDriving() const = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "engine/status.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/exception_utils.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/json_container.hpp"
|
||||
|
||||
#include <memory>
|
||||
@@ -185,8 +184,7 @@ bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const Engin
|
||||
|
||||
auto mem = storage::makeSharedMemory(barrier.data().region);
|
||||
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
|
||||
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER) >
|
||||
sizeof(std::uint64_t) + sizeof(util::FingerPrint);
|
||||
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER) > 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -196,8 +194,8 @@ bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const Engin
|
||||
|
||||
in.seekg(0, std::ios::end);
|
||||
std::size_t size = in.tellg();
|
||||
// An empty core files is only the 8 byte size header plus the 8 byte Fingerprint.
|
||||
return size > sizeof(std::uint64_t) + sizeof(util::FingerPrint);
|
||||
// An empty core files is only the 4 byte size header.
|
||||
return size > sizeof(std::uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef GEOSPATIAL_QUERY_HPP
|
||||
#define GEOSPATIAL_QUERY_HPP
|
||||
|
||||
#include "engine/approach.hpp"
|
||||
#include "engine/phantom_node.hpp"
|
||||
#include "util/bearing.hpp"
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
@@ -51,19 +50,15 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Does not filter by small/big component!
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const
|
||||
const double max_distance) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||
return boolPairAnd(HasValidEdge(segment),
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
},
|
||||
[this, max_distance, input_coordinate](const std::size_t,
|
||||
const CandidateSegment &segment) {
|
||||
return CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
[this](const CandidateSegment &segment) { return HasValidEdge(segment); },
|
||||
[this, max_distance, input_coordinate](const std::size_t,
|
||||
const CandidateSegment &segment) {
|
||||
return CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
}
|
||||
@@ -74,18 +69,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const int bearing_range) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, bearing, bearing_range, max_distance](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_direction = boolPairAnd(
|
||||
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
|
||||
use_direction =
|
||||
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
|
||||
return use_direction;
|
||||
[this, bearing, bearing_range, max_distance](const CandidateSegment &segment) {
|
||||
return boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||
HasValidEdge(segment));
|
||||
},
|
||||
[this, max_distance, input_coordinate](const std::size_t,
|
||||
const CandidateSegment &segment) {
|
||||
@@ -101,17 +91,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const int bearing_range) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, bearing, bearing_range](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_direction = boolPairAnd(
|
||||
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
|
||||
return boolPairAnd(use_direction,
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
[this, bearing, bearing_range](const CandidateSegment &segment) {
|
||||
return boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||
HasValidEdge(segment));
|
||||
},
|
||||
[max_results](const std::size_t num_results, const CandidateSegment &) {
|
||||
return num_results >= max_results;
|
||||
@@ -128,17 +114,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const int bearing_range) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, bearing, bearing_range](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_direction = boolPairAnd(
|
||||
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
|
||||
return boolPairAnd(use_direction,
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
[this, bearing, bearing_range](const CandidateSegment &segment) {
|
||||
return boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||
HasValidEdge(segment));
|
||||
},
|
||||
[this, max_distance, max_results, input_coordinate](const std::size_t num_results,
|
||||
const CandidateSegment &segment) {
|
||||
@@ -152,19 +134,14 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Returns max_results nearest PhantomNodes.
|
||||
// Does not filter by small/big component!
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const Approach approach) const
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||
return boolPairAnd(HasValidEdge(segment),
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
},
|
||||
[max_results](const std::size_t num_results, const CandidateSegment &) {
|
||||
return num_results >= max_results;
|
||||
});
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
[this](const CandidateSegment &segment) { return HasValidEdge(segment); },
|
||||
[max_results](const std::size_t num_results, const CandidateSegment &) {
|
||||
return num_results >= max_results;
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
}
|
||||
@@ -174,20 +151,16 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||
const unsigned max_results,
|
||||
const double max_distance,
|
||||
const Approach approach) const
|
||||
const double max_distance) const
|
||||
{
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate](const CandidateSegment &segment) {
|
||||
return boolPairAnd(HasValidEdge(segment),
|
||||
CheckApproach(input_coordinate, segment, approach));
|
||||
},
|
||||
[this, max_distance, max_results, input_coordinate](const std::size_t num_results,
|
||||
const CandidateSegment &segment) {
|
||||
return num_results >= max_results ||
|
||||
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
auto results =
|
||||
rtree.Nearest(input_coordinate,
|
||||
[this](const CandidateSegment &segment) { return HasValidEdge(segment); },
|
||||
[this, max_distance, max_results, input_coordinate](
|
||||
const std::size_t num_results, const CandidateSegment &segment) {
|
||||
return num_results >= max_results ||
|
||||
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||
});
|
||||
|
||||
return MakePhantomNodes(input_coordinate, results);
|
||||
}
|
||||
@@ -196,29 +169,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const
|
||||
const double max_distance) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
[this, &has_big_component, &has_small_component](const CandidateSegment &segment) {
|
||||
auto use_segment = (!has_small_component ||
|
||||
(!has_big_component && !segment.data.component.is_tiny));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto valid_edges = HasValidEdge(segment);
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
use_directions =
|
||||
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||
|
||||
if (use_directions.first || use_directions.second)
|
||||
if (valid_edges.first || valid_edges.second)
|
||||
{
|
||||
has_big_component = has_big_component || !IsTinyComponent(segment);
|
||||
has_small_component = has_small_component || IsTinyComponent(segment);
|
||||
has_big_component = has_big_component || !segment.data.component.is_tiny;
|
||||
has_small_component = has_small_component || segment.data.component.is_tiny;
|
||||
}
|
||||
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
return use_directions;
|
||||
},
|
||||
[this, &has_big_component, max_distance, input_coordinate](
|
||||
@@ -240,30 +208,28 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
[this, &has_big_component, &has_small_component](const CandidateSegment &segment) {
|
||||
auto use_segment = (!has_small_component ||
|
||||
(!has_big_component && !segment.data.component.is_tiny));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
|
||||
if (!use_directions.first && !use_directions.second)
|
||||
return use_directions;
|
||||
const auto valid_edges = HasValidEdge(segment);
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
use_directions =
|
||||
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||
|
||||
if (use_directions.first || use_directions.second)
|
||||
if (valid_edges.first || valid_edges.second)
|
||||
{
|
||||
has_big_component = has_big_component || !IsTinyComponent(segment);
|
||||
has_small_component = has_small_component || IsTinyComponent(segment);
|
||||
|
||||
has_big_component = has_big_component || !segment.data.component.is_tiny;
|
||||
has_small_component = has_small_component || segment.data.component.is_tiny;
|
||||
}
|
||||
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
return use_directions;
|
||||
},
|
||||
[&has_big_component](const std::size_t num_results, const CandidateSegment &) {
|
||||
@@ -282,25 +248,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
|
||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this,
|
||||
approach,
|
||||
&input_coordinate,
|
||||
bearing,
|
||||
bearing_range,
|
||||
&has_big_component,
|
||||
&has_small_component](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
[this, bearing, bearing_range, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_segment = (!has_small_component ||
|
||||
(!has_big_component && !segment.data.component.is_tiny));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||
|
||||
@@ -309,13 +267,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
use_directions =
|
||||
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||
HasValidEdge(segment));
|
||||
use_directions = boolPairAnd(
|
||||
use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||
|
||||
if (use_directions.first || use_directions.second)
|
||||
{
|
||||
has_big_component = has_big_component || !IsTinyComponent(segment);
|
||||
has_small_component = has_small_component || IsTinyComponent(segment);
|
||||
has_big_component = has_big_component || !segment.data.component.is_tiny;
|
||||
has_small_component = has_small_component || segment.data.component.is_tiny;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,22 +296,16 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const int bearing_range) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this,
|
||||
approach,
|
||||
&input_coordinate,
|
||||
bearing,
|
||||
bearing_range,
|
||||
&has_big_component,
|
||||
&has_small_component](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
[this, bearing, bearing_range, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
auto use_segment = (!has_small_component ||
|
||||
(!has_big_component && !segment.data.component.is_tiny));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||
|
||||
@@ -365,13 +314,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
use_directions =
|
||||
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
|
||||
HasValidEdge(segment));
|
||||
use_directions = boolPairAnd(
|
||||
use_directions, CheckApproach(input_coordinate, segment, approach));
|
||||
|
||||
if (use_directions.first || use_directions.second)
|
||||
{
|
||||
has_big_component = has_big_component || !IsTinyComponent(segment);
|
||||
has_small_component = has_small_component || IsTinyComponent(segment);
|
||||
has_big_component = has_big_component || !segment.data.component.is_tiny;
|
||||
has_small_component = has_small_component || segment.data.component.is_tiny;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,24 +371,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
|
||||
EdgeWeight forward_weight_offset = 0, forward_weight = 0;
|
||||
EdgeWeight reverse_weight_offset = 0, reverse_weight = 0;
|
||||
EdgeDuration forward_duration_offset = 0, forward_duration = 0;
|
||||
EdgeDuration reverse_duration_offset = 0, reverse_duration = 0;
|
||||
|
||||
BOOST_ASSERT(data.forward_segment_id.enabled || data.reverse_segment_id.enabled);
|
||||
BOOST_ASSERT(!data.reverse_segment_id.enabled ||
|
||||
datafacade.GetGeometryIndex(data.forward_segment_id.id).id ==
|
||||
datafacade.GetGeometryIndex(data.reverse_segment_id.id).id);
|
||||
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
|
||||
const auto component_id = datafacade.GetComponentID(data.forward_segment_id.id);
|
||||
EdgeWeight forward_duration_offset = 0, forward_duration = 0;
|
||||
EdgeWeight reverse_duration_offset = 0, reverse_duration = 0;
|
||||
|
||||
const std::vector<EdgeWeight> forward_weight_vector =
|
||||
datafacade.GetUncompressedForwardWeights(geometry_id);
|
||||
datafacade.GetUncompressedForwardWeights(data.packed_geometry_id);
|
||||
const std::vector<EdgeWeight> reverse_weight_vector =
|
||||
datafacade.GetUncompressedReverseWeights(geometry_id);
|
||||
datafacade.GetUncompressedReverseWeights(data.packed_geometry_id);
|
||||
const std::vector<EdgeWeight> forward_duration_vector =
|
||||
datafacade.GetUncompressedForwardDurations(geometry_id);
|
||||
datafacade.GetUncompressedForwardDurations(data.packed_geometry_id);
|
||||
const std::vector<EdgeWeight> reverse_duration_vector =
|
||||
datafacade.GetUncompressedReverseDurations(geometry_id);
|
||||
datafacade.GetUncompressedReverseDurations(data.packed_geometry_id);
|
||||
|
||||
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
|
||||
{
|
||||
@@ -469,17 +408,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
||||
{
|
||||
forward_weight = static_cast<EdgeWeight>(forward_weight * ratio);
|
||||
forward_duration = static_cast<EdgeDuration>(forward_duration * ratio);
|
||||
forward_duration = static_cast<EdgeWeight>(forward_duration * ratio);
|
||||
}
|
||||
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
||||
{
|
||||
reverse_weight -= static_cast<EdgeWeight>(reverse_weight * ratio);
|
||||
reverse_duration -= static_cast<EdgeDuration>(reverse_duration * ratio);
|
||||
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
|
||||
}
|
||||
|
||||
// check phantom node segments validity
|
||||
auto areSegmentsValid = [](auto first, auto last) -> bool {
|
||||
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
|
||||
return std::find(first, last, INVALID_EDGE_WEIGHT) == last;
|
||||
};
|
||||
bool is_forward_valid_source =
|
||||
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
|
||||
@@ -492,7 +431,6 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
|
||||
|
||||
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
||||
component_id,
|
||||
forward_weight,
|
||||
reverse_weight,
|
||||
forward_weight_offset,
|
||||
@@ -557,7 +495,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
|
||||
/**
|
||||
* Checks to see if the edge weights are valid. We might have an edge,
|
||||
* but a traffic update might set the speed to 0 (weight == INVALID_SEGMENT_WEIGHT).
|
||||
* but a traffic update might set the speed to 0 (weight == INVALID_EDGE_WEIGHT).
|
||||
* which means that this edge is not currently traversible. If this is the case,
|
||||
* then we shouldn't snap to this edge.
|
||||
*/
|
||||
@@ -567,64 +505,25 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
bool forward_edge_valid = false;
|
||||
bool reverse_edge_valid = false;
|
||||
|
||||
const auto &data = segment.data;
|
||||
BOOST_ASSERT(data.forward_segment_id.enabled);
|
||||
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
|
||||
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
|
||||
|
||||
const std::vector<EdgeWeight> forward_weight_vector =
|
||||
datafacade.GetUncompressedForwardWeights(geometry_id);
|
||||
datafacade.GetUncompressedForwardWeights(segment.data.packed_geometry_id);
|
||||
|
||||
if (forward_weight_vector[data.fwd_segment_position] != INVALID_SEGMENT_WEIGHT)
|
||||
if (forward_weight_vector[segment.data.fwd_segment_position] != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
forward_edge_valid = data.forward_segment_id.enabled;
|
||||
forward_edge_valid = segment.data.forward_segment_id.enabled;
|
||||
}
|
||||
|
||||
const std::vector<EdgeWeight> reverse_weight_vector =
|
||||
datafacade.GetUncompressedReverseWeights(geometry_id);
|
||||
if (reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1] !=
|
||||
INVALID_SEGMENT_WEIGHT)
|
||||
datafacade.GetUncompressedReverseWeights(segment.data.packed_geometry_id);
|
||||
if (reverse_weight_vector[reverse_weight_vector.size() - segment.data.fwd_segment_position -
|
||||
1] != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
reverse_edge_valid = data.reverse_segment_id.enabled;
|
||||
reverse_edge_valid = segment.data.reverse_segment_id.enabled;
|
||||
}
|
||||
|
||||
return std::make_pair(forward_edge_valid, reverse_edge_valid);
|
||||
}
|
||||
|
||||
bool IsTinyComponent(const CandidateSegment &segment) const
|
||||
{
|
||||
const auto &data = segment.data;
|
||||
BOOST_ASSERT(data.forward_segment_id.enabled);
|
||||
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
|
||||
return datafacade.GetComponentID(data.forward_segment_id.id).is_tiny;
|
||||
}
|
||||
|
||||
std::pair<bool, bool> CheckApproach(const util::Coordinate &input_coordinate,
|
||||
const CandidateSegment &segment,
|
||||
const Approach approach) const
|
||||
{
|
||||
bool isOnewaySegment =
|
||||
!(segment.data.forward_segment_id.enabled && segment.data.reverse_segment_id.enabled);
|
||||
if (!isOnewaySegment && approach == Approach::CURB)
|
||||
{
|
||||
// Check the counter clockwise
|
||||
//
|
||||
// input_coordinate
|
||||
// |
|
||||
// |
|
||||
// segment.data.u ---------------- segment.data.v
|
||||
|
||||
bool input_coordinate_is_at_right = !util::coordinate_calculation::isCCW(
|
||||
coordinates[segment.data.u], coordinates[segment.data.v], input_coordinate);
|
||||
|
||||
if (datafacade.IsLeftHandDriving())
|
||||
input_coordinate_is_at_right = !input_coordinate_is_at_right;
|
||||
|
||||
return std::make_pair(input_coordinate_is_at_right, (!input_coordinate_is_at_right));
|
||||
}
|
||||
return std::make_pair(true, true);
|
||||
}
|
||||
|
||||
const RTreeT &rtree;
|
||||
const CoordinateList &coordinates;
|
||||
DataFacadeT &datafacade;
|
||||
|
||||
@@ -51,11 +51,8 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
// source node rev: 2 0 <- 1 <- 2
|
||||
const auto source_segment_start_coordinate =
|
||||
source_node.fwd_segment_position + (reversed_source ? 1 : 0);
|
||||
const auto source_node_id =
|
||||
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
|
||||
const auto source_gemetry_id = facade.GetGeometryIndex(source_node_id).id;
|
||||
const std::vector<NodeID> source_geometry =
|
||||
facade.GetUncompressedForwardGeometry(source_gemetry_id);
|
||||
facade.GetUncompressedForwardGeometry(source_node.packed_geometry_id);
|
||||
geometry.osm_node_ids.push_back(
|
||||
facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate]));
|
||||
|
||||
@@ -92,11 +89,8 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
// segment leading to the target node
|
||||
geometry.segment_distances.push_back(cumulative_distance);
|
||||
|
||||
const auto target_node_id =
|
||||
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
|
||||
const auto target_gemetry_id = facade.GetGeometryIndex(target_node_id).id;
|
||||
const std::vector<DatasourceID> forward_datasources =
|
||||
facade.GetUncompressedForwardDatasources(target_gemetry_id);
|
||||
facade.GetUncompressedForwardDatasources(target_node.packed_geometry_id);
|
||||
|
||||
// FIXME if source and target phantoms are on the same segment then duration and weight
|
||||
// will be from one projected point till end of segment
|
||||
@@ -119,7 +113,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
||||
const auto target_segment_end_coordinate =
|
||||
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
|
||||
const std::vector<NodeID> target_geometry =
|
||||
facade.GetUncompressedForwardGeometry(target_gemetry_id);
|
||||
facade.GetUncompressedForwardGeometry(target_node.packed_geometry_id);
|
||||
geometry.osm_node_ids.push_back(
|
||||
facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate]));
|
||||
|
||||
|
||||
@@ -40,8 +40,7 @@ struct NamedSegment
|
||||
|
||||
template <std::size_t SegmentNumber>
|
||||
|
||||
std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDataFacade &facade,
|
||||
const std::vector<PathData> &route_data,
|
||||
std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathData> &route_data,
|
||||
const PhantomNode &target_node,
|
||||
const bool target_traversed_in_reverse)
|
||||
{
|
||||
@@ -81,10 +80,8 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
|
||||
});
|
||||
const auto target_duration =
|
||||
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
||||
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
|
||||
: target_node.forward_segment_id.id;
|
||||
if (target_duration > 1)
|
||||
segments.push_back({target_duration, index++, facade.GetNameIndex(target_node_id)});
|
||||
segments.push_back({target_duration, index++, target_node.name_id});
|
||||
// this makes sure that the segment with the lowest position comes first
|
||||
std::sort(
|
||||
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
|
||||
@@ -186,7 +183,7 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
||||
if (needs_summary)
|
||||
{
|
||||
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(
|
||||
facade, route_data, target_node, target_traversed_in_reverse);
|
||||
route_data, target_node, target_traversed_in_reverse);
|
||||
|
||||
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
|
||||
BOOST_ASSERT(summary_array.begin() != summary_array.end());
|
||||
|
||||
@@ -49,19 +49,15 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
|
||||
const EdgeWeight source_duration =
|
||||
source_traversed_in_reverse ? source_node.reverse_duration : source_node.forward_duration;
|
||||
const auto source_node_id = source_traversed_in_reverse ? source_node.reverse_segment_id.id
|
||||
: source_node.forward_segment_id.id;
|
||||
const auto source_name_id = facade.GetNameIndex(source_node_id);
|
||||
const auto source_mode = facade.GetTravelMode(source_node_id);
|
||||
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
|
||||
: source_node.forward_travel_mode;
|
||||
|
||||
const EdgeWeight target_duration =
|
||||
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
||||
const EdgeWeight target_weight =
|
||||
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
|
||||
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
|
||||
: target_node.forward_segment_id.id;
|
||||
const auto target_name_id = facade.GetNameIndex(target_node_id);
|
||||
const auto target_mode = facade.GetTravelMode(target_node_id);
|
||||
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
|
||||
: target_node.forward_travel_mode;
|
||||
|
||||
const auto number_of_segments = leg_geometry.GetNumberOfSegments();
|
||||
|
||||
@@ -99,7 +95,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
|
||||
// some name changes are not announced in our processing. For these, we have to keep the
|
||||
// first name on the segment
|
||||
auto step_name_id = source_name_id;
|
||||
auto step_name_id = source_node.name_id;
|
||||
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
|
||||
{
|
||||
const auto &path_point = leg_data[leg_data_index];
|
||||
@@ -138,7 +134,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
}
|
||||
else
|
||||
{
|
||||
step_name_id = facade.GetNameIndex(target_node_id);
|
||||
step_name_id = target_node.name_id;
|
||||
}
|
||||
|
||||
// extract bearings
|
||||
@@ -234,11 +230,11 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
|
||||
const EdgeWeight duration = std::max(0, target_duration - source_duration);
|
||||
|
||||
steps.push_back(RouteStep{source_name_id,
|
||||
facade.GetNameForID(source_name_id).to_string(),
|
||||
facade.GetRefForID(source_name_id).to_string(),
|
||||
facade.GetPronunciationForID(source_name_id).to_string(),
|
||||
facade.GetDestinationsForID(source_name_id).to_string(),
|
||||
steps.push_back(RouteStep{source_node.name_id,
|
||||
facade.GetNameForID(source_node.name_id).to_string(),
|
||||
facade.GetRefForID(source_node.name_id).to_string(),
|
||||
facade.GetPronunciationForID(source_node.name_id).to_string(),
|
||||
facade.GetDestinationsForID(source_node.name_id).to_string(),
|
||||
NO_ROTARY_NAME,
|
||||
NO_ROTARY_NAME,
|
||||
duration / 10.,
|
||||
@@ -272,11 +268,11 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
||||
0};
|
||||
|
||||
BOOST_ASSERT(!leg_geometry.locations.empty());
|
||||
steps.push_back(RouteStep{target_name_id,
|
||||
facade.GetNameForID(target_name_id).to_string(),
|
||||
facade.GetRefForID(target_name_id).to_string(),
|
||||
facade.GetPronunciationForID(target_name_id).to_string(),
|
||||
facade.GetDestinationsForID(target_name_id).to_string(),
|
||||
steps.push_back(RouteStep{target_node.name_id,
|
||||
facade.GetNameForID(target_node.name_id).to_string(),
|
||||
facade.GetRefForID(target_node.name_id).to_string(),
|
||||
facade.GetPronunciationForID(target_node.name_id).to_string(),
|
||||
facade.GetDestinationsForID(target_node.name_id).to_string(),
|
||||
NO_ROTARY_NAME,
|
||||
NO_ROTARY_NAME,
|
||||
ZERO_DURATION,
|
||||
|
||||
@@ -63,8 +63,8 @@ struct Hint
|
||||
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
||||
};
|
||||
|
||||
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
|
||||
constexpr std::size_t ENCODED_HINT_SIZE = 92;
|
||||
static_assert(sizeof(Hint) == 72 + 4, "Hint is bigger than expected");
|
||||
constexpr std::size_t ENCODED_HINT_SIZE = 104;
|
||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace osrm
|
||||
namespace engine
|
||||
{
|
||||
|
||||
const constexpr unsigned INVALID_EXIT_NR = 0;
|
||||
|
||||
struct PathData
|
||||
{
|
||||
// id of via node of the turn
|
||||
@@ -47,28 +49,28 @@ struct PathData
|
||||
struct InternalRouteResult
|
||||
{
|
||||
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||
std::vector<PathData> unpacked_alternative;
|
||||
std::vector<PhantomNodes> segment_end_coordinates;
|
||||
std::vector<bool> source_traversed_in_reverse;
|
||||
std::vector<bool> target_traversed_in_reverse;
|
||||
EdgeWeight shortest_path_weight = INVALID_EDGE_WEIGHT;
|
||||
std::vector<bool> alt_source_traversed_in_reverse;
|
||||
std::vector<bool> alt_target_traversed_in_reverse;
|
||||
int shortest_path_length;
|
||||
int alternative_path_length;
|
||||
|
||||
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_weight; }
|
||||
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_length; }
|
||||
|
||||
bool has_alternative() const { return INVALID_EDGE_WEIGHT != alternative_path_length; }
|
||||
|
||||
bool is_via_leg(const std::size_t leg) const
|
||||
{
|
||||
return (leg != unpacked_path_segments.size() - 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct InternalManyRoutesResult
|
||||
{
|
||||
InternalManyRoutesResult() = default;
|
||||
InternalManyRoutesResult(InternalRouteResult route) : routes{std::move(route)} {}
|
||||
InternalManyRoutesResult(std::vector<InternalRouteResult> routes_) : routes{std::move(routes_)}
|
||||
InternalRouteResult()
|
||||
: shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<InternalRouteResult> routes;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,12 +48,16 @@ struct PhantomNode
|
||||
{
|
||||
PhantomNode()
|
||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
|
||||
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
||||
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
|
||||
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
|
||||
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
||||
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
||||
is_valid_forward_source{false}, is_valid_forward_target{false},
|
||||
is_valid_reverse_source{false}, is_valid_reverse_target{false}
|
||||
forward_duration_offset(0), reverse_duration_offset(0),
|
||||
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
||||
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE), is_valid_forward_source(false),
|
||||
is_valid_forward_target(false), is_valid_reverse_source(false),
|
||||
is_valid_reverse_target(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -91,7 +95,7 @@ struct PhantomNode
|
||||
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
||||
(reverse_duration != MAXIMAL_EDGE_DURATION)) &&
|
||||
(component.id != INVALID_COMPONENTID);
|
||||
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
|
||||
}
|
||||
|
||||
bool IsValid(const unsigned number_of_nodes, const util::Coordinate queried_coordinate) const
|
||||
@@ -99,7 +103,7 @@ struct PhantomNode
|
||||
return queried_coordinate == input_location && IsValid(number_of_nodes);
|
||||
}
|
||||
|
||||
bool IsValid() const { return location.IsValid(); }
|
||||
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
|
||||
|
||||
bool IsValidForwardSource() const
|
||||
{
|
||||
@@ -122,7 +126,6 @@ struct PhantomNode
|
||||
|
||||
template <class OtherT>
|
||||
explicit PhantomNode(const OtherT &other,
|
||||
ComponentID component,
|
||||
EdgeWeight forward_weight,
|
||||
EdgeWeight reverse_weight,
|
||||
EdgeWeight forward_weight_offset,
|
||||
@@ -138,13 +141,17 @@ struct PhantomNode
|
||||
const util::Coordinate location,
|
||||
const util::Coordinate input_location)
|
||||
: forward_segment_id{other.forward_segment_id},
|
||||
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
|
||||
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
|
||||
reverse_segment_id{other.reverse_segment_id}, name_id{other.name_id},
|
||||
forward_weight{forward_weight}, reverse_weight{reverse_weight},
|
||||
forward_weight_offset{forward_weight_offset},
|
||||
reverse_weight_offset{reverse_weight_offset}, forward_duration{forward_duration},
|
||||
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
|
||||
reverse_duration_offset{reverse_duration_offset},
|
||||
component{component.id, component.is_tiny}, location{location},
|
||||
packed_geometry_id{other.packed_geometry_id},
|
||||
component{other.component.id, other.component.is_tiny}, location{location},
|
||||
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
||||
forward_travel_mode{other.forward_travel_mode},
|
||||
backward_travel_mode{other.backward_travel_mode},
|
||||
is_valid_forward_source{is_valid_forward_source},
|
||||
is_valid_forward_target{is_valid_forward_target},
|
||||
is_valid_reverse_source{is_valid_reverse_source},
|
||||
@@ -154,6 +161,7 @@ struct PhantomNode
|
||||
|
||||
SegmentID forward_segment_id;
|
||||
SegmentID reverse_segment_id;
|
||||
unsigned name_id;
|
||||
EdgeWeight forward_weight;
|
||||
EdgeWeight reverse_weight;
|
||||
EdgeWeight forward_weight_offset; // TODO: try to remove -> requires path unpacking changes
|
||||
@@ -162,21 +170,30 @@ struct PhantomNode
|
||||
EdgeWeight reverse_duration;
|
||||
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
||||
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
||||
ComponentID component;
|
||||
unsigned packed_geometry_id;
|
||||
struct ComponentType
|
||||
{
|
||||
std::uint32_t id : 31;
|
||||
std::uint32_t is_tiny : 1;
|
||||
} component;
|
||||
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to be 4 bytes big");
|
||||
|
||||
util::Coordinate location;
|
||||
util::Coordinate input_location;
|
||||
unsigned short fwd_segment_position;
|
||||
// note 4 bits would suffice for each,
|
||||
// but the saved byte would be padding anyway
|
||||
extractor::TravelMode forward_travel_mode : 4;
|
||||
extractor::TravelMode backward_travel_mode : 4;
|
||||
// is phantom node valid to be used as source or target
|
||||
private:
|
||||
unsigned short is_valid_forward_source : 1;
|
||||
unsigned short is_valid_forward_target : 1;
|
||||
unsigned short is_valid_reverse_source : 1;
|
||||
unsigned short is_valid_reverse_target : 1;
|
||||
unsigned short : 12; // Unused padding out to 16 bits (2 bytes)
|
||||
bool is_valid_forward_source : 1;
|
||||
bool is_valid_forward_target : 1;
|
||||
bool is_valid_reverse_source : 1;
|
||||
bool is_valid_reverse_target : 1;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
|
||||
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
|
||||
|
||||
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
||||
|
||||
@@ -203,6 +220,7 @@ inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
|
||||
{
|
||||
out << "node1: " << pn.forward_segment_id.id << ", "
|
||||
<< "node2: " << pn.reverse_segment_id.id << ", "
|
||||
<< "name: " << pn.name_id << ", "
|
||||
<< "fwd-w: " << pn.forward_weight << ", "
|
||||
<< "rev-w: " << pn.reverse_weight << ", "
|
||||
<< "fwd-o: " << pn.forward_weight_offset << ", "
|
||||
@@ -211,6 +229,7 @@ inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
|
||||
<< "rev-d: " << pn.reverse_duration << ", "
|
||||
<< "fwd-do: " << pn.forward_duration_offset << ", "
|
||||
<< "rev-do: " << pn.reverse_duration_offset << ", "
|
||||
<< "geom: " << pn.packed_geometry_id << ", "
|
||||
<< "comp: " << pn.component.is_tiny << " / " << pn.component.id << ", "
|
||||
<< "pos: " << pn.fwd_segment_position << ", "
|
||||
<< "loc: " << pn.location;
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <util/log.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
@@ -120,14 +118,9 @@ class BasePlugin
|
||||
|
||||
const bool use_hints = !parameters.hints.empty();
|
||||
const bool use_bearings = !parameters.bearings.empty();
|
||||
const bool use_approaches = !parameters.approaches.empty();
|
||||
|
||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
{
|
||||
Approach approach = engine::Approach::UNRESTRICTED;
|
||||
if (use_approaches && parameters.approaches[i])
|
||||
approach = parameters.approaches[i].get();
|
||||
|
||||
if (use_hints && parameters.hints[i] &&
|
||||
parameters.hints[i]->IsValid(parameters.coordinates[i], facade))
|
||||
{
|
||||
@@ -144,13 +137,12 @@ class BasePlugin
|
||||
facade.NearestPhantomNodesInRange(parameters.coordinates[i],
|
||||
radiuses[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
parameters.bearings[i]->range);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_nodes[i] = facade.NearestPhantomNodesInRange(
|
||||
parameters.coordinates[i], radiuses[i], approach);
|
||||
phantom_nodes[i] =
|
||||
facade.NearestPhantomNodesInRange(parameters.coordinates[i], radiuses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,15 +160,10 @@ class BasePlugin
|
||||
const bool use_hints = !parameters.hints.empty();
|
||||
const bool use_bearings = !parameters.bearings.empty();
|
||||
const bool use_radiuses = !parameters.radiuses.empty();
|
||||
const bool use_approaches = !parameters.approaches.empty();
|
||||
|
||||
BOOST_ASSERT(parameters.IsValid());
|
||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
{
|
||||
Approach approach = engine::Approach::UNRESTRICTED;
|
||||
if (use_approaches && parameters.approaches[i])
|
||||
approach = parameters.approaches[i].get();
|
||||
|
||||
if (use_hints && parameters.hints[i] &&
|
||||
parameters.hints[i]->IsValid(parameters.coordinates[i], facade))
|
||||
{
|
||||
@@ -196,31 +183,27 @@ class BasePlugin
|
||||
number_of_results,
|
||||
*parameters.radiuses[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
parameters.bearings[i]->range);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_nodes[i] = facade.NearestPhantomNodes(parameters.coordinates[i],
|
||||
number_of_results,
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
parameters.bearings[i]->range);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (use_radiuses && parameters.radiuses[i])
|
||||
{
|
||||
phantom_nodes[i] = facade.NearestPhantomNodes(parameters.coordinates[i],
|
||||
number_of_results,
|
||||
*parameters.radiuses[i],
|
||||
approach);
|
||||
phantom_nodes[i] = facade.NearestPhantomNodes(
|
||||
parameters.coordinates[i], number_of_results, *parameters.radiuses[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_nodes[i] = facade.NearestPhantomNodes(
|
||||
parameters.coordinates[i], number_of_results, approach);
|
||||
phantom_nodes[i] =
|
||||
facade.NearestPhantomNodes(parameters.coordinates[i], number_of_results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,15 +224,10 @@ class BasePlugin
|
||||
const bool use_hints = !parameters.hints.empty();
|
||||
const bool use_bearings = !parameters.bearings.empty();
|
||||
const bool use_radiuses = !parameters.radiuses.empty();
|
||||
const bool use_approaches = !parameters.approaches.empty();
|
||||
|
||||
BOOST_ASSERT(parameters.IsValid());
|
||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
{
|
||||
Approach approach = engine::Approach::UNRESTRICTED;
|
||||
if (use_approaches && parameters.approaches[i])
|
||||
approach = parameters.approaches[i].get();
|
||||
|
||||
if (use_hints && parameters.hints[i] &&
|
||||
parameters.hints[i]->IsValid(parameters.coordinates[i], facade))
|
||||
{
|
||||
@@ -267,8 +245,7 @@ class BasePlugin
|
||||
parameters.coordinates[i],
|
||||
*parameters.radiuses[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
parameters.bearings[i]->range);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -276,8 +253,7 @@ class BasePlugin
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
parameters.bearings[i]->range);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -286,13 +262,13 @@ class BasePlugin
|
||||
{
|
||||
phantom_node_pairs[i] =
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i], *parameters.radiuses[i], approach);
|
||||
parameters.coordinates[i], *parameters.radiuses[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_node_pairs[i] =
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i], approach);
|
||||
parameters.coordinates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace engine
|
||||
class RoutingAlgorithmsInterface
|
||||
{
|
||||
public:
|
||||
virtual InternalManyRoutesResult
|
||||
virtual InternalRouteResult
|
||||
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
||||
|
||||
virtual InternalRouteResult
|
||||
@@ -65,7 +65,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
||||
|
||||
virtual ~RoutingAlgorithms() = default;
|
||||
|
||||
InternalManyRoutesResult
|
||||
InternalRouteResult
|
||||
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
|
||||
|
||||
InternalRouteResult ShortestPathSearch(
|
||||
@@ -129,7 +129,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
||||
};
|
||||
|
||||
template <typename Algorithm>
|
||||
InternalManyRoutesResult
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||
{
|
||||
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
@@ -188,7 +188,7 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::G
|
||||
|
||||
// CoreCH overrides
|
||||
template <>
|
||||
InternalManyRoutesResult inline RoutingAlgorithms<
|
||||
InternalRouteResult inline RoutingAlgorithms<
|
||||
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
||||
@@ -206,7 +206,7 @@ RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
||||
|
||||
// MLD overrides for not implemented
|
||||
template <>
|
||||
InternalManyRoutesResult inline RoutingAlgorithms<
|
||||
InternalRouteResult inline RoutingAlgorithms<
|
||||
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is not implemented");
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace routing_algorithms
|
||||
{
|
||||
namespace ch
|
||||
{
|
||||
InternalManyRoutesResult
|
||||
InternalRouteResult
|
||||
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const PhantomNodes &phantom_node_pair);
|
||||
|
||||
@@ -83,37 +83,37 @@ void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNod
|
||||
|
||||
template <typename FacadeT>
|
||||
void annotatePath(const FacadeT &facade,
|
||||
const PhantomNodes &phantom_node_pair,
|
||||
const std::vector<NodeID> &unpacked_nodes,
|
||||
const NodeID source_node,
|
||||
const NodeID target_node,
|
||||
const std::vector<EdgeID> &unpacked_edges,
|
||||
const PhantomNodes &phantom_node_pair,
|
||||
std::vector<PathData> &unpacked_path)
|
||||
{
|
||||
BOOST_ASSERT(!unpacked_nodes.empty());
|
||||
BOOST_ASSERT(unpacked_nodes.size() == unpacked_edges.size() + 1);
|
||||
BOOST_ASSERT(source_node != SPECIAL_NODEID && target_node != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(!unpacked_edges.empty() || source_node == target_node);
|
||||
|
||||
const auto source_node_id = unpacked_nodes.front();
|
||||
const auto target_node_id = unpacked_nodes.back();
|
||||
const bool start_traversed_in_reverse =
|
||||
phantom_node_pair.source_phantom.forward_segment_id.id != source_node_id;
|
||||
phantom_node_pair.source_phantom.forward_segment_id.id != source_node;
|
||||
const bool target_traversed_in_reverse =
|
||||
phantom_node_pair.target_phantom.forward_segment_id.id != target_node_id;
|
||||
phantom_node_pair.target_phantom.forward_segment_id.id != target_node;
|
||||
|
||||
BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id == source_node_id ||
|
||||
phantom_node_pair.source_phantom.reverse_segment_id.id == source_node_id);
|
||||
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node_id ||
|
||||
phantom_node_pair.target_phantom.reverse_segment_id.id == target_node_id);
|
||||
BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id == source_node ||
|
||||
phantom_node_pair.source_phantom.reverse_segment_id.id == source_node);
|
||||
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node ||
|
||||
phantom_node_pair.target_phantom.reverse_segment_id.id == target_node);
|
||||
|
||||
auto node_from = unpacked_nodes.begin(), node_last = std::prev(unpacked_nodes.end());
|
||||
for (auto edge = unpacked_edges.begin(); node_from != node_last; ++node_from, ++edge)
|
||||
for (auto edge_id : unpacked_edges)
|
||||
{
|
||||
const auto &edge_data = facade.GetEdgeData(*edge);
|
||||
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
|
||||
const auto node_id = *node_from; // edge-based graph node index
|
||||
const auto name_index = facade.GetNameIndex(node_id);
|
||||
const auto &edge_data = facade.GetEdgeData(edge_id);
|
||||
const auto turn_id = edge_data.turn_id; // edge-based node ID
|
||||
const auto name_index = facade.GetNameIndexFromEdgeID(turn_id);
|
||||
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
|
||||
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
|
||||
const extractor::TravelMode travel_mode =
|
||||
(unpacked_path.empty() && start_traversed_in_reverse)
|
||||
? phantom_node_pair.source_phantom.backward_travel_mode
|
||||
: facade.GetTravelModeForEdgeID(turn_id);
|
||||
|
||||
const auto geometry_index = facade.GetGeometryIndex(node_id);
|
||||
const auto geometry_index = facade.GetGeometryIndexForEdgeID(turn_id);
|
||||
std::vector<NodeID> id_vector;
|
||||
|
||||
std::vector<EdgeWeight> weight_vector;
|
||||
@@ -180,16 +180,23 @@ void annotatePath(const FacadeT &facade,
|
||||
std::vector<EdgeWeight> weight_vector;
|
||||
std::vector<EdgeWeight> duration_vector;
|
||||
std::vector<DatasourceID> datasource_vector;
|
||||
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
|
||||
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
|
||||
const auto is_local_path = source_geometry_id == target_geometry_id && unpacked_path.empty();
|
||||
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
|
||||
phantom_node_pair.target_phantom.packed_geometry_id) &&
|
||||
unpacked_path.empty();
|
||||
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
id_vector = facade.GetUncompressedReverseGeometry(target_geometry_id);
|
||||
weight_vector = facade.GetUncompressedReverseWeights(target_geometry_id);
|
||||
duration_vector = facade.GetUncompressedReverseDurations(target_geometry_id);
|
||||
datasource_vector = facade.GetUncompressedReverseDatasources(target_geometry_id);
|
||||
id_vector = facade.GetUncompressedReverseGeometry(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
weight_vector = facade.GetUncompressedReverseWeights(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
duration_vector = facade.GetUncompressedReverseDurations(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
datasource_vector = facade.GetUncompressedReverseDatasources(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
if (is_local_path)
|
||||
{
|
||||
@@ -207,10 +214,17 @@ void annotatePath(const FacadeT &facade,
|
||||
}
|
||||
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
|
||||
id_vector = facade.GetUncompressedForwardGeometry(target_geometry_id);
|
||||
weight_vector = facade.GetUncompressedForwardWeights(target_geometry_id);
|
||||
duration_vector = facade.GetUncompressedForwardDurations(target_geometry_id);
|
||||
datasource_vector = facade.GetUncompressedForwardDatasources(target_geometry_id);
|
||||
id_vector = facade.GetUncompressedForwardGeometry(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
weight_vector = facade.GetUncompressedForwardWeights(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
duration_vector = facade.GetUncompressedForwardDurations(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
|
||||
datasource_vector = facade.GetUncompressedForwardDatasources(
|
||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||
}
|
||||
|
||||
// Given the following compressed geometry:
|
||||
@@ -224,19 +238,20 @@ void annotatePath(const FacadeT &facade,
|
||||
(start_index < end_index ? ++segment_idx : --segment_idx))
|
||||
{
|
||||
BOOST_ASSERT(segment_idx < id_vector.size() - 1);
|
||||
BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0);
|
||||
unpacked_path.push_back(
|
||||
PathData{id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
||||
facade.GetNameIndex(target_node_id),
|
||||
weight_vector[segment_idx],
|
||||
duration_vector[segment_idx],
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||
facade.GetTravelMode(target_node_id),
|
||||
INVALID_ENTRY_CLASSID,
|
||||
datasource_vector[segment_idx],
|
||||
util::guidance::TurnBearing(0),
|
||||
util::guidance::TurnBearing(0)});
|
||||
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
|
||||
unpacked_path.push_back(PathData{
|
||||
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
||||
phantom_node_pair.target_phantom.name_id,
|
||||
weight_vector[segment_idx],
|
||||
duration_vector[segment_idx],
|
||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
||||
: phantom_node_pair.target_phantom.forward_travel_mode,
|
||||
INVALID_ENTRY_CLASSID,
|
||||
datasource_vector[segment_idx],
|
||||
util::guidance::TurnBearing(0),
|
||||
util::guidance::TurnBearing(0)});
|
||||
}
|
||||
|
||||
if (unpacked_path.size() > 0)
|
||||
@@ -295,19 +310,17 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algo
|
||||
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
||||
|
||||
double distance = 0;
|
||||
double prev_lat =
|
||||
static_cast<double>(util::toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
double prev_lon =
|
||||
static_cast<double>(util::toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
double prev_lat = static_cast<double>(toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
double prev_lon = static_cast<double>(toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
double prev_cos = std::cos(prev_lat);
|
||||
for (const auto &p : unpacked_path)
|
||||
{
|
||||
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(util::toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
|
||||
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(util::toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
|
||||
static_cast<double>(toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
@@ -323,9 +336,9 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algo
|
||||
}
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(util::toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
static_cast<double>(toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(util::toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
static_cast<double>(toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
|
||||
@@ -299,25 +299,22 @@ void unpackPath(const FacadeT &facade,
|
||||
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
|
||||
BOOST_ASSERT(nodes_number > 0);
|
||||
|
||||
std::vector<NodeID> unpacked_nodes;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
unpacked_nodes.reserve(nodes_number);
|
||||
unpacked_edges.reserve(nodes_number);
|
||||
|
||||
unpacked_nodes.push_back(*packed_path_begin);
|
||||
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
|
||||
if (nodes_number > 1)
|
||||
{
|
||||
unpackPath(facade,
|
||||
packed_path_begin,
|
||||
packed_path_end,
|
||||
[&](std::pair<NodeID, NodeID> &edge, const auto &edge_id) {
|
||||
BOOST_ASSERT(edge.first == unpacked_nodes.back());
|
||||
unpacked_nodes.push_back(edge.second);
|
||||
unpacked_edges.push_back(edge_id);
|
||||
});
|
||||
target_node = *std::prev(packed_path_end);
|
||||
unpacked_edges.reserve(std::distance(packed_path_begin, packed_path_end));
|
||||
unpackPath(
|
||||
facade,
|
||||
packed_path_begin,
|
||||
packed_path_end,
|
||||
[&facade, &unpacked_edges](std::pair<NodeID, NodeID> & /* edge */,
|
||||
const auto &edge_id) { unpacked_edges.push_back(edge_id); });
|
||||
}
|
||||
|
||||
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -180,7 +180,7 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::tuple<EdgeWeight, std::vector<NodeID>, std::vector<EdgeID>>
|
||||
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
|
||||
search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
@@ -192,7 +192,8 @@ search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
{
|
||||
if (forward_heap.Empty() || reverse_heap.Empty())
|
||||
{
|
||||
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
|
||||
return std::make_tuple(
|
||||
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||
}
|
||||
|
||||
const auto &partition = facade.GetMultiLevelPartition();
|
||||
@@ -239,7 +240,8 @@ search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
// No path found for both target nodes?
|
||||
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
|
||||
{
|
||||
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
|
||||
return std::make_tuple(
|
||||
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||
}
|
||||
|
||||
// Get packed path as edges {from node ID, to node ID, edge ID}
|
||||
@@ -263,14 +265,11 @@ search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
current_node = parent_node;
|
||||
parent_node = reverse_heap.GetData(parent_node).parent;
|
||||
}
|
||||
const NodeID target_node = current_node;
|
||||
|
||||
// Unpack path
|
||||
std::vector<NodeID> unpacked_nodes;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
unpacked_nodes.reserve(packed_path.size());
|
||||
unpacked_edges.reserve(packed_path.size());
|
||||
|
||||
unpacked_nodes.push_back(source_node);
|
||||
std::vector<EdgeID> unpacked_path;
|
||||
unpacked_path.reserve(packed_path.size());
|
||||
for (auto const &packed_edge : packed_path)
|
||||
{
|
||||
NodeID source, target;
|
||||
@@ -278,8 +277,7 @@ search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
std::tie(source, target, overlay_edge) = packed_edge;
|
||||
if (!overlay_edge)
|
||||
{ // a base graph edge
|
||||
unpacked_nodes.push_back(target);
|
||||
unpacked_edges.push_back(facade.FindEdge(source, target));
|
||||
unpacked_path.push_back(facade.FindEdge(source, target));
|
||||
}
|
||||
else
|
||||
{ // an overlay graph edge
|
||||
@@ -298,54 +296,62 @@ search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
// TODO: when structured bindings will be allowed change to
|
||||
// auto [subpath_weight, subpath_source, subpath_target, subpath] = ...
|
||||
EdgeWeight subpath_weight;
|
||||
std::vector<NodeID> subpath_nodes;
|
||||
std::vector<EdgeID> subpath_edges;
|
||||
std::tie(subpath_weight, subpath_nodes, subpath_edges) = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!subpath_edges.empty());
|
||||
BOOST_ASSERT(subpath_nodes.size() > 1);
|
||||
BOOST_ASSERT(subpath_nodes.front() == source);
|
||||
BOOST_ASSERT(subpath_nodes.back() == target);
|
||||
unpacked_nodes.insert(
|
||||
unpacked_nodes.end(), std::next(subpath_nodes.begin()), subpath_nodes.end());
|
||||
unpacked_edges.insert(unpacked_edges.end(), subpath_edges.begin(), subpath_edges.end());
|
||||
NodeID subpath_source, subpath_target;
|
||||
std::vector<EdgeID> subpath;
|
||||
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
||||
search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!subpath.empty());
|
||||
BOOST_ASSERT(subpath_source == source);
|
||||
BOOST_ASSERT(subpath_target == target);
|
||||
unpacked_path.insert(unpacked_path.end(), subpath.begin(), subpath.end());
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
||||
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
|
||||
}
|
||||
|
||||
// Alias to be compatible with the CH-based search
|
||||
// TODO reorder parameters
|
||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps for shortest path search
|
||||
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
EdgeWeight &weight,
|
||||
std::vector<NodeID> &unpacked_nodes,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
// TODO: change search calling interface to use unpacked_edges result
|
||||
std::tie(weight, unpacked_nodes, std::ignore) = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
|
||||
if (weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
packed_leg.push_back(source_node);
|
||||
std::transform(unpacked_edges.begin(),
|
||||
unpacked_edges.end(),
|
||||
std::back_inserter(packed_leg),
|
||||
[&facade](const auto edge) { return facade.GetTarget(edge); });
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: refactor CH-related stub to use unpacked_edges
|
||||
template <typename RandomIter, typename FacadeT>
|
||||
void unpackPath(const FacadeT &facade,
|
||||
RandomIter packed_path_begin,
|
||||
@@ -356,24 +362,21 @@ void unpackPath(const FacadeT &facade,
|
||||
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
|
||||
BOOST_ASSERT(nodes_number > 0);
|
||||
|
||||
std::vector<NodeID> unpacked_nodes;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
unpacked_nodes.reserve(nodes_number);
|
||||
unpacked_edges.reserve(nodes_number);
|
||||
|
||||
unpacked_nodes.push_back(*packed_path_begin);
|
||||
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
|
||||
|
||||
if (nodes_number > 1)
|
||||
{
|
||||
util::for_each_pair(
|
||||
packed_path_begin,
|
||||
packed_path_end,
|
||||
[&facade, &unpacked_nodes, &unpacked_edges](const auto from, const auto to) {
|
||||
unpacked_nodes.push_back(to);
|
||||
unpacked_edges.push_back(facade.FindEdge(from, to));
|
||||
});
|
||||
target_node = *std::prev(packed_path_end);
|
||||
util::for_each_pair(packed_path_begin,
|
||||
packed_path_end,
|
||||
[&facade, &unpacked_edges](const auto from, const auto to) {
|
||||
unpacked_edges.push_back(facade.FindEdge(from, to));
|
||||
});
|
||||
}
|
||||
|
||||
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
}
|
||||
|
||||
inline double
|
||||
@@ -392,16 +395,16 @@ getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
std::vector<NodeID> unpacked_nodes;
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
std::tie(weight, unpacked_nodes, unpacked_edges) = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
@@ -409,8 +412,7 @@ getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
}
|
||||
|
||||
std::vector<PathData> unpacked_path;
|
||||
|
||||
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
|
||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
#include "engine/algorithm.hpp"
|
||||
#include "util/query_heap.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
@@ -14,7 +14,8 @@ namespace engine
|
||||
|
||||
// Algorithm-dependent heaps
|
||||
// - CH algorithms use CH heaps
|
||||
// - CoreCH algorithms use CH
|
||||
// - CoreCH algorithms use CoreCH heaps that can be upcasted to CH heaps when CH algorithms reused
|
||||
// by CoreCH at calling ch::routingStep, ch::retrievePackedPathFromSingleHeap and ch::unpackPath
|
||||
// - MLD algorithms use MLD heaps
|
||||
|
||||
template <typename Algorithm> struct SearchEngineData
|
||||
@@ -36,14 +37,14 @@ struct ManyToManyHeapData : HeapData
|
||||
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||
{
|
||||
using QueryHeap = util::
|
||||
QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||
|
||||
using ManyToManyQueryHeap = util::QueryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
ManyToManyHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
using ManyToManyQueryHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
ManyToManyHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
|
||||
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
|
||||
|
||||
@@ -80,11 +81,11 @@ struct MultiLayerDijkstraHeapData
|
||||
|
||||
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
||||
{
|
||||
using QueryHeap = util::QueryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
MultiLayerDijkstraHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
using QueryHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
MultiLayerDijkstraHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
|
||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ class CompressedEdgeContainer
|
||||
struct OnewayCompressedEdge
|
||||
{
|
||||
public:
|
||||
NodeID node_id; // refers to an internal node-based-node
|
||||
SegmentWeight weight; // the weight of the edge leading to this node
|
||||
SegmentDuration duration; // the duration of the edge leading to this node
|
||||
NodeID node_id; // refers to an internal node-based-node
|
||||
EdgeWeight weight; // the weight of the edge leading to this node
|
||||
EdgeWeight duration; // the duration of the edge leading to this node
|
||||
};
|
||||
|
||||
using OnewayEdgeBucket = std::vector<OnewayCompressedEdge>;
|
||||
@@ -35,13 +35,13 @@ class CompressedEdgeContainer
|
||||
const NodeID target_node,
|
||||
const EdgeWeight weight1,
|
||||
const EdgeWeight weight2,
|
||||
const EdgeDuration duration1,
|
||||
const EdgeDuration duration2);
|
||||
const EdgeWeight duration1,
|
||||
const EdgeWeight duration2);
|
||||
|
||||
void AddUncompressedEdge(const EdgeID edge_id,
|
||||
const NodeID target_node,
|
||||
const SegmentWeight weight,
|
||||
const SegmentWeight duration);
|
||||
const EdgeWeight weight,
|
||||
const EdgeWeight duration);
|
||||
|
||||
void InitializeBothwayVector();
|
||||
unsigned ZipEdges(const unsigned f_edge_pos, const unsigned r_edge_pos);
|
||||
@@ -63,12 +63,7 @@ class CompressedEdgeContainer
|
||||
std::unique_ptr<SegmentDataContainer> ToSegmentData();
|
||||
|
||||
private:
|
||||
SegmentWeight ClipWeight(const SegmentWeight weight);
|
||||
SegmentDuration ClipDuration(const SegmentDuration duration);
|
||||
|
||||
int free_list_maximum = 0;
|
||||
std::atomic_size_t clipped_weights{0};
|
||||
std::atomic_size_t clipped_durations{0};
|
||||
|
||||
void IncreaseFreeList();
|
||||
std::vector<OnewayEdgeBucket> m_compressed_oneway_geometries;
|
||||
|
||||
@@ -13,6 +13,23 @@ namespace extractor
|
||||
struct EdgeBasedEdge
|
||||
{
|
||||
public:
|
||||
EdgeBasedEdge();
|
||||
|
||||
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &other);
|
||||
|
||||
EdgeBasedEdge(const NodeID source,
|
||||
const NodeID target,
|
||||
const NodeID edge_id,
|
||||
const EdgeWeight weight,
|
||||
const EdgeWeight duration,
|
||||
const bool forward,
|
||||
const bool backward);
|
||||
|
||||
bool operator<(const EdgeBasedEdge &other) const;
|
||||
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
|
||||
struct EdgeData
|
||||
{
|
||||
EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {}
|
||||
@@ -34,24 +51,7 @@ struct EdgeBasedEdge
|
||||
std::uint32_t backward : 1;
|
||||
|
||||
auto is_unidirectional() const { return !forward || !backward; }
|
||||
};
|
||||
|
||||
EdgeBasedEdge();
|
||||
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &other);
|
||||
EdgeBasedEdge(const NodeID source,
|
||||
const NodeID target,
|
||||
const NodeID edge_id,
|
||||
const EdgeWeight weight,
|
||||
const EdgeWeight duration,
|
||||
const bool forward,
|
||||
const bool backward);
|
||||
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
|
||||
|
||||
bool operator<(const EdgeBasedEdge &other) const;
|
||||
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
EdgeData data;
|
||||
} data;
|
||||
};
|
||||
static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
|
||||
"Size of extractor::EdgeBasedEdge type is "
|
||||
@@ -73,13 +73,6 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
||||
{
|
||||
}
|
||||
|
||||
inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
||||
const NodeID target,
|
||||
const EdgeBasedEdge::EdgeData &data)
|
||||
: source(source), target(target), data{data}
|
||||
{
|
||||
}
|
||||
|
||||
inline bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
|
||||
{
|
||||
const auto unidirectional = data.is_unidirectional();
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/edge_based_node_segment.hpp"
|
||||
#include "extractor/edge_based_node.hpp"
|
||||
#include "extractor/extraction_turn.hpp"
|
||||
#include "extractor/guidance/turn_analysis.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
@@ -53,13 +51,13 @@ namespace lookup
|
||||
#pragma pack(push, 1)
|
||||
struct TurnIndexBlock
|
||||
{
|
||||
NodeID from_id;
|
||||
NodeID via_id;
|
||||
NodeID to_id;
|
||||
OSMNodeID from_id;
|
||||
OSMNodeID via_id;
|
||||
OSMNodeID to_id;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert(std::is_trivial<TurnIndexBlock>::value, "TurnIndexBlock is not trivial");
|
||||
static_assert(sizeof(TurnIndexBlock) == 12, "TurnIndexBlock is not packed correctly");
|
||||
static_assert(sizeof(TurnIndexBlock) == 24, "TurnIndexBlock is not packed correctly");
|
||||
} // ns lookup
|
||||
|
||||
struct NodeBasedGraphToEdgeBasedGraphMappingWriter; // fwd. decl
|
||||
@@ -76,7 +74,7 @@ class EdgeBasedGraphFactory
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::PackedOSMIDs &osm_node_ids,
|
||||
const util::PackedVector<OSMNodeID> &osm_node_ids,
|
||||
ProfileProperties profile_properties,
|
||||
const util::NameTable &name_table,
|
||||
std::vector<std::uint32_t> &turn_lane_offsets,
|
||||
@@ -84,7 +82,7 @@ class EdgeBasedGraphFactory
|
||||
guidance::LaneDescriptionMap &lane_description_map);
|
||||
|
||||
void Run(ScriptingEnvironment &scripting_environment,
|
||||
const std::string &turn_data_filename,
|
||||
const std::string &original_edge_data_filename,
|
||||
const std::string &turn_lane_data_filename,
|
||||
const std::string &turn_weight_penalties_filename,
|
||||
const std::string &turn_duration_penalties_filename,
|
||||
@@ -93,8 +91,7 @@ class EdgeBasedGraphFactory
|
||||
|
||||
// The following get access functions destroy the content in the factory
|
||||
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
|
||||
void GetEdgeBasedNodes(EdgeBasedNodeDataContainer &data_container);
|
||||
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
|
||||
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
||||
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
||||
|
||||
@@ -129,13 +126,12 @@ class EdgeBasedGraphFactory
|
||||
std::vector<EdgeWeight> m_edge_based_node_weights;
|
||||
|
||||
//! list of edge based nodes (compressed segments)
|
||||
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
|
||||
EdgeBasedNodeDataContainer m_edge_based_node_container;
|
||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||
EdgeID m_max_edge_id;
|
||||
|
||||
const std::vector<util::Coordinate> &m_coordinates;
|
||||
const extractor::PackedOSMIDs &m_osm_node_ids;
|
||||
const util::PackedVector<OSMNodeID> &m_osm_node_ids;
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
|
||||
std::shared_ptr<RestrictionMap const> m_restriction_map;
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef EDGE_BASED_NODE_HPP
|
||||
#define EDGE_BASED_NODE_HPP
|
||||
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
/// This is what util::StaticRTree serialized and stores on disk
|
||||
/// It is generated in EdgeBasedGraphFactory.
|
||||
struct EdgeBasedNode
|
||||
{
|
||||
EdgeBasedNode()
|
||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
|
||||
name_id(0), packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
||||
fwd_segment_position(std::numeric_limits<unsigned short>::max()),
|
||||
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
explicit EdgeBasedNode(const SegmentID forward_segment_id_,
|
||||
const SegmentID reverse_segment_id_,
|
||||
NodeID u,
|
||||
NodeID v,
|
||||
unsigned name_id,
|
||||
unsigned packed_geometry_id_,
|
||||
bool is_tiny_component,
|
||||
unsigned component_id,
|
||||
unsigned short fwd_segment_position,
|
||||
TravelMode forward_travel_mode,
|
||||
TravelMode backward_travel_mode)
|
||||
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
|
||||
v(v), name_id(name_id), packed_geometry_id(packed_geometry_id_),
|
||||
component{component_id, is_tiny_component}, fwd_segment_position(fwd_segment_position),
|
||||
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
|
||||
{
|
||||
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
|
||||
}
|
||||
|
||||
SegmentID forward_segment_id; // needed for edge-expanded graph
|
||||
SegmentID reverse_segment_id; // needed for edge-expanded graph
|
||||
NodeID u; // indices into the coordinates array
|
||||
NodeID v; // indices into the coordinates array
|
||||
unsigned name_id; // id of the edge name
|
||||
|
||||
unsigned packed_geometry_id;
|
||||
struct
|
||||
{
|
||||
unsigned id : 31;
|
||||
bool is_tiny : 1;
|
||||
} component;
|
||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||
TravelMode forward_travel_mode : 4;
|
||||
TravelMode backward_travel_mode : 4;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EDGE_BASED_NODE_HPP
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifndef OSRM_EXTRACT_EDGE_BASED_NODE_SEGMENT_HPP
|
||||
#define OSRM_EXTRACT_EDGE_BASED_NODE_SEGMENT_HPP
|
||||
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
/// This is what util::StaticRTree serialized and stores on disk
|
||||
/// It is generated in EdgeBasedGraphFactory.
|
||||
struct EdgeBasedNodeSegment
|
||||
{
|
||||
EdgeBasedNodeSegment()
|
||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
|
||||
fwd_segment_position(std::numeric_limits<unsigned short>::max())
|
||||
{
|
||||
}
|
||||
|
||||
explicit EdgeBasedNodeSegment(const SegmentID forward_segment_id_,
|
||||
const SegmentID reverse_segment_id_,
|
||||
NodeID u,
|
||||
NodeID v,
|
||||
unsigned short fwd_segment_position)
|
||||
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
|
||||
v(v), fwd_segment_position(fwd_segment_position)
|
||||
{
|
||||
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
|
||||
}
|
||||
|
||||
SegmentID forward_segment_id; // edge-based graph node ID in forward direction (u->v)
|
||||
SegmentID reverse_segment_id; // edge-based graph node ID in reverse direction (v->u if exists)
|
||||
NodeID u; // node-based graph node ID of the start node
|
||||
NodeID v; // node-based graph node ID of the target node
|
||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSRM_EXTRACT_EDGE_BASED_NODE_SEGMENT_HPP
|
||||
@@ -40,7 +40,7 @@ class ExtractionContainers
|
||||
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
||||
|
||||
void WriteNodes(storage::io::FileWriter &file_out) const;
|
||||
void WriteRestrictions(const std::string &restrictions_file_name);
|
||||
void WriteRestrictions(const std::string &restrictions_file_name) const;
|
||||
void WriteEdges(storage::io::FileWriter &file_out) const;
|
||||
void WriteCharData(const std::string &file_name);
|
||||
|
||||
@@ -48,7 +48,7 @@ class ExtractionContainers
|
||||
using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
|
||||
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
|
||||
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
|
||||
using RestrictionsVector = std::vector<InputRestrictionContainer>;
|
||||
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
|
||||
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
|
||||
using STXXLNameCharData = stxxl::vector<unsigned char>;
|
||||
using STXXLNameOffsets = stxxl::vector<unsigned>;
|
||||
@@ -59,11 +59,10 @@ class ExtractionContainers
|
||||
STXXLNameCharData name_char_data;
|
||||
STXXLNameOffsets name_offsets;
|
||||
// an adjacency array containing all turn lane masks
|
||||
RestrictionsVector restrictions_list;
|
||||
STXXLRestrictionsVector restrictions_list;
|
||||
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||
std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;
|
||||
unsigned max_internal_node_id;
|
||||
std::vector<TurnRestriction> unconditional_turn_restrictions;
|
||||
|
||||
ExtractionContainers();
|
||||
|
||||
|
||||
@@ -56,27 +56,21 @@ class Extractor
|
||||
private:
|
||||
ExtractorConfig config;
|
||||
|
||||
std::vector<TurnRestriction> ParseOSMData(ScriptingEnvironment &scripting_environment,
|
||||
const unsigned number_of_threads);
|
||||
|
||||
std::pair<std::size_t, EdgeID>
|
||||
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
extractor::PackedOSMIDs &osm_node_ids,
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids,
|
||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file,
|
||||
std::vector<TurnRestriction> &turn_restrictions);
|
||||
const std::string &intersection_class_output_file);
|
||||
void WriteProfileProperties(const std::string &output_path,
|
||||
const ProfileProperties &properties) const;
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
|
||||
const std::vector<EdgeBasedNodeSegment> &input_node_segments,
|
||||
EdgeBasedNodeDataContainer &nodes_container) const;
|
||||
void BuildRTree(std::vector<EdgeBasedNodeSegment> edge_based_node_segments,
|
||||
const util::DeallocatingVector<EdgeBasedEdge> &edges,
|
||||
std::vector<EdgeBasedNode> &nodes) const;
|
||||
void BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
|
||||
std::vector<bool> node_is_startpoint,
|
||||
const std::vector<util::Coordinate> &coordinates);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
@@ -84,7 +78,11 @@ class Extractor
|
||||
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||
std::unordered_set<NodeID> &traffic_lights,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
extractor::PackedOSMIDs &osm_node_ids);
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids);
|
||||
|
||||
void WriteEdgeBasedGraph(const std::string &output_file_filename,
|
||||
const EdgeID max_edge_id,
|
||||
util::DeallocatingVector<EdgeBasedEdge> const &edge_based_edge_list);
|
||||
|
||||
void WriteIntersectionClassificationData(
|
||||
const std::string &output_file_name,
|
||||
|
||||
@@ -65,8 +65,7 @@ struct ExtractorConfig
|
||||
turn_lane_data_file_name = basepath + ".osrm.tld";
|
||||
timestamp_file_name = basepath + ".osrm.timestamp";
|
||||
geometry_output_path = basepath + ".osrm.geometry";
|
||||
node_based_nodes_data_path = basepath + ".osrm.nbg_nodes";
|
||||
edge_based_nodes_data_path = basepath + ".osrm.ebg_nodes";
|
||||
node_output_path = basepath + ".osrm.nodes";
|
||||
edge_output_path = basepath + ".osrm.edges";
|
||||
edge_graph_output_path = basepath + ".osrm.ebg";
|
||||
rtree_nodes_output_path = basepath + ".osrm.ramIndex";
|
||||
@@ -93,9 +92,8 @@ struct ExtractorConfig
|
||||
std::string geometry_output_path;
|
||||
std::string edge_output_path;
|
||||
std::string edge_graph_output_path;
|
||||
std::string node_based_nodes_data_path;
|
||||
std::string edge_based_nodes_data_path;
|
||||
std::string edge_based_node_weights_output_path;
|
||||
std::string node_output_path;
|
||||
std::string rtree_nodes_output_path;
|
||||
std::string rtree_leafs_output_path;
|
||||
std::string profile_properties_output_path;
|
||||
@@ -112,7 +110,6 @@ struct ExtractorConfig
|
||||
std::string turn_penalties_index_path;
|
||||
|
||||
bool use_metadata;
|
||||
bool parse_conditionals;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#ifndef OSRM_EXTRACTOR_FILES_HPP
|
||||
#define OSRM_EXTRACTOR_FILES_HPP
|
||||
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/serialization.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
@@ -20,32 +17,6 @@ namespace extractor
|
||||
namespace files
|
||||
{
|
||||
|
||||
template <typename EdgeBasedEdgeVector>
|
||||
void writeEdgeBasedGraph(const boost::filesystem::path &path,
|
||||
EdgeID const max_edge_id,
|
||||
const EdgeBasedEdgeVector &edge_based_edge_list)
|
||||
{
|
||||
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
||||
|
||||
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
||||
|
||||
writer.WriteElementCount64(max_edge_id);
|
||||
storage::serialization::write(writer, edge_based_edge_list);
|
||||
}
|
||||
|
||||
template <typename EdgeBasedEdgeVector>
|
||||
void readEdgeBasedGraph(const boost::filesystem::path &path,
|
||||
EdgeID &max_edge_id,
|
||||
EdgeBasedEdgeVector &edge_based_edge_list)
|
||||
{
|
||||
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
||||
|
||||
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
||||
|
||||
max_edge_id = reader.ReadElementCount64();
|
||||
storage::serialization::read(reader, edge_based_edge_list);
|
||||
}
|
||||
|
||||
// reads .osrm.nodes
|
||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||
inline void readNodes(const boost::filesystem::path &path,
|
||||
@@ -100,7 +71,7 @@ inline void writeNBGMapping(const boost::filesystem::path &path,
|
||||
// reads .osrm.datasource_names
|
||||
inline void readDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, sources);
|
||||
@@ -109,7 +80,7 @@ inline void readDatasources(const boost::filesystem::path &path, Datasources &so
|
||||
// writes .osrm.datasource_names
|
||||
inline void writeDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, sources);
|
||||
@@ -122,7 +93,7 @@ inline void readSegmentData(const boost::filesystem::path &path, SegmentDataT &s
|
||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, segment_data);
|
||||
@@ -135,7 +106,7 @@ inline void writeSegmentData(const boost::filesystem::path &path, const SegmentD
|
||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, segment_data);
|
||||
@@ -149,7 +120,7 @@ inline void readTurnData(const boost::filesystem::path &path, TurnDataT &turn_da
|
||||
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, turn_data);
|
||||
@@ -163,40 +134,12 @@ inline void writeTurnData(const boost::filesystem::path &path, const TurnDataT &
|
||||
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, turn_data);
|
||||
}
|
||||
|
||||
// reads .osrm.nodes_data
|
||||
template <typename NodeDataT>
|
||||
inline void readNodeData(const boost::filesystem::path &path, NodeDataT &node_data)
|
||||
{
|
||||
static_assert(std::is_same<EdgeBasedNodeDataContainer, NodeDataT>::value ||
|
||||
std::is_same<EdgeBasedNodeDataView, NodeDataT>::value ||
|
||||
std::is_same<EdgeBasedNodeDataExternalContainer, NodeDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, node_data);
|
||||
}
|
||||
|
||||
// writes .osrm.nodes_data
|
||||
template <typename NodeDataT>
|
||||
inline void writeNodeData(const boost::filesystem::path &path, const NodeDataT &node_data)
|
||||
{
|
||||
static_assert(std::is_same<EdgeBasedNodeDataContainer, NodeDataT>::value ||
|
||||
std::is_same<EdgeBasedNodeDataView, NodeDataT>::value ||
|
||||
std::is_same<EdgeBasedNodeDataExternalContainer, NodeDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, node_data);
|
||||
}
|
||||
|
||||
// reads .osrm.tls
|
||||
template <typename OffsetsT, typename MaskT>
|
||||
inline void readTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
@@ -208,7 +151,7 @@ inline void readTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
"");
|
||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, turn_offsets);
|
||||
@@ -226,7 +169,7 @@ inline void writeTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
"");
|
||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, turn_offsets);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "extractor/node_based_edge.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "osrm/coordinate.hpp"
|
||||
#include "util/strong_typedef.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
@@ -19,7 +19,7 @@ struct NodeBasedEdge
|
||||
NodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
EdgeWeight duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
@@ -37,7 +37,7 @@ struct NodeBasedEdge
|
||||
NodeID target; // 32 4
|
||||
NodeID name_id; // 32 4
|
||||
EdgeWeight weight; // 32 4
|
||||
EdgeDuration duration; // 32 4
|
||||
EdgeWeight duration; // 32 4
|
||||
std::uint8_t forward : 1; // 1
|
||||
std::uint8_t backward : 1; // 1
|
||||
std::uint8_t roundabout : 1; // 1
|
||||
@@ -56,7 +56,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
||||
OSMNodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
EdgeWeight duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
@@ -86,7 +86,7 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||
NodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
EdgeWeight duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
@@ -125,7 +125,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
||||
OSMNodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
EdgeWeight duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||
|
||||
#include "extractor/travel_mode.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/permutation.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl;
|
||||
}
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
void read(storage::io::FileReader &reader,
|
||||
detail::EdgeBasedNodeDataContainerImpl<Ownership> &ebn_data);
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
void write(storage::io::FileWriter &writer,
|
||||
const detail::EdgeBasedNodeDataContainerImpl<Ownership> &ebn_data);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
using TravelMode = extractor::TravelMode;
|
||||
|
||||
public:
|
||||
EdgeBasedNodeDataContainerImpl() = default;
|
||||
|
||||
EdgeBasedNodeDataContainerImpl(std::size_t size)
|
||||
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size)
|
||||
{
|
||||
}
|
||||
|
||||
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids,
|
||||
Vector<NameID> name_ids,
|
||||
Vector<ComponentID> component_ids,
|
||||
Vector<TravelMode> travel_modes)
|
||||
: geometry_ids(std::move(geometry_ids)), name_ids(std::move(name_ids)),
|
||||
component_ids(std::move(component_ids)), travel_modes(std::move(travel_modes))
|
||||
{
|
||||
}
|
||||
|
||||
GeometryID GetGeometryID(const NodeID node_id) const { return geometry_ids[node_id]; }
|
||||
|
||||
TravelMode GetTravelMode(const NodeID node_id) const { return travel_modes[node_id]; }
|
||||
|
||||
NameID GetNameID(const NodeID node_id) const { return name_ids[node_id]; }
|
||||
|
||||
ComponentID GetComponentID(const NodeID node_id) const { return component_ids[node_id]; }
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void SetData(NodeID node_id, GeometryID geometry_id, NameID name_id, TravelMode travel_mode)
|
||||
{
|
||||
geometry_ids[node_id] = geometry_id;
|
||||
name_ids[node_id] = name_id;
|
||||
travel_modes[node_id] = travel_mode;
|
||||
}
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void SetComponentID(NodeID node_id, ComponentID component_id)
|
||||
{
|
||||
component_ids[node_id] = component_id;
|
||||
}
|
||||
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
EdgeBasedNodeDataContainerImpl &ebn_data_container);
|
||||
friend void
|
||||
serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const EdgeBasedNodeDataContainerImpl &ebn_data_container);
|
||||
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void Renumber(const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
util::inplacePermutation(geometry_ids.begin(), geometry_ids.end(), permutation);
|
||||
util::inplacePermutation(name_ids.begin(), name_ids.end(), permutation);
|
||||
util::inplacePermutation(component_ids.begin(), component_ids.end(), permutation);
|
||||
util::inplacePermutation(travel_modes.begin(), travel_modes.end(), permutation);
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<GeometryID> geometry_ids;
|
||||
Vector<NameID> name_ids;
|
||||
Vector<ComponentID> component_ids;
|
||||
Vector<TravelMode> travel_modes;
|
||||
};
|
||||
}
|
||||
|
||||
using EdgeBasedNodeDataExternalContainer =
|
||||
detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::External>;
|
||||
using EdgeBasedNodeDataContainer =
|
||||
detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::Container>;
|
||||
using EdgeBasedNodeDataView = detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_PACKED_OSM_IDS_HPP
|
||||
#define OSRM_EXTRACTOR_PACKED_OSM_IDS_HPP
|
||||
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
using PackedOSMIDs = util::detail::PackedVector<OSMNodeID, 33, Ownership>;
|
||||
}
|
||||
|
||||
using PackedOSMIDsView = detail::PackedOSMIDs<storage::Ownership::View>;
|
||||
using PackedOSMIDs = detail::PackedOSMIDs<storage::Ownership::Container>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -47,7 +47,7 @@ class RasterGrid
|
||||
storage::io::FileReader file_reader(filepath, storage::io::FileReader::HasNoFingerprint);
|
||||
|
||||
std::string buffer;
|
||||
buffer.resize(file_reader.GetSize());
|
||||
buffer.resize(file_reader.Size());
|
||||
|
||||
BOOST_ASSERT(buffer.size() > 1);
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef RESTRICTION_HPP
|
||||
#define RESTRICTION_HPP
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/opening_hours.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <limits>
|
||||
@@ -22,8 +20,6 @@ struct TurnRestriction
|
||||
WayOrNode from;
|
||||
WayOrNode to;
|
||||
|
||||
std::vector<util::OpeningHours> condition;
|
||||
|
||||
struct Bits
|
||||
{ // mostly unused
|
||||
Bits()
|
||||
|
||||
@@ -95,7 +95,7 @@ class RestrictionMap
|
||||
return;
|
||||
}
|
||||
|
||||
// find all potential start edges. It is more efficient to get a (small) list
|
||||
// find all potential start edges. It is more efficent to get a (small) list
|
||||
// of potential start edges than iterating over all buckets
|
||||
std::vector<NodeID> predecessors;
|
||||
for (const EdgeID current_edge_id : graph.GetAdjacentEdgeRange(node_u))
|
||||
|
||||
@@ -41,17 +41,14 @@ class ScriptingEnvironment;
|
||||
class RestrictionParser
|
||||
{
|
||||
public:
|
||||
RestrictionParser(bool use_turn_restrictions,
|
||||
bool parse_conditionals,
|
||||
std::vector<std::string> &restrictions);
|
||||
std::vector<InputRestrictionContainer> TryParse(const osmium::Relation &relation) const;
|
||||
RestrictionParser(ScriptingEnvironment &scripting_environment);
|
||||
boost::optional<InputRestrictionContainer> TryParse(const osmium::Relation &relation) const;
|
||||
|
||||
private:
|
||||
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||
|
||||
bool use_turn_restrictions;
|
||||
bool parse_conditionals;
|
||||
std::vector<std::string> restrictions;
|
||||
bool use_turn_restrictions;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
|
||||
#define OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
|
||||
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
@@ -44,8 +43,6 @@ namespace detail
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
template <typename T, std::size_t Bits>
|
||||
using PackedVector = util::detail::PackedVector<T, Bits, Ownership>;
|
||||
|
||||
friend CompressedEdgeContainer;
|
||||
|
||||
@@ -53,17 +50,15 @@ template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
// FIXME We should change the indexing to Edge-Based-Node id
|
||||
using DirectionalGeometryID = std::uint32_t;
|
||||
using SegmentOffset = std::uint32_t;
|
||||
using SegmentWeightVector = PackedVector<SegmentWeight, SEGMENT_WEIGHT_BITS>;
|
||||
using SegmentDurationVector = PackedVector<SegmentDuration, SEGMENT_DURAITON_BITS>;
|
||||
|
||||
SegmentDataContainerImpl() = default;
|
||||
|
||||
SegmentDataContainerImpl(Vector<std::uint32_t> index_,
|
||||
Vector<NodeID> nodes_,
|
||||
SegmentWeightVector fwd_weights_,
|
||||
SegmentWeightVector rev_weights_,
|
||||
SegmentDurationVector fwd_durations_,
|
||||
SegmentDurationVector rev_durations_,
|
||||
Vector<EdgeWeight> fwd_weights_,
|
||||
Vector<EdgeWeight> rev_weights_,
|
||||
Vector<EdgeWeight> fwd_durations_,
|
||||
Vector<EdgeWeight> rev_durations_,
|
||||
Vector<DatasourceID> datasources_)
|
||||
: index(std::move(index_)), nodes(std::move(nodes_)), fwd_weights(std::move(fwd_weights_)),
|
||||
rev_weights(std::move(rev_weights_)), fwd_durations(std::move(fwd_durations_)),
|
||||
@@ -206,10 +201,10 @@ template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
private:
|
||||
Vector<std::uint32_t> index;
|
||||
Vector<NodeID> nodes;
|
||||
SegmentWeightVector fwd_weights;
|
||||
SegmentWeightVector rev_weights;
|
||||
SegmentDurationVector fwd_durations;
|
||||
SegmentDurationVector rev_durations;
|
||||
Vector<EdgeWeight> fwd_weights;
|
||||
Vector<EdgeWeight> rev_weights;
|
||||
Vector<EdgeWeight> fwd_durations;
|
||||
Vector<EdgeWeight> rev_durations;
|
||||
Vector<DatasourceID> datasources;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
|
||||
@@ -20,7 +18,6 @@ namespace extractor
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
// read/write for datasources file
|
||||
inline void read(storage::io::FileReader &reader, Datasources &sources)
|
||||
{
|
||||
reader.ReadInto(sources);
|
||||
@@ -31,17 +28,16 @@ inline void write(storage::io::FileWriter &writer, Datasources &sources)
|
||||
writer.WriteFrom(sources);
|
||||
}
|
||||
|
||||
// read/write for segment data file
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data)
|
||||
{
|
||||
storage::serialization::read(reader, segment_data.index);
|
||||
storage::serialization::read(reader, segment_data.nodes);
|
||||
util::serialization::read(reader, segment_data.fwd_weights);
|
||||
util::serialization::read(reader, segment_data.rev_weights);
|
||||
util::serialization::read(reader, segment_data.fwd_durations);
|
||||
util::serialization::read(reader, segment_data.rev_durations);
|
||||
storage::serialization::read(reader, segment_data.fwd_weights);
|
||||
storage::serialization::read(reader, segment_data.rev_weights);
|
||||
storage::serialization::read(reader, segment_data.fwd_durations);
|
||||
storage::serialization::read(reader, segment_data.rev_durations);
|
||||
storage::serialization::read(reader, segment_data.datasources);
|
||||
}
|
||||
|
||||
@@ -51,20 +47,22 @@ inline void write(storage::io::FileWriter &writer,
|
||||
{
|
||||
storage::serialization::write(writer, segment_data.index);
|
||||
storage::serialization::write(writer, segment_data.nodes);
|
||||
util::serialization::write(writer, segment_data.fwd_weights);
|
||||
util::serialization::write(writer, segment_data.rev_weights);
|
||||
util::serialization::write(writer, segment_data.fwd_durations);
|
||||
util::serialization::write(writer, segment_data.rev_durations);
|
||||
storage::serialization::write(writer, segment_data.fwd_weights);
|
||||
storage::serialization::write(writer, segment_data.rev_weights);
|
||||
storage::serialization::write(writer, segment_data.fwd_durations);
|
||||
storage::serialization::write(writer, segment_data.rev_durations);
|
||||
storage::serialization::write(writer, segment_data.datasources);
|
||||
}
|
||||
|
||||
// read/write for turn data file
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::TurnDataContainerImpl<Ownership> &turn_data_container)
|
||||
{
|
||||
storage::serialization::read(reader, turn_data_container.geometry_ids);
|
||||
storage::serialization::read(reader, turn_data_container.name_ids);
|
||||
storage::serialization::read(reader, turn_data_container.turn_instructions);
|
||||
storage::serialization::read(reader, turn_data_container.lane_data_ids);
|
||||
storage::serialization::read(reader, turn_data_container.travel_modes);
|
||||
storage::serialization::read(reader, turn_data_container.entry_class_ids);
|
||||
storage::serialization::read(reader, turn_data_container.pre_turn_bearings);
|
||||
storage::serialization::read(reader, turn_data_container.post_turn_bearings);
|
||||
@@ -74,77 +72,15 @@ template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::TurnDataContainerImpl<Ownership> &turn_data_container)
|
||||
{
|
||||
storage::serialization::write(writer, turn_data_container.geometry_ids);
|
||||
storage::serialization::write(writer, turn_data_container.name_ids);
|
||||
storage::serialization::write(writer, turn_data_container.turn_instructions);
|
||||
storage::serialization::write(writer, turn_data_container.lane_data_ids);
|
||||
storage::serialization::write(writer, turn_data_container.travel_modes);
|
||||
storage::serialization::write(writer, turn_data_container.entry_class_ids);
|
||||
storage::serialization::write(writer, turn_data_container.pre_turn_bearings);
|
||||
storage::serialization::write(writer, turn_data_container.post_turn_bearings);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
|
||||
{
|
||||
storage::serialization::read(reader, node_data_container.geometry_ids);
|
||||
storage::serialization::read(reader, node_data_container.name_ids);
|
||||
storage::serialization::read(reader, node_data_container.component_ids);
|
||||
storage::serialization::read(reader, node_data_container.travel_modes);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
|
||||
{
|
||||
storage::serialization::write(writer, node_data_container.geometry_ids);
|
||||
storage::serialization::write(writer, node_data_container.name_ids);
|
||||
storage::serialization::write(writer, node_data_container.component_ids);
|
||||
storage::serialization::write(writer, node_data_container.travel_modes);
|
||||
}
|
||||
|
||||
// read/write for conditional turn restrictions file
|
||||
inline void read(storage::io::FileReader &reader, std::vector<TurnRestriction> &restrictions)
|
||||
{
|
||||
auto num_indices = reader.ReadElementCount64();
|
||||
restrictions.reserve(num_indices);
|
||||
TurnRestriction restriction;
|
||||
while (num_indices > 0)
|
||||
{
|
||||
bool is_only;
|
||||
reader.ReadInto(restriction.via);
|
||||
reader.ReadInto(restriction.from);
|
||||
reader.ReadInto(restriction.to);
|
||||
reader.ReadInto(is_only);
|
||||
auto num_conditions = reader.ReadElementCount64();
|
||||
restriction.condition.resize(num_conditions);
|
||||
for (uint64_t i = 0; i < num_conditions; i++)
|
||||
{
|
||||
reader.ReadInto(restriction.condition[i].modifier);
|
||||
storage::serialization::read(reader, restriction.condition[i].times);
|
||||
storage::serialization::read(reader, restriction.condition[i].weekdays);
|
||||
storage::serialization::read(reader, restriction.condition[i].monthdays);
|
||||
}
|
||||
restriction.flags.is_only = is_only;
|
||||
|
||||
restrictions.push_back(std::move(restriction));
|
||||
num_indices--;
|
||||
}
|
||||
}
|
||||
|
||||
inline void write(storage::io::FileWriter &writer, const TurnRestriction &restriction)
|
||||
{
|
||||
writer.WriteOne(restriction.via);
|
||||
writer.WriteOne(restriction.from);
|
||||
writer.WriteOne(restriction.to);
|
||||
writer.WriteOne(restriction.flags.is_only);
|
||||
writer.WriteElementCount64(restriction.condition.size());
|
||||
for (const auto &c : restriction.condition)
|
||||
{
|
||||
writer.WriteOne(c.modifier);
|
||||
storage::serialization::write(writer, c.times);
|
||||
storage::serialization::write(writer, c.weekdays);
|
||||
storage::serialization::write(writer, c.monthdays);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ template <typename GraphT> class TarjanSCC
|
||||
std::stack<NodeID> tarjan_stack;
|
||||
std::vector<TarjanNode> tarjan_node_list(max_node_id);
|
||||
unsigned component_index = 0, size_of_current_component = 0;
|
||||
unsigned large_component_count = 0;
|
||||
unsigned index = 0;
|
||||
std::vector<bool> processing_node_before_recursion(max_node_id, true);
|
||||
for (const NodeID node : util::irange(0u, max_node_id))
|
||||
@@ -147,9 +146,8 @@ template <typename GraphT> class TarjanSCC
|
||||
|
||||
if (size_of_current_component > 1000)
|
||||
{
|
||||
++large_component_count;
|
||||
util::Log(logDEBUG) << "large component [" << component_index
|
||||
<< "]=" << size_of_current_component;
|
||||
util::Log() << "large component [" << component_index
|
||||
<< "]=" << size_of_current_component;
|
||||
}
|
||||
|
||||
++component_index;
|
||||
@@ -160,8 +158,6 @@ template <typename GraphT> class TarjanSCC
|
||||
}
|
||||
|
||||
TIMER_STOP(SCC_RUN);
|
||||
util::Log() << "Found " << component_index << " SCC (" << large_component_count
|
||||
<< " large, " << (component_index - large_component_count) << " small)";
|
||||
util::Log() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s";
|
||||
|
||||
size_one_counter = std::count_if(component_size_vector.begin(),
|
||||
|
||||
@@ -40,20 +40,29 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
||||
public:
|
||||
TurnDataContainerImpl() = default;
|
||||
|
||||
TurnDataContainerImpl(Vector<extractor::guidance::TurnInstruction> turn_instructions,
|
||||
Vector<LaneDataID> lane_data_ids,
|
||||
Vector<EntryClassID> entry_class_ids,
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings,
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings)
|
||||
: turn_instructions(std::move(turn_instructions)), lane_data_ids(std::move(lane_data_ids)),
|
||||
entry_class_ids(std::move(entry_class_ids)),
|
||||
pre_turn_bearings(std::move(pre_turn_bearings)),
|
||||
post_turn_bearings(std::move(post_turn_bearings))
|
||||
TurnDataContainerImpl(Vector<GeometryID> geometry_ids_,
|
||||
Vector<NameID> name_ids_,
|
||||
Vector<extractor::guidance::TurnInstruction> turn_instructions_,
|
||||
Vector<LaneDataID> lane_data_ids_,
|
||||
Vector<extractor::TravelMode> travel_modes_,
|
||||
Vector<EntryClassID> entry_class_ids_,
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings_,
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings_)
|
||||
: geometry_ids(std::move(geometry_ids_)), name_ids(std::move(name_ids_)),
|
||||
turn_instructions(std::move(turn_instructions_)),
|
||||
lane_data_ids(std::move(lane_data_ids_)), travel_modes(std::move(travel_modes_)),
|
||||
entry_class_ids(std::move(entry_class_ids_)),
|
||||
pre_turn_bearings(std::move(pre_turn_bearings_)),
|
||||
post_turn_bearings(std::move(post_turn_bearings_))
|
||||
{
|
||||
}
|
||||
|
||||
GeometryID GetGeometryID(const EdgeID id) const { return geometry_ids[id]; }
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
|
||||
|
||||
extractor::TravelMode GetTravelMode(const EdgeID id) const { return travel_modes[id]; }
|
||||
|
||||
util::guidance::TurnBearing GetPreTurnBearing(const EdgeID id) const
|
||||
{
|
||||
return pre_turn_bearings[id];
|
||||
@@ -68,6 +77,8 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
||||
|
||||
bool HasLaneData(const EdgeID id) const { return INVALID_LANE_DATAID != lane_data_ids[id]; }
|
||||
|
||||
NameID GetNameID(const EdgeID id) const { return name_ids[id]; }
|
||||
|
||||
extractor::guidance::TurnInstruction GetTurnInstruction(const EdgeID id) const
|
||||
{
|
||||
return turn_instructions[id];
|
||||
@@ -75,14 +86,20 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void push_back(extractor::guidance::TurnInstruction turn_instruction,
|
||||
void push_back(GeometryID geometry_id,
|
||||
NameID name_id,
|
||||
extractor::guidance::TurnInstruction turn_instruction,
|
||||
LaneDataID lane_data_id,
|
||||
EntryClassID entry_class_id,
|
||||
extractor::TravelMode travel_mode,
|
||||
util::guidance::TurnBearing pre_turn_bearing,
|
||||
util::guidance::TurnBearing post_turn_bearing)
|
||||
{
|
||||
geometry_ids.push_back(geometry_id);
|
||||
name_ids.push_back(name_id);
|
||||
turn_instructions.push_back(turn_instruction);
|
||||
lane_data_ids.push_back(lane_data_id);
|
||||
travel_modes.push_back(travel_mode);
|
||||
entry_class_ids.push_back(entry_class_id);
|
||||
pre_turn_bearings.push_back(pre_turn_bearing);
|
||||
post_turn_bearings.push_back(post_turn_bearing);
|
||||
@@ -94,8 +111,11 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
||||
const TurnDataContainerImpl &turn_data_container);
|
||||
|
||||
private:
|
||||
Vector<GeometryID> geometry_ids;
|
||||
Vector<NameID> name_ids;
|
||||
Vector<extractor::guidance::TurnInstruction> turn_instructions;
|
||||
Vector<LaneDataID> lane_data_ids;
|
||||
Vector<extractor::TravelMode> travel_modes;
|
||||
Vector<EntryClassID> entry_class_ids;
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings;
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "nodejs/json_v8_renderer.hpp"
|
||||
|
||||
#include "osrm/approach.hpp"
|
||||
#include "osrm/bearing.hpp"
|
||||
#include "osrm/coordinate.hpp"
|
||||
#include "osrm/engine_config.hpp"
|
||||
@@ -76,7 +75,7 @@ inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &r
|
||||
}
|
||||
}
|
||||
|
||||
inline void ParseResult(const osrm::Status & /*result_status*/, const std::string & /*unused*/) {}
|
||||
inline void ParseResult(const osrm::Status &result_status, const std::string & /*unused*/) {}
|
||||
|
||||
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
|
||||
{
|
||||
@@ -298,63 +297,6 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("approaches").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> approaches = obj->Get(Nan::New("approaches").ToLocalChecked());
|
||||
if (approaches.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (!approaches->IsArray())
|
||||
{
|
||||
Nan::ThrowError("Approaches must be an arrays of strings");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto approaches_array = v8::Local<v8::Array>::Cast(approaches);
|
||||
|
||||
if (approaches_array->Length() != params->coordinates.size())
|
||||
{
|
||||
Nan::ThrowError("Approaches array must have the same length as coordinates array");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < approaches_array->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> approach_raw = approaches_array->Get(i);
|
||||
if (approach_raw.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (approach_raw->IsNull())
|
||||
{
|
||||
params->approaches.emplace_back();
|
||||
}
|
||||
else if (approach_raw->IsString())
|
||||
{
|
||||
const Nan::Utf8String approach_utf8str(approach_raw);
|
||||
std::string approach_str{*approach_utf8str,
|
||||
*approach_utf8str + approach_utf8str.length()};
|
||||
if (approach_str == "curb")
|
||||
{
|
||||
params->approaches.push_back(osrm::Approach::CURB);
|
||||
}
|
||||
else if (approach_str == "unrestricted")
|
||||
{
|
||||
params->approaches.push_back(osrm::Approach::UNRESTRICTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
Nan::ThrowError("'approaches' param must be one of [curb, unrestricted]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Nan::ThrowError("Approach must be a string: [curb, unrestricted] or null");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("bearings").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> bearings = obj->Get(Nan::New("bearings").ToLocalChecked());
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2016, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef OSRM_APPROACH_HPP
|
||||
#define OSRM_APPROACH_HPP
|
||||
|
||||
#include "engine/approach.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
using engine::Approach;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -33,12 +33,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
namespace osrm
|
||||
{
|
||||
using util::Coordinate;
|
||||
using util::toFixed;
|
||||
using util::toFloating;
|
||||
using util::FixedLatitude;
|
||||
using util::FixedLongitude;
|
||||
using util::FloatLatitude;
|
||||
using util::FloatLongitude;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,15 +21,9 @@ namespace partition
|
||||
|
||||
struct EdgeBasedGraphEdgeData : extractor::EdgeBasedEdge::EdgeData
|
||||
{
|
||||
using Base = extractor::EdgeBasedEdge::EdgeData;
|
||||
using Base::Base;
|
||||
// We need to write out the full edge based graph again.
|
||||
|
||||
EdgeBasedGraphEdgeData(const EdgeBasedGraphEdgeData &) = default;
|
||||
EdgeBasedGraphEdgeData(EdgeBasedGraphEdgeData &&) = default;
|
||||
EdgeBasedGraphEdgeData &operator=(const EdgeBasedGraphEdgeData &) = default;
|
||||
EdgeBasedGraphEdgeData &operator=(EdgeBasedGraphEdgeData &&) = default;
|
||||
EdgeBasedGraphEdgeData(const Base &base) : Base(base) {}
|
||||
EdgeBasedGraphEdgeData() : Base() {}
|
||||
// TODO: in case we want to modify the graph we need to store a boundary_arc flag here
|
||||
};
|
||||
|
||||
struct DynamicEdgeBasedGraph : util::DynamicGraph<EdgeBasedGraphEdgeData>
|
||||
|
||||
@@ -4,15 +4,11 @@
|
||||
#include "partition/edge_based_graph.hpp"
|
||||
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/files.hpp"
|
||||
#include "storage/io.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/dynamic_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <tbb/parallel_reduce.h>
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -60,137 +56,124 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
|
||||
template <typename OutputEdgeT>
|
||||
std::vector<OutputEdgeT> prepareEdgesForUsageInGraph(std::vector<extractor::EdgeBasedEdge> edges)
|
||||
{
|
||||
// sort into blocks of edges with same source + target
|
||||
// the we partition by the forward flag to sort all edges with a forward direction first.
|
||||
// the we sort by weight to ensure the first forward edge is the smallest forward edge
|
||||
std::sort(begin(edges), end(edges), [](const auto &lhs, const auto &rhs) {
|
||||
return std::tie(lhs.source, lhs.target, rhs.data.forward, lhs.data.weight) <
|
||||
std::tie(rhs.source, rhs.target, lhs.data.forward, rhs.data.weight);
|
||||
});
|
||||
std::sort(begin(edges), end(edges));
|
||||
|
||||
std::vector<OutputEdgeT> output_edges;
|
||||
output_edges.reserve(edges.size());
|
||||
std::vector<OutputEdgeT> graph_edges;
|
||||
graph_edges.reserve(edges.size());
|
||||
|
||||
for (auto begin_interval = edges.begin(); begin_interval != edges.end();)
|
||||
for (NodeID i = 0; i < edges.size();)
|
||||
{
|
||||
const NodeID source = begin_interval->source;
|
||||
const NodeID target = begin_interval->target;
|
||||
|
||||
auto end_interval =
|
||||
std::find_if_not(begin_interval, edges.end(), [source, target](const auto &edge) {
|
||||
return std::tie(edge.source, edge.target) == std::tie(source, target);
|
||||
});
|
||||
BOOST_ASSERT(begin_interval != end_interval);
|
||||
const NodeID source = edges[i].source;
|
||||
const NodeID target = edges[i].target;
|
||||
|
||||
// remove eigenloops
|
||||
if (source == target)
|
||||
{
|
||||
begin_interval = end_interval;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT_MSG(begin_interval->data.forward != begin_interval->data.backward,
|
||||
"The forward and backward flag need to be mutally exclusive");
|
||||
OutputEdgeT forward_edge;
|
||||
OutputEdgeT reverse_edge;
|
||||
forward_edge.source = reverse_edge.source = source;
|
||||
forward_edge.target = reverse_edge.target = target;
|
||||
forward_edge.data.turn_id = reverse_edge.data.turn_id = edges[i].data.turn_id;
|
||||
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
||||
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION_INT_30;
|
||||
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||
|
||||
// find smallest backward edge and check if we can merge
|
||||
auto first_backward = std::find_if(
|
||||
begin_interval, end_interval, [](const auto &edge) { return edge.data.backward; });
|
||||
|
||||
// thanks to the sorting we know this is the smallest backward edge
|
||||
// and there is no forward edge
|
||||
if (begin_interval == first_backward)
|
||||
// remove parallel edges
|
||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||
{
|
||||
output_edges.push_back(OutputEdgeT{source, target, first_backward->data});
|
||||
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;
|
||||
}
|
||||
// only a forward edge, thanks to the sorting this is the smallest
|
||||
else if (first_backward == end_interval)
|
||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||
if (forward_edge.data.weight == reverse_edge.data.weight)
|
||||
{
|
||||
output_edges.push_back(OutputEdgeT{source, target, begin_interval->data});
|
||||
if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
forward_edge.data.backward = true;
|
||||
graph_edges.push_back(forward_edge);
|
||||
}
|
||||
}
|
||||
// we have both a forward and a backward edge, we need to evaluate
|
||||
// if we can merge them
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(begin_interval->data.forward);
|
||||
BOOST_ASSERT(first_backward->data.backward);
|
||||
BOOST_ASSERT(first_backward != end_interval);
|
||||
|
||||
// same weight, so we can just merge them
|
||||
if (begin_interval->data.weight == first_backward->data.weight)
|
||||
{ // insert seperate edges
|
||||
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
OutputEdgeT merged{source, target, begin_interval->data};
|
||||
merged.data.backward = true;
|
||||
output_edges.push_back(std::move(merged));
|
||||
graph_edges.push_back(forward_edge);
|
||||
}
|
||||
// we need to insert separate forward and reverse edges
|
||||
else
|
||||
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
output_edges.push_back(OutputEdgeT{source, target, begin_interval->data});
|
||||
output_edges.push_back(OutputEdgeT{source, target, first_backward->data});
|
||||
graph_edges.push_back(reverse_edge);
|
||||
}
|
||||
}
|
||||
|
||||
begin_interval = end_interval;
|
||||
}
|
||||
|
||||
return output_edges;
|
||||
return graph_edges;
|
||||
}
|
||||
|
||||
std::vector<extractor::EdgeBasedEdge> graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
|
||||
struct EdgeBasedGraphReader
|
||||
{
|
||||
auto range = tbb::blocked_range<NodeID>(0, edge_based_graph.GetNumberOfNodes());
|
||||
auto max_turn_id =
|
||||
tbb::parallel_reduce(range,
|
||||
NodeID{0},
|
||||
[&edge_based_graph](const auto range, NodeID initial) {
|
||||
NodeID max_turn_id = initial;
|
||||
for (auto node = range.begin(); node < range.end(); ++node)
|
||||
{
|
||||
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const auto &data = edge_based_graph.GetEdgeData(edge);
|
||||
max_turn_id = std::max(max_turn_id, data.turn_id);
|
||||
}
|
||||
}
|
||||
return max_turn_id;
|
||||
},
|
||||
[](const NodeID lhs, const NodeID rhs) { return std::max(lhs, rhs); });
|
||||
EdgeBasedGraphReader(storage::io::FileReader &reader)
|
||||
{
|
||||
// Reads: | Fingerprint | #e | max_eid | edges |
|
||||
// - uint64: number of edges
|
||||
// - EdgeID: max edge id
|
||||
// - extractor::EdgeBasedEdge edges
|
||||
//
|
||||
// Gets written in Extractor::WriteEdgeBasedGraph
|
||||
|
||||
std::vector<extractor::EdgeBasedEdge> edges(max_turn_id + 1);
|
||||
tbb::parallel_for(range, [&](const auto range) {
|
||||
for (auto node = range.begin(); node < range.end(); ++node)
|
||||
{
|
||||
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const auto &data = edge_based_graph.GetEdgeData(edge);
|
||||
// we only need to save the forward edges, since the read method will
|
||||
// convert from forward to bi-directional edges again
|
||||
if (data.forward)
|
||||
{
|
||||
auto target = edge_based_graph.GetTarget(edge);
|
||||
BOOST_ASSERT(data.turn_id <= max_turn_id);
|
||||
edges[data.turn_id] = extractor::EdgeBasedEdge{node, target, data};
|
||||
// only save the forward edge
|
||||
edges[data.turn_id].data.forward = true;
|
||||
edges[data.turn_id].data.backward = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const auto num_edges = reader.ReadElementCount64();
|
||||
const auto max_edge_id = reader.ReadOne<EdgeID>();
|
||||
|
||||
return edges;
|
||||
}
|
||||
num_nodes = max_edge_id + 1;
|
||||
|
||||
inline DynamicEdgeBasedGraph LoadEdgeBasedGraph(const boost::filesystem::path &path)
|
||||
{
|
||||
EdgeID max_node_id;
|
||||
edges.resize(num_edges);
|
||||
reader.ReadInto(edges);
|
||||
}
|
||||
|
||||
// FIXME: wrapped in unique_ptr since dynamic_graph is not move-able
|
||||
|
||||
std::unique_ptr<DynamicEdgeBasedGraph> BuildEdgeBasedGraph()
|
||||
{
|
||||
// FIXME: The following is a rough adaption from:
|
||||
// - adaptToContractorInput
|
||||
// - GraphContractor::GraphContractor
|
||||
// and should really be abstracted over.
|
||||
// FIXME: edges passed as a const reference, can be changed pass-by-value if can be moved
|
||||
|
||||
auto directed = splitBidirectionalEdges(edges);
|
||||
auto tidied = prepareEdgesForUsageInGraph<DynamicEdgeBasedGraphEdge>(std::move(directed));
|
||||
|
||||
return std::make_unique<DynamicEdgeBasedGraph>(num_nodes, std::move(tidied));
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<extractor::EdgeBasedEdge> edges;
|
||||
extractor::files::readEdgeBasedGraph(path, max_node_id, edges);
|
||||
std::size_t num_nodes;
|
||||
};
|
||||
|
||||
auto directed = splitBidirectionalEdges(edges);
|
||||
auto tidied = prepareEdgesForUsageInGraph<DynamicEdgeBasedGraphEdge>(std::move(directed));
|
||||
inline std::unique_ptr<DynamicEdgeBasedGraph> LoadEdgeBasedGraph(const std::string &path)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader(path, fingerprint);
|
||||
|
||||
return DynamicEdgeBasedGraph(max_node_id + 1, std::move(tidied));
|
||||
EdgeBasedGraphReader builder{reader};
|
||||
|
||||
return builder.BuildEdgeBasedGraph();
|
||||
}
|
||||
|
||||
} // ns partition
|
||||
|
||||
@@ -38,11 +38,9 @@ struct PartitionConfig
|
||||
edge_based_graph_path = basepath + ".osrm.ebg";
|
||||
compressed_node_based_graph_path = basepath + ".osrm.cnbg";
|
||||
cnbg_ebg_mapping_path = basepath + ".osrm.cnbg_to_ebg";
|
||||
file_index_path = basepath + ".osrm.fileIndex";
|
||||
partition_path = basepath + ".osrm.partition";
|
||||
storage_path = basepath + ".osrm.cells";
|
||||
node_data_path = basepath + ".osrm.ebg_nodes";
|
||||
hsgr_path = basepath + ".osrm.hsgr";
|
||||
mld_partition_path = basepath + ".osrm.partition";
|
||||
mld_storage_path = basepath + ".osrm.cells";
|
||||
}
|
||||
|
||||
// might be changed to the node based graph at some point
|
||||
@@ -51,10 +49,8 @@ struct PartitionConfig
|
||||
boost::filesystem::path compressed_node_based_graph_path;
|
||||
boost::filesystem::path cnbg_ebg_mapping_path;
|
||||
boost::filesystem::path partition_path;
|
||||
boost::filesystem::path file_index_path;
|
||||
boost::filesystem::path storage_path;
|
||||
boost::filesystem::path node_data_path;
|
||||
boost::filesystem::path hsgr_path;
|
||||
boost::filesystem::path mld_partition_path;
|
||||
boost::filesystem::path mld_storage_path;
|
||||
|
||||
unsigned requested_num_threads;
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef OSRM_PARTITION_RENUMBER_HPP
|
||||
#define OSRM_PARTITION_RENUMBER_HPP
|
||||
|
||||
#include "extractor/edge_based_node_segment.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
|
||||
#include "partition/bisection_to_partition.hpp"
|
||||
#include "partition/edge_based_graph.hpp"
|
||||
|
||||
#include "util/dynamic_graph.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
std::vector<std::uint32_t> makePermutation(const DynamicEdgeBasedGraph &graph,
|
||||
const std::vector<Partition> &partitions);
|
||||
|
||||
template <typename EdgeDataT>
|
||||
inline void renumber(util::DynamicGraph<EdgeDataT> &graph,
|
||||
const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
// dynamic graph has own specilization
|
||||
graph.Renumber(permutation);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT>
|
||||
inline void renumber(util::StaticGraph<EdgeDataT> &graph,
|
||||
const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
// static graph has own specilization
|
||||
graph.Renumber(permutation);
|
||||
}
|
||||
|
||||
inline void renumber(extractor::EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
node_data_container.Renumber(permutation);
|
||||
}
|
||||
|
||||
inline void renumber(std::vector<Partition> &partitions,
|
||||
const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
for (auto &partition : partitions)
|
||||
{
|
||||
util::inplacePermutation(partition.begin(), partition.end(), permutation);
|
||||
}
|
||||
}
|
||||
|
||||
inline void renumber(util::vector_view<extractor::EdgeBasedNodeSegment> &segments,
|
||||
const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
for (auto &segment : segments)
|
||||
{
|
||||
BOOST_ASSERT(segment.forward_segment_id.enabled);
|
||||
segment.forward_segment_id.id = permutation[segment.forward_segment_id.id];
|
||||
if (segment.reverse_segment_id.enabled)
|
||||
segment.reverse_segment_id.id = permutation[segment.reverse_segment_id.id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -111,15 +111,15 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::_1,
|
||||
qi::_2)];
|
||||
|
||||
location_rule = (double_ > qi::lit(',') >
|
||||
double_)[qi::_val = ph::bind(
|
||||
[](double lon, double lat) {
|
||||
return util::Coordinate(
|
||||
util::toFixed(util::UnsafeFloatLongitude{lon}),
|
||||
util::toFixed(util::UnsafeFloatLatitude{lat}));
|
||||
},
|
||||
qi::_1,
|
||||
qi::_2)];
|
||||
location_rule =
|
||||
(double_ > qi::lit(',') >
|
||||
double_)[qi::_val = ph::bind(
|
||||
[](double lon, double lat) {
|
||||
return util::Coordinate(util::toFixed(util::FloatLongitude{lon}),
|
||||
util::toFixed(util::FloatLatitude{lat}));
|
||||
},
|
||||
qi::_1,
|
||||
qi::_2)];
|
||||
|
||||
polyline_rule = qi::as_string[qi::lit("polyline(") > +polyline_chars > ')']
|
||||
[qi::_val = ph::bind(
|
||||
@@ -149,16 +149,10 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::lit("bearings=") >
|
||||
(-(qi::short_ > ',' > qi::short_))[ph::bind(add_bearing, qi::_r1, qi::_1)] % ';';
|
||||
|
||||
approach_type.add("unrestricted", engine::Approach::UNRESTRICTED)("curb",
|
||||
engine::Approach::CURB);
|
||||
approach_rule = qi::lit("approaches=") >
|
||||
(-approach_type %
|
||||
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
||||
|
||||
base_rule = radiuses_rule(qi::_r1) //
|
||||
| hints_rule(qi::_r1) //
|
||||
| bearings_rule(qi::_r1) //
|
||||
| generate_hints_rule(qi::_r1) | approach_rule(qi::_r1);
|
||||
| generate_hints_rule(qi::_r1);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -171,7 +165,6 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::rule<Iterator, Signature> hints_rule;
|
||||
|
||||
qi::rule<Iterator, Signature> generate_hints_rule;
|
||||
qi::rule<Iterator, Signature> approach_rule;
|
||||
|
||||
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
|
||||
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
|
||||
@@ -181,8 +174,6 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::rule<Iterator, std::string()> polyline_chars;
|
||||
qi::rule<Iterator, double()> unlimited_rule;
|
||||
qi::real_parser<double, json_policy> double_;
|
||||
|
||||
qi::symbols<char, engine::Approach> approach_type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+17
-15
@@ -23,6 +23,10 @@ namespace io
|
||||
|
||||
class FileReader
|
||||
{
|
||||
private:
|
||||
const boost::filesystem::path filepath;
|
||||
boost::filesystem::ifstream input_stream;
|
||||
|
||||
public:
|
||||
class LineWrapper : public std::string
|
||||
{
|
||||
@@ -46,7 +50,7 @@ class FileReader
|
||||
}
|
||||
|
||||
FileReader(const boost::filesystem::path &filepath_, const FingerprintFlag flag)
|
||||
: filepath(filepath_), fingerprint(flag)
|
||||
: filepath(filepath_)
|
||||
{
|
||||
input_stream.open(filepath, std::ios::binary);
|
||||
if (!input_stream)
|
||||
@@ -71,15 +75,7 @@ class FileReader
|
||||
|
||||
// restore the current position
|
||||
input_stream.seekg(positon, std::ios::beg);
|
||||
|
||||
if (fingerprint == FingerprintFlag::VerifyFingerprint)
|
||||
{
|
||||
return std::size_t(file_size) - sizeof(util::FingerPrint);
|
||||
}
|
||||
else
|
||||
{
|
||||
return file_size;
|
||||
}
|
||||
return file_size;
|
||||
}
|
||||
|
||||
/* Read count objects of type T into pointer dest */
|
||||
@@ -129,6 +125,7 @@ class FileReader
|
||||
|
||||
/*******************************************/
|
||||
|
||||
std::uint32_t ReadElementCount32() { return ReadOne<std::uint32_t>(); }
|
||||
std::uint64_t ReadElementCount64() { return ReadOne<std::uint64_t>(); }
|
||||
|
||||
template <typename T> std::size_t ReadVectorSize()
|
||||
@@ -167,10 +164,14 @@ class FileReader
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const boost::filesystem::path filepath;
|
||||
boost::filesystem::ifstream input_stream;
|
||||
FingerprintFlag fingerprint;
|
||||
std::size_t Size()
|
||||
{
|
||||
auto current_pos = input_stream.tellg();
|
||||
input_stream.seekg(0, input_stream.end);
|
||||
auto length = input_stream.tellg();
|
||||
input_stream.seekg(current_pos, input_stream.beg);
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
class FileWriter
|
||||
@@ -227,8 +228,9 @@ class FileWriter
|
||||
|
||||
template <typename T> void WriteFrom(const T &src) { WriteFrom(&src, 1); }
|
||||
|
||||
template <typename T> void WriteOne(const T &tmp) { WriteFrom(tmp); }
|
||||
template <typename T> void WriteOne(const T tmp) { WriteFrom(tmp); }
|
||||
|
||||
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
||||
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
||||
|
||||
void WriteFingerprint()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef OSRM_STORAGE_SERIALIZATION_HPP
|
||||
#define OSRM_STORAGE_SERIALIZATION_HPP
|
||||
|
||||
#include "util/deallocating_vector.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
@@ -15,49 +14,6 @@ namespace storage
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
/* All vector formats here use the same on-disk format.
|
||||
* This is important because we want to be able to write from a vector
|
||||
* of one kind, but read it into a vector of another kind.
|
||||
*
|
||||
* All vector types with this guarantee should be placed in this file.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
inline void read(storage::io::FileReader &reader, util::DeallocatingVector<T> &vec)
|
||||
{
|
||||
vec.current_size = reader.ReadElementCount64(vec.current_size);
|
||||
std::size_t num_blocks =
|
||||
std::ceil(vec.current_size / util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK);
|
||||
vec.bucket_list.resize(num_blocks);
|
||||
// Read all but the last block which can be partital
|
||||
for (auto bucket_index : util::irange<std::size_t>(0, num_blocks - 1))
|
||||
{
|
||||
vec.bucket_list[bucket_index] = new T[util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK];
|
||||
reader.ReadInto(vec.bucket_list[bucket_index],
|
||||
util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK);
|
||||
}
|
||||
std::size_t last_block_size =
|
||||
vec.current_size % util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK;
|
||||
vec.bucket_list.back() = new T[util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK];
|
||||
reader.ReadInto(vec.bucket_list.back(), last_block_size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void write(storage::io::FileWriter &writer, const util::DeallocatingVector<T> &vec)
|
||||
{
|
||||
writer.WriteElementCount64(vec.current_size);
|
||||
// Write all but the last block which can be partially filled
|
||||
for (auto bucket_index : util::irange<std::size_t>(0, vec.bucket_list.size() - 1))
|
||||
{
|
||||
writer.WriteFrom(vec.bucket_list[bucket_index],
|
||||
util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK);
|
||||
}
|
||||
std::size_t last_block_size =
|
||||
vec.current_size % util::DeallocatingVector<T>::ELEMENTS_PER_BLOCK;
|
||||
writer.WriteFrom(vec.bucket_list.back(), last_block_size);
|
||||
}
|
||||
|
||||
template <typename T> inline void read(storage::io::FileReader &reader, stxxl::vector<T> &vec)
|
||||
{
|
||||
auto size = reader.ReadOne<std::uint64_t>();
|
||||
|
||||
@@ -19,18 +19,16 @@ namespace storage
|
||||
const constexpr char CANARY[4] = {'O', 'S', 'R', 'M'};
|
||||
|
||||
const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
|
||||
"GEOMETRY_ID_LIST",
|
||||
"NAME_ID_LIST",
|
||||
"COMPONENT_ID_LIST",
|
||||
"TRAVEL_MODE_LIST",
|
||||
"VIA_NODE_LIST",
|
||||
"CH_GRAPH_NODE_LIST",
|
||||
"CH_GRAPH_EDGE_LIST",
|
||||
"COORDINATE_LIST",
|
||||
"OSM_NODE_ID_LIST",
|
||||
"TURN_INSTRUCTION",
|
||||
"TRAVEL_MODE",
|
||||
"ENTRY_CLASSID",
|
||||
"R_SEARCH_TREE",
|
||||
"R_SEARCH_TREE_LEVELS",
|
||||
"GEOMETRIES_INDEX",
|
||||
"GEOMETRIES_NODE_LIST",
|
||||
"GEOMETRIES_FWD_WEIGHT_LIST",
|
||||
@@ -74,18 +72,16 @@ struct DataLayout
|
||||
enum BlockID
|
||||
{
|
||||
NAME_CHAR_DATA = 0,
|
||||
GEOMETRY_ID_LIST,
|
||||
NAME_ID_LIST,
|
||||
COMPONENT_ID_LIST,
|
||||
TRAVEL_MODE_LIST,
|
||||
VIA_NODE_LIST,
|
||||
CH_GRAPH_NODE_LIST,
|
||||
CH_GRAPH_EDGE_LIST,
|
||||
COORDINATE_LIST,
|
||||
OSM_NODE_ID_LIST,
|
||||
TURN_INSTRUCTION,
|
||||
TRAVEL_MODE,
|
||||
ENTRY_CLASSID,
|
||||
R_SEARCH_TREE,
|
||||
R_SEARCH_TREE_LEVELS,
|
||||
GEOMETRIES_INDEX,
|
||||
GEOMETRIES_NODE_LIST,
|
||||
GEOMETRIES_FWD_WEIGHT_LIST,
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
|
||||
#if defined(__linux__)
|
||||
// See issue #3911, boost interprocess is broken with a glibc > 2.25
|
||||
// #define USE_BOOST_INTERPROCESS_CONDITION 1
|
||||
#define USE_BOOST_INTERPROCESS_CONDITION 1
|
||||
#endif
|
||||
|
||||
namespace osrm
|
||||
|
||||
@@ -55,8 +55,7 @@ struct StorageConfig final
|
||||
boost::filesystem::path ram_index_path;
|
||||
boost::filesystem::path file_index_path;
|
||||
boost::filesystem::path hsgr_data_path;
|
||||
boost::filesystem::path node_based_nodes_data_path;
|
||||
boost::filesystem::path edge_based_nodes_data_path;
|
||||
boost::filesystem::path nodes_data_path;
|
||||
boost::filesystem::path edges_data_path;
|
||||
boost::filesystem::path core_data_path;
|
||||
boost::filesystem::path geometries_path;
|
||||
|
||||
@@ -63,9 +63,10 @@ struct Turn final
|
||||
: from(from), via(via), to(to)
|
||||
{
|
||||
}
|
||||
Turn(const OSMNodeID &from_id, const OSMNodeID &via_id, const OSMNodeID &to_id)
|
||||
: from(static_cast<std::uint64_t>(from_id)), via(static_cast<std::uint64_t>(via_id)),
|
||||
to(static_cast<std::uint64_t>(to_id))
|
||||
template <typename Other>
|
||||
Turn(const Other &turn)
|
||||
: from(static_cast<std::uint64_t>(turn.from_id)),
|
||||
via(static_cast<std::uint64_t>(turn.via_id)), to(static_cast<std::uint64_t>(turn.to_id))
|
||||
{
|
||||
}
|
||||
bool operator<(const Turn &rhs) const
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
|
||||
@@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
namespace osrm
|
||||
@@ -47,14 +46,12 @@ struct UpdaterConfig final
|
||||
turn_weight_penalties_path = osrm_input_path.string() + ".turn_weight_penalties";
|
||||
turn_duration_penalties_path = osrm_input_path.string() + ".turn_duration_penalties";
|
||||
turn_penalties_index_path = osrm_input_path.string() + ".turn_penalties_index";
|
||||
node_based_nodes_data_path = osrm_input_path.string() + ".nbg_nodes";
|
||||
edge_based_nodes_data_path = osrm_input_path.string() + ".ebg_nodes";
|
||||
node_based_graph_path = osrm_input_path.string() + ".nodes";
|
||||
edge_data_path = osrm_input_path.string() + ".edges";
|
||||
geometry_path = osrm_input_path.string() + ".geometry";
|
||||
rtree_leaf_path = osrm_input_path.string() + ".fileIndex";
|
||||
datasource_names_path = osrm_input_path.string() + ".datasource_names";
|
||||
profile_properties_path = osrm_input_path.string() + ".properties";
|
||||
turn_restrictions_path = osrm_input_path.string() + ".restrictions";
|
||||
}
|
||||
|
||||
boost::filesystem::path osrm_input_path;
|
||||
@@ -64,21 +61,17 @@ struct UpdaterConfig final
|
||||
std::string turn_weight_penalties_path;
|
||||
std::string turn_duration_penalties_path;
|
||||
std::string turn_penalties_index_path;
|
||||
std::string node_based_nodes_data_path;
|
||||
std::string edge_based_nodes_data_path;
|
||||
std::string node_based_graph_path;
|
||||
std::string edge_data_path;
|
||||
std::string geometry_path;
|
||||
std::string rtree_leaf_path;
|
||||
|
||||
double log_edge_updates_factor;
|
||||
std::time_t valid_now;
|
||||
|
||||
std::vector<std::string> segment_speed_lookup_paths;
|
||||
std::vector<std::string> turn_penalty_lookup_paths;
|
||||
std::string datasource_names_path;
|
||||
std::string profile_properties_path;
|
||||
std::string turn_restrictions_path;
|
||||
std::string tz_file_path;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2016, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef OSRM_UTIL_ALIAS_HPP
|
||||
#define OSRM_UTIL_ALIAS_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
template <typename From, typename Tag> struct Alias;
|
||||
template <typename From, typename Tag>
|
||||
inline std::ostream &operator<<(std::ostream &stream, const Alias<From, Tag> &inst);
|
||||
|
||||
template <typename From, typename Tag> struct Alias final
|
||||
{
|
||||
using value_type = From;
|
||||
static_assert(std::is_arithmetic<From>::value, "Needs to be based on an arithmetic type");
|
||||
|
||||
From __value;
|
||||
friend std::ostream &operator<<<From, Tag>(std::ostream &stream, const Alias &inst);
|
||||
|
||||
explicit operator From &() { return __value; }
|
||||
explicit operator From() const { return __value; }
|
||||
inline Alias operator+(const Alias rhs_) const
|
||||
{
|
||||
return Alias{__value + static_cast<const From>(rhs_)};
|
||||
}
|
||||
inline Alias operator-(const Alias rhs_) const
|
||||
{
|
||||
return Alias{__value - static_cast<const From>(rhs_)};
|
||||
}
|
||||
inline Alias operator*(const Alias rhs_) const
|
||||
{
|
||||
return Alias{__value * static_cast<const From>(rhs_)};
|
||||
}
|
||||
inline Alias operator*(const double rhs_) const { return Alias{__value * rhs_}; }
|
||||
inline Alias operator/(const Alias rhs_) const
|
||||
{
|
||||
return Alias{__value / static_cast<const From>(rhs_)};
|
||||
}
|
||||
inline Alias operator/(const double rhs_) const { return Alias{__value / rhs_}; }
|
||||
inline Alias operator|(const Alias rhs_) const
|
||||
{
|
||||
return Alias{__value | static_cast<const From>(rhs_)};
|
||||
}
|
||||
inline Alias operator&(const Alias rhs_) const
|
||||
{
|
||||
return Alias{__value & static_cast<const From>(rhs_)};
|
||||
}
|
||||
inline bool operator<(const Alias z_) const { return __value < static_cast<const From>(z_); }
|
||||
inline bool operator>(const Alias z_) const { return __value > static_cast<const From>(z_); }
|
||||
inline bool operator<=(const Alias z_) const { return __value <= static_cast<const From>(z_); }
|
||||
inline bool operator>=(const Alias z_) const { return __value >= static_cast<const From>(z_); }
|
||||
inline bool operator==(const Alias z_) const { return __value == static_cast<const From>(z_); }
|
||||
inline bool operator!=(const Alias z_) const { return __value != static_cast<const From>(z_); }
|
||||
|
||||
inline Alias operator++()
|
||||
{
|
||||
__value++;
|
||||
return *this;
|
||||
}
|
||||
inline Alias operator--()
|
||||
{
|
||||
__value--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Alias operator+=(const Alias z_)
|
||||
{
|
||||
__value += static_cast<const From>(z_);
|
||||
return *this;
|
||||
}
|
||||
inline Alias operator-=(const Alias z_)
|
||||
{
|
||||
__value -= static_cast<const From>(z_);
|
||||
return *this;
|
||||
}
|
||||
inline Alias operator/=(const Alias z_)
|
||||
{
|
||||
__value /= static_cast<const From>(z_);
|
||||
return *this;
|
||||
}
|
||||
inline Alias operator*=(const Alias z_)
|
||||
{
|
||||
__value *= static_cast<const From>(z_);
|
||||
return *this;
|
||||
}
|
||||
inline Alias operator|=(const Alias z_)
|
||||
{
|
||||
__value |= static_cast<const From>(z_);
|
||||
return *this;
|
||||
}
|
||||
inline Alias operator&=(const Alias z_)
|
||||
{
|
||||
__value &= static_cast<const From>(z_);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename From, typename Tag>
|
||||
inline std::ostream &operator<<(std::ostream &stream, const Alias<From, Tag> &inst)
|
||||
{
|
||||
return stream << inst.__value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename From, typename Tag> struct hash<osrm::Alias<From, Tag>>
|
||||
{
|
||||
typedef osrm::Alias<From, Tag> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type const &s) const
|
||||
{
|
||||
return std::hash<From>()(static_cast<const From>(s));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OSRM_ALIAS_HPP
|
||||
@@ -120,7 +120,15 @@ inline double reverse(const double bearing)
|
||||
// entry_bearing of 0.
|
||||
inline double angleBetween(const double entry_bearing, const double exit_bearing)
|
||||
{
|
||||
return std::fmod(entry_bearing - exit_bearing + 540., 360.);
|
||||
// transform bearing from cw into ccw order
|
||||
const double offset = 360 - entry_bearing;
|
||||
const double rotated_exit = [](double bearing, const double offset) {
|
||||
bearing += offset;
|
||||
return bearing > 360 ? bearing - 360 : bearing;
|
||||
}(exit_bearing, offset);
|
||||
|
||||
const auto angle = 540 - rotated_exit;
|
||||
return angle >= 360 ? angle - 360 : angle;
|
||||
}
|
||||
|
||||
} // namespace bearing
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#ifndef OSRM_UTIL_QUERY_HEAP_HPP
|
||||
#define OSRM_UTIL_QUERY_HEAP_HPP
|
||||
#ifndef BINARY_HEAP_H
|
||||
#define BINARY_HEAP_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/heap/d_ary_heap.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@@ -131,48 +132,60 @@ template <typename NodeID,
|
||||
typename Weight,
|
||||
typename Data,
|
||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||
class QueryHeap
|
||||
class BinaryHeap
|
||||
{
|
||||
public:
|
||||
using WeightType = Weight;
|
||||
using DataType = Data;
|
||||
|
||||
explicit QueryHeap(std::size_t maxID) : node_index(maxID) { Clear(); }
|
||||
explicit BinaryHeap(std::size_t maxID) : node_index(maxID) { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
heap.clear();
|
||||
heap.resize(1);
|
||||
inserted_nodes.clear();
|
||||
heap[0].weight = std::numeric_limits<Weight>::min();
|
||||
node_index.Clear();
|
||||
}
|
||||
|
||||
std::size_t Size() const { return heap.size(); }
|
||||
std::size_t Size() const { return (heap.size() - 1); }
|
||||
|
||||
bool Empty() const { return 0 == Size(); }
|
||||
|
||||
void Insert(NodeID node, Weight weight, const Data &data)
|
||||
{
|
||||
const auto index = static_cast<Key>(inserted_nodes.size());
|
||||
const auto handle = heap.push(std::make_pair(weight, index));
|
||||
inserted_nodes.emplace_back(HeapNode{handle, node, weight, data});
|
||||
node_index[node] = index;
|
||||
HeapElement element;
|
||||
element.index = static_cast<NodeID>(inserted_nodes.size());
|
||||
element.weight = weight;
|
||||
const Key key = static_cast<Key>(heap.size());
|
||||
heap.emplace_back(element);
|
||||
inserted_nodes.emplace_back(node, key, weight, data);
|
||||
node_index[node] = element.index;
|
||||
Upheap(key);
|
||||
CheckHeap();
|
||||
}
|
||||
|
||||
Data &GetData(NodeID node)
|
||||
{
|
||||
const auto index = node_index.peek_index(node);
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].data;
|
||||
}
|
||||
|
||||
Data const &GetData(NodeID node) const
|
||||
{
|
||||
const auto index = node_index.peek_index(node);
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].data;
|
||||
}
|
||||
|
||||
Weight &GetKey(NodeID node)
|
||||
{
|
||||
const Key index = node_index[node];
|
||||
return inserted_nodes[index].weight;
|
||||
}
|
||||
|
||||
const Weight &GetKey(NodeID node) const
|
||||
{
|
||||
const auto index = node_index.peek_index(node);
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].weight;
|
||||
}
|
||||
|
||||
@@ -180,7 +193,7 @@ class QueryHeap
|
||||
{
|
||||
BOOST_ASSERT(WasInserted(node));
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].handle == HeapHandle{};
|
||||
return inserted_nodes[index].key == 0;
|
||||
}
|
||||
|
||||
bool WasInserted(const NodeID node) const
|
||||
@@ -195,63 +208,134 @@ class QueryHeap
|
||||
|
||||
NodeID Min() const
|
||||
{
|
||||
BOOST_ASSERT(!heap.empty());
|
||||
return inserted_nodes[heap.top().second].node;
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
return inserted_nodes[heap[1].index].node;
|
||||
}
|
||||
|
||||
Weight MinKey() const
|
||||
{
|
||||
BOOST_ASSERT(!heap.empty());
|
||||
return heap.top().first;
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
return heap[1].weight;
|
||||
}
|
||||
|
||||
NodeID DeleteMin()
|
||||
{
|
||||
BOOST_ASSERT(!heap.empty());
|
||||
const Key removedIndex = heap.top().second;
|
||||
heap.pop();
|
||||
inserted_nodes[removedIndex].handle = HeapHandle{};
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
const Key removedIndex = heap[1].index;
|
||||
heap[1] = heap[heap.size() - 1];
|
||||
heap.pop_back();
|
||||
if (heap.size() > 1)
|
||||
{
|
||||
Downheap(1);
|
||||
}
|
||||
inserted_nodes[removedIndex].key = 0;
|
||||
CheckHeap();
|
||||
return inserted_nodes[removedIndex].node;
|
||||
}
|
||||
|
||||
void DeleteAll()
|
||||
{
|
||||
std::for_each(inserted_nodes.begin(), inserted_nodes.end(), [](auto &node) {
|
||||
node.handle = HeapHandle();
|
||||
});
|
||||
heap.clear();
|
||||
auto iend = heap.end();
|
||||
for (auto i = heap.begin() + 1; i != iend; ++i)
|
||||
{
|
||||
inserted_nodes[i->index].key = 0;
|
||||
}
|
||||
heap.resize(1);
|
||||
heap[0].weight = (std::numeric_limits<Weight>::min)();
|
||||
}
|
||||
|
||||
void DecreaseKey(NodeID node, Weight weight)
|
||||
{
|
||||
BOOST_ASSERT(!WasRemoved(node));
|
||||
const auto index = node_index.peek_index(node);
|
||||
auto &reference = inserted_nodes[index];
|
||||
reference.weight = weight;
|
||||
heap.increase(reference.handle, std::make_pair(weight, index));
|
||||
BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
|
||||
const Key &index = node_index.peek_index(node);
|
||||
Key &key = inserted_nodes[index].key;
|
||||
BOOST_ASSERT(key >= 0);
|
||||
|
||||
inserted_nodes[index].weight = weight;
|
||||
heap[key].weight = weight;
|
||||
Upheap(key);
|
||||
CheckHeap();
|
||||
}
|
||||
|
||||
private:
|
||||
using HeapData = std::pair<Weight, Key>;
|
||||
using HeapContainer = boost::heap::d_ary_heap<HeapData,
|
||||
boost::heap::arity<4>,
|
||||
boost::heap::mutable_<true>,
|
||||
boost::heap::compare<std::greater<HeapData>>>;
|
||||
using HeapHandle = typename HeapContainer::handle_type;
|
||||
|
||||
struct HeapNode
|
||||
class HeapNode
|
||||
{
|
||||
HeapHandle handle;
|
||||
public:
|
||||
HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(std::move(d))
|
||||
{
|
||||
}
|
||||
|
||||
NodeID node;
|
||||
Key key;
|
||||
Weight weight;
|
||||
Data data;
|
||||
};
|
||||
struct HeapElement
|
||||
{
|
||||
Key index;
|
||||
Weight weight;
|
||||
};
|
||||
|
||||
std::vector<HeapNode> inserted_nodes;
|
||||
HeapContainer heap;
|
||||
std::vector<HeapElement> heap;
|
||||
IndexStorage node_index;
|
||||
|
||||
void Downheap(Key key)
|
||||
{
|
||||
const Key droppingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
const Key heap_size = static_cast<Key>(heap.size());
|
||||
Key nextKey = key << 1;
|
||||
while (nextKey < heap_size)
|
||||
{
|
||||
const Key nextKeyOther = nextKey + 1;
|
||||
if ((nextKeyOther < heap_size) && (heap[nextKey].weight > heap[nextKeyOther].weight))
|
||||
{
|
||||
nextKey = nextKeyOther;
|
||||
}
|
||||
if (weight <= heap[nextKey].weight)
|
||||
{
|
||||
break;
|
||||
}
|
||||
heap[key] = heap[nextKey];
|
||||
inserted_nodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
nextKey <<= 1;
|
||||
}
|
||||
heap[key].index = droppingIndex;
|
||||
heap[key].weight = weight;
|
||||
inserted_nodes[droppingIndex].key = key;
|
||||
}
|
||||
|
||||
void Upheap(Key key)
|
||||
{
|
||||
const Key risingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
Key nextKey = key >> 1;
|
||||
while (heap[nextKey].weight > weight)
|
||||
{
|
||||
BOOST_ASSERT(nextKey != 0);
|
||||
heap[key] = heap[nextKey];
|
||||
inserted_nodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
nextKey >>= 1;
|
||||
}
|
||||
heap[key].index = risingIndex;
|
||||
heap[key].weight = weight;
|
||||
inserted_nodes[risingIndex].key = key;
|
||||
}
|
||||
|
||||
void CheckHeap()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (std::size_t i = 2; i < heap.size(); ++i)
|
||||
{
|
||||
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSRM_UTIL_QUERY_HEAP_HPP
|
||||
#endif // BINARY_HEAP_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user