Compare commits
241 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4acce593db | |||
| 1756208f3f | |||
| 99d78713a2 | |||
| 38ba8b90fc | |||
| 32402263f8 | |||
| 4fbe68f4d7 | |||
| 991cdf7958 | |||
| fdbcefe358 | |||
| 853691aee2 | |||
| 3b4e2e83ef | |||
| c459530cb6 | |||
| 2a15e6dec8 | |||
| 1a1293608d | |||
| 318df9deaa | |||
| cacb162520 | |||
| 105709cb43 | |||
| 9695fa7941 | |||
| fd9bebbfa7 | |||
| db18e8669f | |||
| 9b4a4fdd82 | |||
| cdc7e5f021 | |||
| adc87149e2 | |||
| 8adbfe06ed | |||
| ae805f9ec8 | |||
| be24689b0f | |||
| 41c31a2388 | |||
| 8b866502d1 | |||
| 7837cd61df | |||
| b573485c31 | |||
| 4e68f3a7e1 | |||
| 5ba26d3d6d | |||
| a6cf2eee7e | |||
| 6843eb1479 | |||
| b331885d3c | |||
| 73716bd651 | |||
| 9edd161da3 | |||
| 1bc3ff6491 | |||
| b0f2ef287e | |||
| 16f53ff81a | |||
| 7a260dc2ba | |||
| 1c0d951f5e | |||
| 77a740c0fb | |||
| 61101db8cf | |||
| b51632a2fb | |||
| 9d10503a9c | |||
| 7d50e5afe0 | |||
| 549216c792 | |||
| 1990de7dcc | |||
| 89f6e2d55b | |||
| c628ecbf24 | |||
| b6f19cd544 | |||
| 14860b62e9 | |||
| 9970b7d580 | |||
| 7feb79ef91 | |||
| 6f84812903 | |||
| 8085e86170 | |||
| 35973576d9 | |||
| 7740d5d7c0 | |||
| c4eff6cd65 | |||
| 5c4353b46e | |||
| 05a5918909 | |||
| 80ad38bbc6 | |||
| 6bee8866de | |||
| ba92674c6e | |||
| 68019a1fb2 | |||
| 3a9acde2c3 | |||
| a3a7a822e1 | |||
| c7d22c2b92 | |||
| b2aeb47630 | |||
| 0a1d1901cc | |||
| 29db0c80d9 | |||
| 4654751872 | |||
| b5b18d8afc | |||
| 15139c934f | |||
| 7b8619e37c | |||
| f52b5c31b6 | |||
| e98859e4c0 | |||
| c5cc4c5a74 | |||
| e3b831364f | |||
| 730d2b5ef2 | |||
| 16abee1022 | |||
| 69fa52a010 | |||
| e1efa4c6ab | |||
| 17cd1575f6 | |||
| 3cd8e0fef8 | |||
| 397bb694fd | |||
| 473ebfcbf6 | |||
| a06171438e | |||
| ea0881553e | |||
| c4bf450fc6 | |||
| bf2b45120a | |||
| 7edf0f218c | |||
| 600ca06166 | |||
| 8d8042ebae | |||
| be123cd72f | |||
| 282415bbc1 | |||
| b08191b2c4 | |||
| 39dd484f45 | |||
| 5450574d63 | |||
| 29d1b34140 | |||
| a915542916 | |||
| fea07f343b | |||
| c7daa521ad | |||
| c2532b1589 | |||
| 4610fd9ff1 | |||
| c4b90f52c0 | |||
| 0e8b8b4901 | |||
| 2c80f76004 | |||
| 666ce46d36 | |||
| bc120776f0 | |||
| 5693ffd2cf | |||
| 51fe0dd5a0 | |||
| 14d2199cd8 | |||
| 9889a454ce | |||
| cb4586ebee | |||
| 44924b4bb4 | |||
| 3af3e06e75 | |||
| 39effb8f7e | |||
| 5a68f4c214 | |||
| f558b16147 | |||
| 4c2d578561 | |||
| 81a4747acb | |||
| 9fc2c32408 | |||
| 24e0028afb | |||
| c334d11e95 | |||
| aec9b6a178 | |||
| 81929c984b | |||
| 5395290fd5 | |||
| b3ef2a0383 | |||
| 9e97748700 | |||
| 4a9fdca7b2 | |||
| f3b7ab92ff | |||
| eae9e7fab6 | |||
| 649d4ee512 | |||
| b5a4ffed96 | |||
| 8a63ad9b4b | |||
| 0d9f18fe1f | |||
| 2690dd0621 | |||
| 4ef331db1f | |||
| e572d6c340 | |||
| 0c48f5fe2f | |||
| 3ee8a963cb | |||
| c322d93435 | |||
| c0dd5d7c76 | |||
| 993f5badf1 | |||
| a542da3678 | |||
| f1a392c4df | |||
| f2bace6c1f | |||
| 921235b2dc | |||
| bde51a9ef5 | |||
| a52213c885 | |||
| 8e800c48bc | |||
| e25654c210 | |||
| ee447afd72 | |||
| c410c200bd | |||
| 8152dcfb4c | |||
| 86ffce3a50 | |||
| bed53f5fd5 | |||
| 2b010fc6f3 | |||
| b8260e44fa | |||
| a594008e57 | |||
| f407afa694 | |||
| 06f28ffd34 | |||
| 4f454a3761 | |||
| d4300e73f3 | |||
| 990e411361 | |||
| 73b3d37837 | |||
| 5d7d5fceba | |||
| b1dfbce675 | |||
| da5aebaef3 | |||
| bced9a5a6d | |||
| 2c5e4e6c02 | |||
| 6ea296fb5c | |||
| cf5f6be472 | |||
| c61198b26b | |||
| 5d1b4ce71d | |||
| c664d0392a | |||
| aaf39162a8 | |||
| cb31f9ec29 | |||
| fed77c4066 | |||
| 6a09d2aa9b | |||
| 15b53de056 | |||
| 6d96a9a2e3 | |||
| 653f647fee | |||
| f7b7335d75 | |||
| 495131efd7 | |||
| 2eb633bc41 | |||
| 86bfe1ede1 | |||
| c04e1b2ded | |||
| 098d77c658 | |||
| 385bba4949 | |||
| bc980e72bf | |||
| 535bb49893 | |||
| b56a7579a8 | |||
| 8b52c6c7ac | |||
| d166fc6a75 | |||
| bdb116afe5 | |||
| 873e766d2e | |||
| a84277f246 | |||
| b80764b6b8 | |||
| 14082d0e00 | |||
| f7775f5e0b | |||
| b7af6eb2a4 | |||
| a4ee2ccb13 | |||
| c61acaf8be | |||
| 0fc8b6289c | |||
| 0f93a7dd05 | |||
| 4d0fb89489 | |||
| 6f4af330ed | |||
| 7c8c25f7bc | |||
| cf56b5ddbf | |||
| ac23e3b223 | |||
| 7922a6172a | |||
| e34f2db4db | |||
| 5df33e5b90 | |||
| db608559f6 | |||
| c048a36a4c | |||
| 33021d37a1 | |||
| 31d6d74f90 | |||
| bec57258a4 | |||
| 43f0723b73 | |||
| 9b74a47c91 | |||
| 993a36ea20 | |||
| 8b5af24eb8 | |||
| 5c9a7a0152 | |||
| 83588fd00f | |||
| 5acf660f37 | |||
| de13834c12 | |||
| 49811e1f46 | |||
| 8788b0fae8 | |||
| 1cafafc4cd | |||
| e2c1956aa5 | |||
| a8bc2cf8a7 | |||
| 975ede4bec | |||
| faff2c774d | |||
| d8e3b03ec1 | |||
| ae41066fbe | |||
| 342da81591 | |||
| df9195b939 | |||
| 519eae63c6 | |||
| 5f598da76d |
@@ -0,0 +1,30 @@
|
|||||||
|
# EditorConfig is awesome: http://EditorConfig.org
|
||||||
|
#
|
||||||
|
# NOTE: Keep settings in sync with the master .clang-format file
|
||||||
|
#
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# CMake configuration files
|
||||||
|
[{CMakeLists.txt,CMakeSettings.json,*.cmake}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# CI configuration files
|
||||||
|
[{.travis.yml,appveyor.yml}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# Unix shell scripts
|
||||||
|
[*.sh]
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# Windows shell scripts
|
||||||
|
[*.bat]
|
||||||
|
end_of_line = crlf
|
||||||
|
indent_style = space
|
||||||
|
trim_trailing_whitespace = true
|
||||||
@@ -66,6 +66,7 @@ Thumbs.db
|
|||||||
######################################
|
######################################
|
||||||
/.vs*
|
/.vs*
|
||||||
/*.local.bat
|
/*.local.bat
|
||||||
|
/CMakeSettings.json
|
||||||
|
|
||||||
# stxxl related files #
|
# stxxl related files #
|
||||||
#######################
|
#######################
|
||||||
|
|||||||
+2
-1
@@ -13,7 +13,7 @@ notifications:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- "5.16"
|
- "5.18"
|
||||||
# enable building tags
|
# enable building tags
|
||||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||||
|
|
||||||
@@ -60,6 +60,7 @@ matrix:
|
|||||||
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||||
- ${MASON} install clang-format 3.8.1
|
- ${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
|
- PATH=$(${MASON} prefix clang-format 3.8.1)/bin:${PATH} ./scripts/format.sh && ./scripts/error_on_dirty.sh
|
||||||
|
- node ./scripts/validate_changelog.js
|
||||||
# See issue 4043
|
# See issue 4043
|
||||||
#- npm run docs && ./scripts/error_on_dirty.sh
|
#- npm run docs && ./scripts/error_on_dirty.sh
|
||||||
after_success:
|
after_success:
|
||||||
|
|||||||
+55
-15
@@ -1,23 +1,63 @@
|
|||||||
# 5.16.4
|
# 5.18.1
|
||||||
- Changes from 5.16.3:
|
- Changes from 5.18.0:
|
||||||
- Bugfixes:
|
- Bugfixes:
|
||||||
- FIXED: Properly calculate annotations for speeds, durations and distances when waypoints are used with mapmatching [#4949](https://github.com/Project-OSRM/osrm-backend/pull/4949)
|
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
|
||||||
|
|
||||||
# 5.16.3
|
# 5.18.0
|
||||||
- Changes from 5.16.2:
|
- Changes from 5.17.0:
|
||||||
|
- Features:
|
||||||
|
- ADDED: `table` plugin now optionally returns `distance` matrix as part of response [#4990](https://github.com/Project-OSRM/osrm-backend/pull/4990)
|
||||||
|
- ADDED: New optional parameter `annotations` for `table` that accepts `distance`, `duration`, or both `distance,duration` as values [#4990](https://github.com/Project-OSRM/osrm-backend/pull/4990)
|
||||||
|
- Infrastructure:
|
||||||
|
- ADDED: Updated libosmium and added protozero and vtzero libraries [#5037](https://github.com/Project-OSRM/osrm-backend/pull/5037)
|
||||||
|
- CHANGED: Use vtzero library in tile plugin [#4686](https://github.com/Project-OSRM/osrm-backend/pull/4686)
|
||||||
|
- Profile:
|
||||||
|
- ADDED: Bicycle profile now returns classes for ferry and tunnel routes. [#5054](https://github.com/Project-OSRM/osrm-backend/pull/5054)
|
||||||
|
- ADDED: Bicycle profile allows to exclude ferry routes (default to not enabled) [#5054](https://github.com/Project-OSRM/osrm-backend/pull/5054)
|
||||||
|
|
||||||
|
# 5.17.1
|
||||||
|
- Changes from 5.17.0:
|
||||||
|
- Bugfixes:
|
||||||
|
- FIXED: Do not combine a segregated edge with a roundabout [#5039](https://github.com/Project-OSRM/osrm-backend/issues/5039)
|
||||||
|
|
||||||
|
# 5.17.0
|
||||||
|
- Changes from 5.16.0:
|
||||||
|
- Bugfixes:
|
||||||
|
- FIXED: deduplication of route steps when waypoints are used [#4909](https://github.com/Project-OSRM/osrm-backend/issues/4909)
|
||||||
|
- FIXED: Use smaller range for U-turn angles in map-matching [#4920](https://github.com/Project-OSRM/osrm-backend/pull/4920)
|
||||||
- FIXED: Remove the last short annotation segment in `trimShortSegments` [#4946](https://github.com/Project-OSRM/osrm-backend/pull/4946)
|
- FIXED: Remove the last short annotation segment in `trimShortSegments` [#4946](https://github.com/Project-OSRM/osrm-backend/pull/4946)
|
||||||
|
- FIXED: Properly calculate annotations for speeds, durations and distances when waypoints are used with mapmatching [#4949](https://github.com/Project-OSRM/osrm-backend/pull/4949)
|
||||||
|
- FIXED: Don't apply unimplemented SH and PH conditions in OpeningHours and add inversed date ranges [#4992](https://github.com/Project-OSRM/osrm-backend/issues/4992)
|
||||||
|
- FIXED: integer overflow in `DynamicGraph::Renumber` [#5021](https://github.com/Project-OSRM/osrm-backend/pull/5021)
|
||||||
|
- Profile:
|
||||||
|
- CHANGED: Handle oneways in get_forward_backward_by_key [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
|
||||||
|
- FIXED: Do not route against oneway road if there is a cycleway in the wrong direction; also review bike profile [#4943](https://github.com/Project-OSRM/osrm-backend/issues/4943)
|
||||||
|
- CHANGED: Make cyclability weighting of the bike profile prefer safer routes more strongly [#5015](https://github.com/Project-OSRM/osrm-backend/issues/5015)
|
||||||
|
- Guidance:
|
||||||
|
- CHANGED: Don't use obviousness for links bifurcations [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
|
||||||
|
- FIXED: Adjust Straight direction modifiers of side roads in driveway handler [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
|
||||||
|
- CHANGED: Added post process logic to collapse segregated turn instructions [#4925](https://github.com/Project-OSRM/osrm-backend/pull/4925)
|
||||||
|
- ADDED: Maneuver relation now supports `straight` as a direction [#4995](https://github.com/Project-OSRM/osrm-backend/pull/4995)
|
||||||
|
- FIXED: Support spelling maneuver relation with British spelling [#4950](https://github.com/Project-OSRM/osrm-backend/issues/4950)
|
||||||
|
- Tools:
|
||||||
|
- ADDED: `osrm-routed` accepts a new property `--memory_file` to store memory in a file on disk. [#4881](https://github.com/Project-OSRM/osrm-backend/pull/4881)
|
||||||
|
- ADDED: `osrm-datastore` accepts a new parameter `--dataset-name` to select the name of the dataset. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
|
||||||
|
- ADDED: `osrm-datastore` accepts a new parameter `--list` to list all datasets loaded into memory. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
|
||||||
|
- ADDED: `osrm-datastore` accepts a new parameter `--only-metric` to only reload the data that can be updated by a weight update (reduces memory for traffic updates). [#5002](https://github.com/Project-OSRM/osrm-backend/pull/5002)
|
||||||
|
- ADDED: `osrm-routed` accepts a new parameter `--dataset-name` to select the shared-memory dataset to use. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
|
||||||
|
- NodeJS:
|
||||||
|
- ADDED: `OSRM` object accepts a new option `memory_file` that stores the memory in a file on disk. [#4881](https://github.com/Project-OSRM/osrm-backend/pull/4881)
|
||||||
|
- ADDED: `OSRM` object accepts a new option `dataset_name` to select the shared-memory dataset. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
|
||||||
|
- Internals
|
||||||
|
- CHANGED: Updated segregated intersection identification [#4845](https://github.com/Project-OSRM/osrm-backend/pull/4845) [#4968](https://github.com/Project-OSRM/osrm-backend/pull/4968)
|
||||||
|
- REMOVED: Remove `.timestamp` file since it was unused [#4960](https://github.com/Project-OSRM/osrm-backend/pull/4960)
|
||||||
|
- Documentation:
|
||||||
|
- ADDED: Add documentation about OSM node ids in nearest service response [#4436](https://github.com/Project-OSRM/osrm-backend/pull/4436)
|
||||||
- Performance
|
- Performance
|
||||||
- FIXED: Speed up response time when lots of legs exist and geojson is used with `steps=true` [#4936](https://github.com/Project-OSRM/osrm-backend/pull/4936)
|
- FIXED: Speed up response time when lots of legs exist and geojson is used with `steps=true` [#4936](https://github.com/Project-OSRM/osrm-backend/pull/4936)
|
||||||
|
- FIXED: Return iterators instead of vectors in datafacade_base functions [#4969](https://github.com/Project-OSRM/osrm-backend/issues/4969)
|
||||||
# 5.16.2
|
- Misc:
|
||||||
- Changes from 5.16.1:
|
- ADDED: expose name for datasource annotations as metadata [#4973](https://github.com/Project-OSRM/osrm-backend/pull/4973)
|
||||||
- Bugfixes:
|
|
||||||
- FIXED #4920: Use smaller range for U-turn angles in map-matching [#4920](https://github.com/Project-OSRM/osrm-backend/pull/4920)
|
|
||||||
|
|
||||||
# 5.16.1
|
|
||||||
- Changes from 5.16.0:
|
|
||||||
- Bugfixes
|
|
||||||
- FIXED #4909: deduplication of route steps when waypoints are used [#4909](https://github.com/Project-OSRM/osrm-backend/issues/4909)
|
|
||||||
|
|
||||||
# 5.16.0
|
# 5.16.0
|
||||||
- Changes from 5.15.2:
|
- Changes from 5.15.2:
|
||||||
|
|||||||
+51
-26
@@ -1,5 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.11)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
# we depend on 2.8.11 introducing target_include_directories
|
|
||||||
|
|
||||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
||||||
message(FATAL_ERROR "In-source builds are not allowed.
|
message(FATAL_ERROR "In-source builds are not allowed.
|
||||||
@@ -59,12 +58,26 @@ if (POLICY CMP0048)
|
|||||||
cmake_policy(SET CMP0048 OLD)
|
cmake_policy(SET CMP0048 OLD)
|
||||||
endif()
|
endif()
|
||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
|
||||||
set(OSRM_VERSION_MINOR 16)
|
|
||||||
set(OSRM_VERSION_PATCH 4)
|
|
||||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
|
||||||
|
|
||||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
include(JSONParser)
|
||||||
|
file(READ "package.json" packagejsonraw)
|
||||||
|
sbeParseJson(packagejson packagejsonraw)
|
||||||
|
|
||||||
|
if (packagejson.version MATCHES "^([0-9]+)\.([0-9]+)\.([0-9]+)")
|
||||||
|
set(OSRM_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||||
|
set(OSRM_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||||
|
set(OSRM_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||||
|
|
||||||
|
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Version from package.json cannot be parsed, expected semver compatible X.Y.Z, but found ${packagejson.version}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_definitions("-DOSRM_PROJECT_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"")
|
||||||
|
else()
|
||||||
|
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# these two functions build up custom variables:
|
# these two functions build up custom variables:
|
||||||
# DEPENDENCIES_INCLUDE_DIRS and OSRM_DEFINES
|
# DEPENDENCIES_INCLUDE_DIRS and OSRM_DEFINES
|
||||||
@@ -153,15 +166,15 @@ add_executable(osrm-partition src/tools/partition.cpp)
|
|||||||
add_executable(osrm-customize src/tools/customize.cpp)
|
add_executable(osrm-customize src/tools/customize.cpp)
|
||||||
add_executable(osrm-contract src/tools/contract.cpp)
|
add_executable(osrm-contract src/tools/contract.cpp)
|
||||||
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
|
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_contract src/osrm/contractor.cpp $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_contract src/osrm/contractor.cpp $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_extract src/osrm/extractor.cpp $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_extract src/osrm/extractor.cpp $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_guidance $<TARGET_OBJECTS:GUIDANCE> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_guidance $<TARGET_OBJECTS:GUIDANCE> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_partition src/osrm/partitioner.cpp $<TARGET_OBJECTS:PARTITIONER> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_partition src/osrm/partitioner.cpp $<TARGET_OBJECTS:PARTITIONER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_customize src/osrm/customizer.cpp $<TARGET_OBJECTS:CUSTOMIZER> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_customize src/osrm/customizer.cpp $<TARGET_OBJECTS:CUSTOMIZER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_update $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_update $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
|
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||||
|
|
||||||
if(ENABLE_GOLD_LINKER)
|
if(ENABLE_GOLD_LINKER)
|
||||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||||
@@ -403,11 +416,30 @@ if(UNIX AND NOT APPLE)
|
|||||||
set(MAYBE_RT_LIBRARY -lrt)
|
set(MAYBE_RT_LIBRARY -lrt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Disallow deprecated protozero APIs
|
|
||||||
add_definitions(-DPROTOZERO_STRICT_API)
|
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
# Third-party libraries
|
||||||
|
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
|
||||||
|
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(MICROTAR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src")
|
||||||
|
include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(MBXGEOM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/geometry.hpp-0.9.2/include")
|
||||||
|
include_directories(SYSTEM ${MBXGEOM_INCLUDE_DIR})
|
||||||
|
set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2.5.4/include")
|
||||||
|
include_directories(SYSTEM ${CHEAPRULER_INCLUDE_DIR})
|
||||||
|
|
||||||
|
add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c")
|
||||||
|
set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
set(PROTOZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/protozero/include")
|
||||||
|
include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(VTZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vtzero/include")
|
||||||
|
include_directories(SYSTEM ${VTZERO_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
||||||
# if mason is enabled no find_package calls are made
|
# if mason is enabled no find_package calls are made
|
||||||
# to ensure that we are only compiling and linking against
|
# to ensure that we are only compiling and linking against
|
||||||
# fully portable mason packages
|
# fully portable mason packages
|
||||||
@@ -482,9 +514,6 @@ if(ENABLE_MASON)
|
|||||||
# note: we avoid calling find_package(Osmium ...) here to ensure that the
|
# note: we avoid calling find_package(Osmium ...) here to ensure that the
|
||||||
# expat and bzip2 are used from mason rather than the system
|
# 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/libosmium/include)
|
||||||
|
|
||||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include)
|
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||||
@@ -542,10 +571,6 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
find_package(Osmium REQUIRED COMPONENTS io)
|
find_package(Osmium REQUIRED COMPONENTS io)
|
||||||
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
|
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()
|
endif()
|
||||||
|
|
||||||
# prefix compilation with ccache by default if available and on clang or gcc
|
# prefix compilation with ccache by default if available and on clang or gcc
|
||||||
@@ -686,7 +711,7 @@ target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update osrm_st
|
|||||||
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
||||||
|
|
||||||
# BUILD_COMPONENTS
|
# BUILD_COMPONENTS
|
||||||
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:MICROTAR> $<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} ${UTIL_LIBRARIES})
|
||||||
install(TARGETS osrm-components DESTINATION bin)
|
install(TARGETS osrm-components DESTINATION bin)
|
||||||
|
|
||||||
@@ -848,4 +873,4 @@ if (ENABLE_NODE_BINDINGS)
|
|||||||
endforeach()
|
endforeach()
|
||||||
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
|
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
|
||||||
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
|
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
|
||||||
endif()
|
endif()
|
||||||
@@ -9,7 +9,7 @@ High performance routing engine written in C++14 designed to run on OpenStreetMa
|
|||||||
The following services are available via HTTP API, C++ library interface and NodeJs wrapper:
|
The following services are available via HTTP API, C++ library interface and NodeJs wrapper:
|
||||||
- Nearest - Snaps coordinates to the street network and returns the nearest matches
|
- Nearest - Snaps coordinates to the street network and returns the nearest matches
|
||||||
- Route - Finds the fastest route between coordinates
|
- Route - Finds the fastest route between coordinates
|
||||||
- Table - Computes the duration of the fastest route between all pairs of supplied coordinates
|
- Table - Computes the duration or distances of the fastest route between all pairs of supplied coordinates
|
||||||
- Match - Snaps noisy GPS traces to the road network in the most plausible way
|
- Match - Snaps noisy GPS traces to the road network in the most plausible way
|
||||||
- Trip - Solves the Traveling Salesman Problem using a greedy heuristic
|
- Trip - Solves the Traveling Salesman Problem using a greedy heuristic
|
||||||
- Tile - Generates Mapbox Vector Tiles with internal routing metadata
|
- Tile - Generates Mapbox Vector Tiles with internal routing metadata
|
||||||
|
|||||||
@@ -0,0 +1,290 @@
|
|||||||
|
# https://github.com/sbellus/json-cmake/blob/9913da8800b95322d393894d3525d634568f305e/JSONParser.cmake
|
||||||
|
# MIT Licensed - https://github.com/sbellus/json-cmake/blob/master/LICENSE
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
|
if (DEFINED JSonParserGuard)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(JSonParserGuard yes)
|
||||||
|
|
||||||
|
macro(sbeParseJson prefix jsonString)
|
||||||
|
cmake_policy(PUSH)
|
||||||
|
|
||||||
|
set(json_string "${${jsonString}}")
|
||||||
|
string(LENGTH "${json_string}" json_jsonLen)
|
||||||
|
set(json_index 0)
|
||||||
|
set(json_AllVariables ${prefix})
|
||||||
|
set(json_ArrayNestingLevel 0)
|
||||||
|
set(json_MaxArrayNestingLevel 0)
|
||||||
|
|
||||||
|
_sbeParse(${prefix})
|
||||||
|
|
||||||
|
unset(json_index)
|
||||||
|
unset(json_AllVariables)
|
||||||
|
unset(json_jsonLen)
|
||||||
|
unset(json_string)
|
||||||
|
unset(json_value)
|
||||||
|
unset(json_inValue)
|
||||||
|
unset(json_name)
|
||||||
|
unset(json_inName)
|
||||||
|
unset(json_newPrefix)
|
||||||
|
unset(json_reservedWord)
|
||||||
|
unset(json_arrayIndex)
|
||||||
|
unset(json_char)
|
||||||
|
unset(json_end)
|
||||||
|
unset(json_ArrayNestingLevel)
|
||||||
|
foreach(json_nestingLevel RANGE ${json_MaxArrayNestingLevel})
|
||||||
|
unset(json_${json_nestingLevel}_arrayIndex)
|
||||||
|
endforeach()
|
||||||
|
unset(json_nestingLevel)
|
||||||
|
unset(json_MaxArrayNestingLevel)
|
||||||
|
|
||||||
|
cmake_policy(POP)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(sbeClearJson prefix)
|
||||||
|
foreach(json_var ${${prefix}})
|
||||||
|
unset(${json_var})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
unset(${prefix})
|
||||||
|
unset(json_var)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(sbePrintJson prefix)
|
||||||
|
foreach(json_var ${${prefix}})
|
||||||
|
message("${json_var} = ${${json_var}}")
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeParse prefix)
|
||||||
|
|
||||||
|
while(${json_index} LESS ${json_jsonLen})
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
if("\"" STREQUAL "${json_char}")
|
||||||
|
_sbeParseNameValue(${prefix})
|
||||||
|
elseif("{" STREQUAL "${json_char}")
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
_sbeParseObject(${prefix})
|
||||||
|
elseif("[" STREQUAL "${json_char}")
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
_sbeParseArray(${prefix})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${json_index} LESS ${json_jsonLen})
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
else()
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if ("}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}")
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
endwhile()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeParseNameValue prefix)
|
||||||
|
set(json_name "")
|
||||||
|
set(json_inName no)
|
||||||
|
|
||||||
|
while(${json_index} LESS ${json_jsonLen})
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
# check if name ends
|
||||||
|
if("\"" STREQUAL "${json_char}" AND json_inName)
|
||||||
|
set(json_inName no)
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
if(NOT ${json_index} LESS ${json_jsonLen})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
set(json_newPrefix ${prefix}.${json_name})
|
||||||
|
set(json_name "")
|
||||||
|
|
||||||
|
if(":" STREQUAL "${json_char}")
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
if(NOT ${json_index} LESS ${json_jsonLen})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
if("\"" STREQUAL "${json_char}")
|
||||||
|
_sbeParseValue(${json_newPrefix})
|
||||||
|
break()
|
||||||
|
elseif("{" STREQUAL "${json_char}")
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
_sbeParseObject(${json_newPrefix})
|
||||||
|
break()
|
||||||
|
elseif("[" STREQUAL "${json_char}")
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
_sbeParseArray(${json_newPrefix})
|
||||||
|
break()
|
||||||
|
else()
|
||||||
|
# reserved word starts
|
||||||
|
_sbeParseReservedWord(${json_newPrefix})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# name without value
|
||||||
|
list(APPEND ${json_AllVariables} ${json_newPrefix})
|
||||||
|
set(${json_newPrefix} "")
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(json_inName)
|
||||||
|
# remove escapes
|
||||||
|
if("\\" STREQUAL "${json_char}")
|
||||||
|
math(EXPR json_index "${json_index} + 1")
|
||||||
|
if(NOT ${json_index} LESS ${json_jsonLen})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(json_name "${json_name}${json_char}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# check if name starts
|
||||||
|
if("\"" STREQUAL "${json_char}" AND NOT json_inName)
|
||||||
|
set(json_inName yes)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
endwhile()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeParseReservedWord prefix)
|
||||||
|
set(json_reservedWord "")
|
||||||
|
set(json_end no)
|
||||||
|
while(${json_index} LESS ${json_jsonLen} AND NOT json_end)
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
if("," STREQUAL "${json_char}" OR "}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}")
|
||||||
|
set(json_end yes)
|
||||||
|
else()
|
||||||
|
set(json_reservedWord "${json_reservedWord}${json_char}")
|
||||||
|
math(EXPR json_index "${json_index} + 1")
|
||||||
|
endif()
|
||||||
|
endwhile()
|
||||||
|
|
||||||
|
list(APPEND ${json_AllVariables} ${prefix})
|
||||||
|
string(STRIP "${json_reservedWord}" json_reservedWord)
|
||||||
|
set(${prefix} ${json_reservedWord})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeParseValue prefix)
|
||||||
|
cmake_policy(SET CMP0054 NEW) # turn off implicit expansions in if statement
|
||||||
|
|
||||||
|
set(json_value "")
|
||||||
|
set(json_inValue no)
|
||||||
|
|
||||||
|
while(${json_index} LESS ${json_jsonLen})
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
# check if json_value ends, it is ended by "
|
||||||
|
if("\"" STREQUAL "${json_char}" AND json_inValue)
|
||||||
|
set(json_inValue no)
|
||||||
|
|
||||||
|
set(${prefix} ${json_value})
|
||||||
|
list(APPEND ${json_AllVariables} ${prefix})
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(json_inValue)
|
||||||
|
# if " is escaped consume
|
||||||
|
if("\\" STREQUAL "${json_char}")
|
||||||
|
math(EXPR json_index "${json_index} + 1")
|
||||||
|
if(NOT ${json_index} LESS ${json_jsonLen})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
if(NOT "\"" STREQUAL "${json_char}")
|
||||||
|
# if it is not " then copy also escape character
|
||||||
|
set(json_char "\\${json_char}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_sbeAddEscapedCharacter("${json_char}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# check if value starts
|
||||||
|
if("\"" STREQUAL "${json_char}" AND NOT json_inValue)
|
||||||
|
set(json_inValue yes)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
math(EXPR json_index "${json_index} + 1")
|
||||||
|
endwhile()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeAddEscapedCharacter char)
|
||||||
|
string(CONCAT json_value "${json_value}" "${char}")
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeParseObject prefix)
|
||||||
|
_sbeParse(${prefix})
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeParseArray prefix)
|
||||||
|
math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} + 1")
|
||||||
|
set(json_${json_ArrayNestingLevel}_arrayIndex 0)
|
||||||
|
|
||||||
|
set(${prefix} "")
|
||||||
|
list(APPEND ${json_AllVariables} ${prefix})
|
||||||
|
|
||||||
|
while(${json_index} LESS ${json_jsonLen})
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
if("\"" STREQUAL "${json_char}")
|
||||||
|
# simple value
|
||||||
|
list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex})
|
||||||
|
_sbeParseValue(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex})
|
||||||
|
elseif("{" STREQUAL "${json_char}")
|
||||||
|
# object
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex})
|
||||||
|
_sbeParseObject(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex})
|
||||||
|
else()
|
||||||
|
list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex})
|
||||||
|
_sbeParseReservedWord(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ${json_index} LESS ${json_jsonLen})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
|
||||||
|
if("]" STREQUAL "${json_char}")
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
break()
|
||||||
|
elseif("," STREQUAL "${json_char}")
|
||||||
|
math(EXPR json_${json_ArrayNestingLevel}_arrayIndex "${json_${json_ArrayNestingLevel}_arrayIndex} + 1")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_sbeMoveToNextNonEmptyCharacter()
|
||||||
|
endwhile()
|
||||||
|
|
||||||
|
if(${json_MaxArrayNestingLevel} LESS ${json_ArrayNestingLevel})
|
||||||
|
set(json_MaxArrayNestingLevel ${json_ArrayNestingLevel})
|
||||||
|
endif()
|
||||||
|
math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} - 1")
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(_sbeMoveToNextNonEmptyCharacter)
|
||||||
|
math(EXPR json_index "${json_index} + 1")
|
||||||
|
if(${json_index} LESS ${json_jsonLen})
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
while(${json_char} MATCHES "[ \t\n\r]" AND ${json_index} LESS ${json_jsonLen})
|
||||||
|
math(EXPR json_index "${json_index} + 1")
|
||||||
|
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
|
||||||
|
endwhile()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
+1
-1
@@ -3,5 +3,5 @@ module.exports = {
|
|||||||
verify: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only -f progress --require features/support --require features/step_definitions',
|
verify: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only -f progress --require features/support --require features/step_definitions',
|
||||||
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||||
all: '--strict --require features/support --require features/step_definitions',
|
all: '--strict --require features/support --require features/step_definitions',
|
||||||
mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
|
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@ch --require features/support --require features/step_definitions -f progress'
|
||||||
};
|
};
|
||||||
|
|||||||
+135
-9
@@ -120,6 +120,7 @@ In addition to the [general options](#general-options) the following options are
|
|||||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||||
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
|
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
|
||||||
- `distance`: Distance in meters to the supplied input coordinate.
|
- `distance`: Distance in meters to the supplied input coordinate.
|
||||||
|
- `nodes`: Array of OpenStreetMap node ids.
|
||||||
|
|
||||||
#### Example Requests
|
#### Example Requests
|
||||||
|
|
||||||
@@ -134,6 +135,10 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
|
|||||||
{
|
{
|
||||||
"waypoints" : [
|
"waypoints" : [
|
||||||
{
|
{
|
||||||
|
"nodes": [
|
||||||
|
2264199819,
|
||||||
|
0
|
||||||
|
],
|
||||||
"hint" : "KSoKADRYroqUBAEAEAAAABkAAAAGAAAAAAAAABhnCQCLtwAA_0vMAKlYIQM8TMwArVghAwEAAQH1a66g",
|
"hint" : "KSoKADRYroqUBAEAEAAAABkAAAAGAAAAAAAAABhnCQCLtwAA_0vMAKlYIQM8TMwArVghAwEAAQH1a66g",
|
||||||
"distance" : 4.152629,
|
"distance" : 4.152629,
|
||||||
"name" : "Friedrichstraße",
|
"name" : "Friedrichstraße",
|
||||||
@@ -143,6 +148,10 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"nodes": [
|
||||||
|
2045820592,
|
||||||
|
0
|
||||||
|
],
|
||||||
"hint" : "KSoKADRYroqUBAEABgAAAAAAAAAAAAAAKQAAABhnCQCLtwAA7kvMAAxZIQM8TMwArVghAwAAAQH1a66g",
|
"hint" : "KSoKADRYroqUBAEABgAAAAAAAAAAAAAAKQAAABhnCQCLtwAA7kvMAAxZIQM8TMwArVghAwAAAQH1a66g",
|
||||||
"distance" : 11.811961,
|
"distance" : 11.811961,
|
||||||
"name" : "Friedrichstraße",
|
"name" : "Friedrichstraße",
|
||||||
@@ -152,6 +161,10 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"nodes": [
|
||||||
|
0,
|
||||||
|
21487242
|
||||||
|
],
|
||||||
"hint" : "KioKgDbbDgCUBAEAAAAAABoAAAAAAAAAPAAAABlnCQCLtwAA50vMADJZIQM8TMwArVghAwAAAQH1a66g",
|
"hint" : "KioKgDbbDgCUBAEAAAAAABoAAAAAAAAAPAAAABlnCQCLtwAA50vMADJZIQM8TMwArVghAwAAAQH1a66g",
|
||||||
"distance" : 15.872438,
|
"distance" : 15.872438,
|
||||||
"name" : "Friedrichstraße",
|
"name" : "Friedrichstraße",
|
||||||
@@ -209,13 +222,13 @@ curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397
|
|||||||
|
|
||||||
### Table service
|
### Table service
|
||||||
|
|
||||||
Computes the duration of the fastest route between all pairs of supplied coordinates.
|
Computes the duration of the fastest route between all pairs of supplied coordinates. Returns the durations or distances or both between the coordinate pairs. Note that the distances are not the shortest distance between two coordinates, but rather the distances of the fastest routes. Duration is in seconds and distances is in meters.
|
||||||
|
|
||||||
```endpoint
|
```endpoint
|
||||||
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]
|
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&{destinations}=[{elem}...]&annotations={duration|distance|duration,distance}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Coordinates**
|
**Options**
|
||||||
|
|
||||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||||
|
|
||||||
@@ -223,6 +236,8 @@ In addition to the [general options](#general-options) the following options are
|
|||||||
|------------|--------------------------------------------------|---------------------------------------------|
|
|------------|--------------------------------------------------|---------------------------------------------|
|
||||||
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|
||||||
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|
||||||
|
|annotations |`duration` (default), `distance`, or `duration,distance`|Return the requested table or tables in response. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned.
|
||||||
|
|
|
||||||
|
|
||||||
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
|
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
|
||||||
to number of input locations;
|
to number of input locations;
|
||||||
@@ -240,14 +255,23 @@ sources=0;5;7&destinations=5;1;4;2;3;6
|
|||||||
#### Example Request
|
#### Example Request
|
||||||
|
|
||||||
```curl
|
```curl
|
||||||
# Returns a 3x3 matrix:
|
# Returns a 3x3 duration matrix:
|
||||||
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219'
|
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219'
|
||||||
|
|
||||||
# Returns a 1x3 matrix
|
# Returns a 1x3 duration matrix
|
||||||
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0'
|
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0'
|
||||||
|
|
||||||
# Returns a asymmetric 3x2 matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
|
# Returns a asymmetric 3x2 duration matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
|
||||||
curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHulFzeMe`EuvKpnCglA)?sources=0;1;3&destinations=2;4'
|
curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHulFzeMe`EuvKpnCglA)?sources=0;1;3&destinations=2;4'
|
||||||
|
|
||||||
|
# Returns a 3x3 duration matrix:
|
||||||
|
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=duration'
|
||||||
|
|
||||||
|
# Returns a 3x3 distance matrix for CH:
|
||||||
|
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=distance'
|
||||||
|
|
||||||
|
# Returns a 3x3 duration matrix and a 3x3 distance matrix for CH:
|
||||||
|
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=distance,duration'
|
||||||
```
|
```
|
||||||
|
|
||||||
**Response**
|
**Response**
|
||||||
@@ -255,17 +279,115 @@ curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHu
|
|||||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||||
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
|
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
|
||||||
the i-th waypoint to the j-th waypoint. Values are given in seconds. Can be `null` if no route between `i` and `j` can be found.
|
the i-th waypoint to the j-th waypoint. Values are given in seconds. Can be `null` if no route between `i` and `j` can be found.
|
||||||
|
- `distances` array of arrays that stores the matrix in row-major order. `distances[i][j]` gives the travel distance from
|
||||||
|
the i-th waypoint to the j-th waypoint. Values are given in meters. Can be `null` if no route between `i` and `j` can be found. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned.
|
||||||
- `sources` array of `Waypoint` objects describing all sources in order
|
- `sources` array of `Waypoint` objects describing all sources in order
|
||||||
- `destinations` array of `Waypoint` objects describing all destinations in order
|
- `destinations` array of `Waypoint` objects describing all destinations in order
|
||||||
|
|
||||||
In case of error the following `code`s are supported in addition to the general ones:
|
In case of error the following `code`s are supported in addition to the general ones:
|
||||||
|
|
||||||
| Type | Description |
|
| Type | Description |
|
||||||
|-------------------|-----------------|
|
|------------------|-----------------|
|
||||||
| `NoTable` | No route found. |
|
| `NoTable` | No route found. |
|
||||||
|
| `NotImplemented` | This request is not supported |
|
||||||
|
|
||||||
All other properties might be undefined.
|
All other properties might be undefined.
|
||||||
|
|
||||||
|
#### Example Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"location": [
|
||||||
|
13.3888,
|
||||||
|
52.517033
|
||||||
|
],
|
||||||
|
"hint": "PAMAgEVJAoAUAAAAIAAAAAcAAAAAAAAArss0Qa7LNEHiVIRA4lSEQAoAAAAQAAAABAAAAAAAAADMAAAAAEzMAKlYIQM8TMwArVghAwEA3wps52D3",
|
||||||
|
"name": "Friedrichstraße"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": [
|
||||||
|
13.397631,
|
||||||
|
52.529432
|
||||||
|
],
|
||||||
|
"hint": "WIQBgL6mAoAEAAAABgAAAAAAAAA7AAAAhU6PQHvHj0IAAAAAQbyYQgQAAAAGAAAAAAAAADsAAADMAAAAf27MABiJIQOCbswA_4ghAwAAXwVs52D3",
|
||||||
|
"name": "Torstraße"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": [
|
||||||
|
13.428554,
|
||||||
|
52.523239
|
||||||
|
],
|
||||||
|
"hint": "7UcAgP___38fAAAAUQAAACYAAABTAAAAhSQKQrXq5kKRbiZCWJo_Qx8AAABRAAAAJgAAAFMAAADMAAAASufMAOdwIQNL58wA03AhAwMAvxBs52D3",
|
||||||
|
"name": "Platz der Vereinten Nationen"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"durations": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
192.6,
|
||||||
|
382.8
|
||||||
|
],
|
||||||
|
[
|
||||||
|
199,
|
||||||
|
0,
|
||||||
|
283.9
|
||||||
|
],
|
||||||
|
[
|
||||||
|
344.7,
|
||||||
|
222.3,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"destinations": [
|
||||||
|
{
|
||||||
|
"location": [
|
||||||
|
13.3888,
|
||||||
|
52.517033
|
||||||
|
],
|
||||||
|
"hint": "PAMAgEVJAoAUAAAAIAAAAAcAAAAAAAAArss0Qa7LNEHiVIRA4lSEQAoAAAAQAAAABAAAAAAAAADMAAAAAEzMAKlYIQM8TMwArVghAwEA3wps52D3",
|
||||||
|
"name": "Friedrichstraße"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": [
|
||||||
|
13.397631,
|
||||||
|
52.529432
|
||||||
|
],
|
||||||
|
"hint": "WIQBgL6mAoAEAAAABgAAAAAAAAA7AAAAhU6PQHvHj0IAAAAAQbyYQgQAAAAGAAAAAAAAADsAAADMAAAAf27MABiJIQOCbswA_4ghAwAAXwVs52D3",
|
||||||
|
"name": "Torstraße"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": [
|
||||||
|
13.428554,
|
||||||
|
52.523239
|
||||||
|
],
|
||||||
|
"hint": "7UcAgP___38fAAAAUQAAACYAAABTAAAAhSQKQrXq5kKRbiZCWJo_Qx8AAABRAAAAJgAAAFMAAADMAAAASufMAOdwIQNL58wA03AhAwMAvxBs52D3",
|
||||||
|
"name": "Platz der Vereinten Nationen"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"code": "Ok",
|
||||||
|
"distances": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1886.89,
|
||||||
|
3791.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1824,
|
||||||
|
0,
|
||||||
|
2838.09
|
||||||
|
],
|
||||||
|
[
|
||||||
|
3275.36,
|
||||||
|
2361.73,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Match service
|
### Match service
|
||||||
|
|
||||||
Map matching matches/snaps given GPS points to the road network in the most plausible way.
|
Map matching matches/snaps given GPS points to the road network in the most plausible way.
|
||||||
@@ -534,6 +656,7 @@ With `steps=false` and `annotations=true`:
|
|||||||
"distance": [5,5,10,5,5],
|
"distance": [5,5,10,5,5],
|
||||||
"duration": [15,15,40,15,15],
|
"duration": [15,15,40,15,15],
|
||||||
"datasources": [1,0,0,0,1],
|
"datasources": [1,0,0,0,1],
|
||||||
|
"metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] },
|
||||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
|
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
|
||||||
"speed": [0.3, 0.3, 0.3, 0.3, 0.3]
|
"speed": [0.3, 0.3, 0.3, 0.3, 0.3]
|
||||||
}
|
}
|
||||||
@@ -548,10 +671,12 @@ Annotation of the whole route leg with fine-grained information about each segme
|
|||||||
|
|
||||||
- `distance`: The distance, in metres, between each pair of coordinates
|
- `distance`: The distance, in metres, between each pair of coordinates
|
||||||
- `duration`: The duration between each pair of coordinates, in seconds. Does not include the duration of any turns.
|
- `duration`: The duration between each pair of coordinates, in seconds. Does not include the duration of any turns.
|
||||||
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract`
|
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`. String-like names are in the `metadata.datasource_names` array.
|
||||||
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
|
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
|
||||||
- `weight`: The weights between each pair of coordinates. Does not include any turn costs.
|
- `weight`: The weights between each pair of coordinates. Does not include any turn costs.
|
||||||
- `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place
|
- `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place
|
||||||
|
- `metadata`: Metadata related to other annotations
|
||||||
|
- `datasource_names`: The names of the datasources used for the speed between each pair of coordinates. `lua profile` is the default profile, other values arethe filenames supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
@@ -560,6 +685,7 @@ Annotation of the whole route leg with fine-grained information about each segme
|
|||||||
"distance": [5,5,10,5,5],
|
"distance": [5,5,10,5,5],
|
||||||
"duration": [15,15,40,15,15],
|
"duration": [15,15,40,15,15],
|
||||||
"datasources": [1,0,0,0,1],
|
"datasources": [1,0,0,0,1],
|
||||||
|
"metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] },
|
||||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
|
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
|
||||||
"weight": [15,15,40,15,15]
|
"weight": [15,15,40,15,15]
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -25,6 +25,7 @@ var osrm = new OSRM('network.osrm');
|
|||||||
Make sure you prepared the dataset with the correct toolchain.
|
Make sure you prepared the dataset with the correct toolchain.
|
||||||
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
|
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
|
||||||
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
|
||||||
|
- `options.memory_file` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Path to a file on disk to store the memory using mmap.
|
||||||
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
|
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
|
||||||
- `options.max_locations_trip` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in trip query (default: unlimited).
|
- `options.max_locations_trip` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in trip query (default: unlimited).
|
||||||
- `options.max_locations_viaroute` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in viaroute query (default: unlimited).
|
- `options.max_locations_viaroute` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in viaroute query (default: unlimited).
|
||||||
@@ -61,7 +62,7 @@ Returns the fastest route between two or more coordinates while visiting the way
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var osrm = new OSRM("berlin-latest.osrm");
|
var osrm = new OSRM("berlin-latest.osrm");
|
||||||
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
|
osrm.route({coordinates: [[13.438640,52.519930], [13.415852,52.513191]]}, function(err, result) {
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
|
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
|
||||||
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
|
||||||
@@ -109,8 +110,8 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
|
|||||||
|
|
||||||
### table
|
### table
|
||||||
|
|
||||||
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
|
Computes duration table for the given locations. Allows for both symmetric and asymmetric
|
||||||
tables.
|
tables. Optionally returns distance table.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -68,7 +68,7 @@ If you want to prioritize certain streets, increase the rate on these.
|
|||||||
|
|
||||||
## Elements
|
## Elements
|
||||||
### api_version
|
### api_version
|
||||||
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 2.
|
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 4.
|
||||||
|
|
||||||
### Library files
|
### Library files
|
||||||
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
|
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
|
||||||
@@ -224,8 +224,8 @@ source_highway_turn_classification | Read | Integer |
|
|||||||
source_access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15))
|
source_access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15))
|
||||||
source_speed | Read | Integer | Speed on this source road in km/h
|
source_speed | Read | Integer | Speed on this source road in km/h
|
||||||
source_priority_class | Read | Enum | The type of road priority class of the source. Defined in `include/extractor/guidance/road_classification.hpp`
|
source_priority_class | Read | Enum | The type of road priority class of the source. Defined in `include/extractor/guidance/road_classification.hpp`
|
||||||
target_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
|
target_restricted | Read | Boolean | Is the target a restricted access road? (See definition in `process_way`)
|
||||||
target_mode | Read | Enum | Travel mode before the turn. Defined in `include/extractor/travel_mode.hpp`
|
target_mode | Read | Enum | Travel mode after the turn. Defined in `include/extractor/travel_mode.hpp`
|
||||||
target_is_motorway | Read | Boolean | Is the target road a motorway?
|
target_is_motorway | Read | Boolean | Is the target road a motorway?
|
||||||
target_is_link | Read | Boolean | Is the target road a link?
|
target_is_link | Read | Boolean | Is the target road a link?
|
||||||
target_number_of_lanes | Read | Integer | How many lanes does the target road have? (default when not tagged: 0)
|
target_number_of_lanes | Read | Integer | How many lanes does the target road have? (default when not tagged: 0)
|
||||||
|
|||||||
+8
-6
@@ -43,12 +43,14 @@ We may introduce forward-compatible changes: query parameters and response prope
|
|||||||
|
|
||||||
1. Check out the appropriate release branch `x.y`
|
1. Check out the appropriate release branch `x.y`
|
||||||
2. Make sure `CHANGELOG.md` is up to date.
|
2. Make sure `CHANGELOG.md` is up to date.
|
||||||
3. Make sure the OSRM version in `CMakeLists.txt` is up to date
|
3. Make sure the `package.json` on branch `x.y` has been committed.
|
||||||
4. Make sure the `package.json` is up to date.
|
4. Make sure all tests are passing (e.g. Travis CI gives you a :green_apple:)
|
||||||
5. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
|
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries. Commit should be one in which the `package.json` version matches the version you want to release.
|
||||||
6. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
|
6. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
|
||||||
7. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
|
7. Push tags and commits: `git push; git push --tags`
|
||||||
8. Push tags and commits: `git push; git push --tags`
|
8. On https://github.com/Project-OSRM/osrm-backend/releases press `Draft a new release`,
|
||||||
|
write the release tag `vx.y.z` in the `Tag version` field, write the changelog entries in the `Describe this release` field
|
||||||
|
and press `Publish release`.
|
||||||
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
|
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
|
||||||
10. Wait until the travis build has been completed and check if the node binaries were published by doing:
|
10. Wait until the travis build has been completed and check if the node binaries were published by doing:
|
||||||
`rm -rf node_modules && npm install` locally.
|
`rm -rf node_modules && npm install` locally.
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
@routing @bicycle @mode
|
||||||
|
Feature: Bicycle - Mode flag
|
||||||
|
Background:
|
||||||
|
Given the profile "bicycle"
|
||||||
|
|
||||||
|
Scenario: Bicycle - We tag ferries with a class
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | route |
|
||||||
|
| ab | primary | |
|
||||||
|
| bc | | ferry |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | d | ab,bc,cd,cd | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
|
||||||
|
| d | a | cd,bc,ab,ab | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
|
||||||
|
| c | a | bc,ab,ab | depart,notification left,arrive | [(ferry)],[()],[()] |
|
||||||
|
| d | b | cd,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
|
||||||
|
| a | c | ab,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
|
||||||
|
| b | d | bc,cd,cd | depart,notification left,arrive | [(ferry)],[()],[()] |
|
||||||
|
|
||||||
|
Scenario: Bicycle - We tag tunnel with a class
|
||||||
|
Background:
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | tunnel |
|
||||||
|
| ab | no |
|
||||||
|
| bc | yes |
|
||||||
|
| cd | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | d | ab,bc,cd,cd | depart,new name right,new name left,arrive | [()],[(tunnel)],[()],[()] |
|
||||||
|
|
||||||
|
Scenario: Bicycle - We tag classes without intersections
|
||||||
|
Background:
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | tunnel |
|
||||||
|
| ab | road | |
|
||||||
|
| bc | road | yes |
|
||||||
|
| cd | road | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | d | road,road | depart,arrive | [(),(tunnel),()],[()] |
|
||||||
|
|
||||||
|
Scenario: Bicycle - From roundabout on ferry
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
c
|
||||||
|
/ \
|
||||||
|
a---b d---f--h
|
||||||
|
\ /
|
||||||
|
e
|
||||||
|
|
|
||||||
|
g
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway | highway | junction | route |
|
||||||
|
| ab | yes | service | | |
|
||||||
|
| cb | yes | service | roundabout | |
|
||||||
|
| dc | yes | service | roundabout | |
|
||||||
|
| be | yes | service | roundabout | |
|
||||||
|
| ed | yes | service | roundabout | |
|
||||||
|
| eg | yes | service | | |
|
||||||
|
| df | | | | ferry |
|
||||||
|
| fh | yes | service | | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | h | ab,df,df,fh,fh | depart,roundabout-exit-2,exit roundabout slight right,notification straight,arrive | [()],[(),()],[(ferry)],[()],[()] |
|
||||||
@@ -46,12 +46,14 @@ Feature: Bike - Cycle tracks/lanes
|
|||||||
| primary | | | | x | x |
|
| primary | | | | x | x |
|
||||||
| motorway | | | | | |
|
| motorway | | | | | |
|
||||||
| motorway | track | | | x | |
|
| motorway | track | | | x | |
|
||||||
| motorway | opposite | | | | x |
|
| motorway | opposite | | | x | x |
|
||||||
| motorway | | track | | | x |
|
| motorway | | track | | x | |
|
||||||
| motorway | | opposite | | | x |
|
| motorway | | opposite | | x | x |
|
||||||
| motorway | | | track | x | |
|
| motorway | | | track | x | |
|
||||||
| motorway | | | opposite | x | |
|
| motorway | | | opposite | x | x |
|
||||||
| motorway | | track | track | x | x |
|
# motorways are implicit oneways and cycleway tracks next to oneways always
|
||||||
|
# follow the oneway direction (unless tagged as opposite)
|
||||||
|
| motorway | | track | track | x | |
|
||||||
| motorway | | opposite | opposite | x | x |
|
| motorway | | opposite | opposite | x | x |
|
||||||
| motorway | | track | opposite | x | x |
|
| motorway | | track | opposite | x | x |
|
||||||
| motorway | | opposite | track | x | x |
|
| motorway | | opposite | track | x | x |
|
||||||
@@ -92,6 +94,6 @@ Feature: Bike - Cycle tracks/lanes
|
|||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | cycleway | oneway | forw | backw |
|
| highway | cycleway | oneway | forw | backw |
|
||||||
| motorway | track | yes | 15 km/h | |
|
| motorway | track | yes | 15 km/h | |
|
||||||
| residential | track | yes | 15 km/h | 6 km/h +-1 |
|
| residential | track | yes | 15 km/h | 4 km/h +-1 |
|
||||||
| cycleway | track | yes | 15 km/h | 6 km/h +-1 |
|
| cycleway | track | yes | 15 km/h | 4 km/h +-1 |
|
||||||
| footway | track | yes | 15 km/h | 6 km/h +-1 |
|
| footway | track | yes | 15 km/h | 4 km/h +-1 |
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
@routing @bicycle @exclude
|
||||||
|
Feature: Bicycle - Exclude flags
|
||||||
|
Background:
|
||||||
|
Given the profile file "bicycle" initialized with
|
||||||
|
"""
|
||||||
|
profile.excludable = Sequence { Set { 'ferry' } }
|
||||||
|
"""
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a....b~~~~~c...f
|
||||||
|
: :
|
||||||
|
d.....e
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | route | duration | # |
|
||||||
|
| ab | service | | | always drivable |
|
||||||
|
| bc | | ferry | 00:00:01 | not drivable for exclude=ferry, but fast. |
|
||||||
|
| bd | service | | | always drivable |
|
||||||
|
| de | service | | | always drivable |
|
||||||
|
| ec | service | | | always drivable |
|
||||||
|
| cf | service | | | always drivable |
|
||||||
|
|
||||||
|
Scenario: Bicycle - exclude nothing
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | f | ab,bc,cf,cf |
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | matchings | duration |
|
||||||
|
| abcf | abcf | 109 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | f |
|
||||||
|
| a | 0 | 109 |
|
||||||
|
| f | 109 | 0 |
|
||||||
|
|
||||||
|
Scenario: Bicycle - exclude ferry
|
||||||
|
Given the query options
|
||||||
|
| exclude | ferry |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | f | ab,bd,de,ec,cf,cf |
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | matchings | duration |
|
||||||
|
| abcf | abcf | 301.2 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | f |
|
||||||
|
| a | 0 | 301 +- 1 |
|
||||||
|
| f | 301.2 +- 1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
@@ -141,5 +141,12 @@ Feature: Bike - Oneway streets
|
|||||||
| highway | oneway | cycleway:left | cycleway:right | forw | backw |
|
| highway | oneway | cycleway:left | cycleway:right | forw | backw |
|
||||||
| primary | yes | | | cycling | pushing bike |
|
| primary | yes | | | cycling | pushing bike |
|
||||||
| primary | yes | | track | cycling | pushing bike |
|
| primary | yes | | track | cycling | pushing bike |
|
||||||
| primary | yes | track | | cycling | cycling |
|
| primary | yes | track | | cycling | pushing bike |
|
||||||
| primary | yes | track | track | cycling | cycling |
|
| primary | yes | track | track | cycling | pushing bike |
|
||||||
|
|
||||||
|
Scenario: Bike - Left/right cycleways on any oneways
|
||||||
|
Then routability should be
|
||||||
|
| foot | oneway | cycleway:left | cycleway:right | forw | backw |
|
||||||
|
| no | yes | track | | cycling | |
|
||||||
|
| yes | yes | track | | cycling | pushing bike |
|
||||||
|
| yes | -1 | track | | pushing bike | cycling |
|
||||||
@@ -11,15 +11,15 @@ Feature: Bicycle - Adds penalties to unsafe roads
|
|||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | cycleway | forw | backw | forw_rate | backw_rate |
|
| highway | cycleway | forw | backw | forw_rate | backw_rate |
|
||||||
| motorway | | | | | |
|
| motorway | | | | | |
|
||||||
| primary | | 15 km/h | 15 km/h | 2.9 | 2.9 |
|
| primary | | 15 km/h | 15 km/h | 2.1 | 2.1 |
|
||||||
| secondary | | 15 km/h | 15 km/h | 3.1 | 3.1 |
|
| secondary | | 15 km/h | 15 km/h | 2.7 | 2.7 |
|
||||||
| tertiary | | 15 km/h | 15 km/h | 3.3 | 3.3 |
|
| tertiary | | 15 km/h | 15 km/h | 3.3 | 3.3 |
|
||||||
| primary_link | | 15 km/h | 15 km/h | 2.9 | 2.9 |
|
| primary_link | | 15 km/h | 15 km/h | 2.1 | 2.1 |
|
||||||
| secondary_link | | 15 km/h | 15 km/h | 3.1 | 3.1 |
|
| secondary_link | | 15 km/h | 15 km/h | 2.7 | 2.7 |
|
||||||
| tertiary_link | | 15 km/h | 15 km/h | 3.3 | 3.3 |
|
| tertiary_link | | 15 km/h | 15 km/h | 3.3 | 3.3 |
|
||||||
| residential | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| residential | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| cycleway | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| cycleway | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| footway | | 6 km/h +-1 | 6 km/h +-1 | 1.7 | 1.7 |
|
| footway | | 4 km/h +-1 | 4 km/h +-1 | 1.1 | 1.1 |
|
||||||
|
|
||||||
Scenario: Bike - Apply no penalties to ways with cycleways
|
Scenario: Bike - Apply no penalties to ways with cycleways
|
||||||
Then routability should be
|
Then routability should be
|
||||||
@@ -51,49 +51,49 @@ Feature: Bicycle - Adds penalties to unsafe roads
|
|||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | cycleway:right | cycleway:left | forw | backw | forw_rate | backw_rate |
|
| highway | cycleway:right | cycleway:left | forw | backw | forw_rate | backw_rate |
|
||||||
| motorway | track | | 15 km/h | | 4.2 | |
|
| motorway | track | | 15 km/h | | 4.2 | |
|
||||||
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
|
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.1 |
|
||||||
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
|
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 2.7 |
|
||||||
| tertiary | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
| tertiary | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
||||||
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
|
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.1 |
|
||||||
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
|
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.7 |
|
||||||
| tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
| tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
||||||
| residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| footway | track | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 |
|
| footway | track | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 |
|
||||||
| motorway | | track | | 15 km/h | | 4.2 |
|
| motorway | | track | 15 km/h | | 4.2 | |
|
||||||
| primary | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
|
| primary | | track | 15 km/h | 15 km/h | 2.1 | 4.2 |
|
||||||
| secondary | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
|
| secondary | | track | 15 km/h | 15 km/h | 2.7 | 4.2 |
|
||||||
| tertiary | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
| tertiary | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
||||||
| primary_link | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
|
| primary_link | | track | 15 km/h | 15 km/h | 2.1 | 4.2 |
|
||||||
| secondary_link | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
|
| secondary_link | | track | 15 km/h | 15 km/h | 2.7 | 4.2 |
|
||||||
| tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
| tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
||||||
| residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| footway | | track | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 |
|
| footway | | track | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 |
|
||||||
| motorway | lane | | 15 km/h | | 4.2 | |
|
| motorway | lane | | 15 km/h | | 4.2 | |
|
||||||
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
|
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
|
||||||
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
|
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 |
|
||||||
| tertiary | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
| tertiary | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
||||||
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
|
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
|
||||||
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
|
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 |
|
||||||
| tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
| tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
|
||||||
| residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 |
|
| residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 |
|
||||||
| cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| footway | lane | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 |
|
| footway | lane | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 |
|
||||||
| motorway | | lane | | 15 km/h | | 4.2 |
|
| motorway | | lane | 15 km/h | | 4.2 | |
|
||||||
| primary | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
|
| primary | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
|
||||||
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 3.1 | 4.2 |
|
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 2.7 | 4.2 |
|
||||||
| tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
| tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
||||||
| primary_link | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
|
| primary_link | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
|
||||||
| secondary_link | | lane | 15 km/h | 15 km/h | 3.1 | 4.2 |
|
| secondary_link | | lane | 15 km/h | 15 km/h | 2.7 | 4.2 |
|
||||||
| tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
| tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
||||||
| residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| cycleway | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| cycleway | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| footway | | lane | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 |
|
| footway | | lane | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 |
|
||||||
| motorway | shared_lane | | 15 km/h | | 4.2 | |
|
| motorway | shared_lane | | 15 km/h | | 4.2 | |
|
||||||
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
|
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
|
||||||
| motorway | | shared_lane | | 15 km/h | | 4.2 |
|
| motorway | | shared_lane | 15 km/h | | 4.2 | |
|
||||||
| primary | | shared_lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
|
| primary | | shared_lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Bike - Don't apply penalties for all kind of cycleways
|
Scenario: Bike - Don't apply penalties for all kind of cycleways
|
||||||
@@ -101,4 +101,4 @@ Feature: Bicycle - Adds penalties to unsafe roads
|
|||||||
| highway | cycleway | forw | backw | forw_rate | backw_rate |
|
| highway | cycleway | forw | backw | forw_rate | backw_rate |
|
||||||
| tertiary | shared_lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| tertiary | shared_lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| tertiary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
| tertiary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
|
||||||
| tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 4.2 |
|
| tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 3.3 |
|
||||||
|
|||||||
@@ -54,6 +54,6 @@ Feature: Bike - Surfaces
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | modes | speed |
|
| from | to | route | modes | speed |
|
||||||
| a | b | ab,ab | cycling,cycling | 15 km/h |
|
| a | b | ab,ab | cycling,cycling | 15 km/h |
|
||||||
| b | a | ab,ab | pushing bike,pushing bike | 6 km/h |
|
| b | a | ab,ab | pushing bike,pushing bike | 4 km/h |
|
||||||
| c | d | cd,cd | pushing bike,pushing bike | 6 km/h |
|
| c | d | cd,cd | pushing bike,pushing bike | 4 km/h |
|
||||||
| d | c | cd,cd | pushing bike,pushing bike | 6 km/h |
|
| d | c | cd,cd | pushing bike,pushing bike | 4 km/h |
|
||||||
|
|||||||
@@ -691,14 +691,14 @@ Feature: Car - Turn restrictions
|
|||||||
# """
|
# """
|
||||||
Given the node locations
|
Given the node locations
|
||||||
| node | lat | lon |
|
| node | lat | lon |
|
||||||
| a | 38.9113 | -77.0091 |
|
| a | 38.91124 | -77.00909 |
|
||||||
| b | 38.9108 | -77.0091 |
|
| b | 38.91080 | -77.00909 |
|
||||||
| c | 38.9104 | -77.0091 |
|
| c | 38.91038 | -77.00909 |
|
||||||
| d | 38.9110 | -77.0096 |
|
| d | 38.91105 | -77.00967 |
|
||||||
| e | 38.9106 | -77.0086 |
|
| e | 38.91037 | -77.00807 |
|
||||||
| f | 38.9105 | -77.0090 |
|
| f | 38.91036 | -77.00899 |
|
||||||
| g | 38.9108 | -77.0090 |
|
| g | 38.91076 | -77.00901 |
|
||||||
| h | 38.9113 | -77.0090 |
|
| h | 38.91124 | -77.00900 |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | oneway | name |
|
| nodes | oneway | name |
|
||||||
@@ -719,7 +719,7 @@ Feature: Car - Turn restrictions
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | turns |
|
| from | to | route | turns |
|
||||||
| a | e | cap south,florida nw,florida nw,florida ne | depart,turn right,continue uturn,arrive |
|
| 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 |
|
| f | d | cap north,florida nw,florida nw | depart,turn left,arrive |
|
||||||
| e | c | florida ne,florida nw,cap south,cap south | depart,continue uturn,turn right,arrive |
|
| e | c | florida ne,florida nw,cap south,cap south | depart,continue uturn,turn right,arrive |
|
||||||
|
|
||||||
@no_turning @conditionals
|
@no_turning @conditionals
|
||||||
@@ -738,14 +738,14 @@ Feature: Car - Turn restrictions
|
|||||||
# """
|
# """
|
||||||
Given the node locations
|
Given the node locations
|
||||||
| node | lat | lon |
|
| node | lat | lon |
|
||||||
| a | 38.9113 | -77.0091 |
|
| a | 38.91124 | -77.00909 |
|
||||||
| b | 38.9108 | -77.0091 |
|
| b | 38.91080 | -77.00909 |
|
||||||
| c | 38.9104 | -77.0091 |
|
| c | 38.91038 | -77.00909 |
|
||||||
| d | 38.9110 | -77.0096 |
|
| d | 38.91105 | -77.00967 |
|
||||||
| e | 38.9106 | -77.0086 |
|
| e | 38.91037 | -77.00807 |
|
||||||
| f | 38.9105 | -77.0090 |
|
| f | 38.91036 | -77.00899 |
|
||||||
| g | 38.9108 | -77.0090 |
|
| g | 38.91076 | -77.00901 |
|
||||||
| h | 38.9113 | -77.0090 |
|
| h | 38.91124 | -77.00900 |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | oneway | name |
|
| nodes | oneway | name |
|
||||||
@@ -765,7 +765,7 @@ Feature: Car - Turn restrictions
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | turns |
|
| from | to | route | turns |
|
||||||
| a | e | cap south,florida,florida ne | depart,turn left,arrive |
|
| a | e | cap south,florida ne,florida ne | depart,turn left,arrive |
|
||||||
| f | d | cap north,florida ne,florida ne,florida nw | depart,turn sharp right,continue uturn,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 |
|
| e | c | florida ne,cap south,cap south | depart,turn left,arrive |
|
||||||
|
|
||||||
|
|||||||
@@ -135,12 +135,12 @@ Feature: Car - Destination only, no passing through
|
|||||||
Scenario: Car - Routing through a parking lot tagged access=destination,service
|
Scenario: Car - Routing through a parking lot tagged access=destination,service
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a----c++++b+++g----h---i
|
a----c++++b+++g------h---i
|
||||||
| + + + |
|
| + + + /
|
||||||
| + + + |
|
| + + + /
|
||||||
| + + + |
|
| + + + /
|
||||||
| d++++e+f /
|
| d++++e+f /
|
||||||
z---------------y
|
z--------------y
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
@@ -155,9 +155,10 @@ Feature: Car - Destination only, no passing through
|
|||||||
| gf | destination | service |
|
| gf | destination | service |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | i | azyhi,azyhi |
|
| a | i | azyhi,azyhi |
|
||||||
| b | f | be,def,def |
|
| b | f | be,def,def |
|
||||||
|
| b | i | cbg,ghi,azyhi,azyhi |
|
||||||
|
|
||||||
Scenario: Car - Disallow snapping to access=private,highway=service
|
Scenario: Car - Disallow snapping to access=private,highway=service
|
||||||
Given a grid size of 20 meters
|
Given a grid size of 20 meters
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ Feature: Bike - Mode flag
|
|||||||
| c | traffic_signals |
|
| c | traffic_signals |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | highway | name | oneway:bicycle |
|
| nodes | highway | name | oneway:bicycle | maxspeed:forward |
|
||||||
| abcd | cycleway | street | |
|
| abcd | cycleway | street | | 4 km/h |
|
||||||
| eb | path | | yes |
|
| eb | path | | yes | |
|
||||||
| icef | tertiary | road | |
|
| icef | tertiary | road | | 4 km/h |
|
||||||
| geh | secondary | street | |
|
| geh | secondary | street | | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
|
|||||||
@@ -35,20 +35,20 @@ Feature: Collapse
|
|||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
||||||
| a,d | first,first | depart,arrive | a,d |
|
| a,d | first,first | depart,arrive | a,d |
|
||||||
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
|
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
|
||||||
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
|
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
|
||||||
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
||||||
| e,h | first,first | depart,arrive | e,h |
|
| e,h | first,first | depart,arrive | e,h |
|
||||||
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
|
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
|
||||||
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
|
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
|
||||||
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
||||||
| k,l | second,second | depart,arrive | k,l |
|
| k,l | second,second | depart,arrive | k,l |
|
||||||
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
|
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
|
||||||
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
|
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
|
||||||
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
||||||
| i,j | second,second | depart,arrive | i,j |
|
| i,j | second,second | depart,arrive | i,j |
|
||||||
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
|
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
|
||||||
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
|
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
|
||||||
|
|
||||||
Scenario: Segregated Intersection, Cross Belonging to Single Street
|
Scenario: Segregated Intersection, Cross Belonging to Single Street
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -74,7 +74,7 @@ Feature: Collapse
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,i | first,second,third,third | depart,turn left,turn slight left,arrive | a,b,e,i |
|
| a,i | first,third,third | depart,turn sharp left,arrive | a,b,i |
|
||||||
|
|
||||||
Scenario: Segregated Intersection, Cross Belonging to Correct Street
|
Scenario: Segregated Intersection, Cross Belonging to Correct Street
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -106,20 +106,20 @@ Feature: Collapse
|
|||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
||||||
| a,d | first,first | depart,arrive | a,d |
|
| a,d | first,first | depart,arrive | a,d |
|
||||||
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
|
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
|
||||||
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
|
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
|
||||||
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
||||||
| e,h | first,first | depart,arrive | e,h |
|
| e,h | first,first | depart,arrive | e,h |
|
||||||
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
|
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
|
||||||
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
|
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
|
||||||
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
||||||
| k,l | second,second | depart,arrive | k,l |
|
| k,l | second,second | depart,arrive | k,l |
|
||||||
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
|
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
|
||||||
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
|
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
|
||||||
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
||||||
| i,j | second,second | depart,arrive | i,j |
|
| i,j | second,second | depart,arrive | i,j |
|
||||||
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
|
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
|
||||||
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
|
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
|
||||||
|
|
||||||
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets
|
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -151,20 +151,20 @@ Feature: Collapse
|
|||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
||||||
| a,d | first,first | depart,arrive | a,d |
|
| a,d | first,first | depart,arrive | a,d |
|
||||||
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
|
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
|
||||||
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
|
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
|
||||||
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
||||||
| e,h | first,first | depart,arrive | e,h |
|
| e,h | first,first | depart,arrive | e,h |
|
||||||
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
|
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
|
||||||
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
|
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
|
||||||
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
||||||
| k,l | second,second | depart,arrive | k,l |
|
| k,l | second,second | depart,arrive | k,l |
|
||||||
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
|
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
|
||||||
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
|
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
|
||||||
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
||||||
| i,j | second,second | depart,arrive | i,j |
|
| i,j | second,second | depart,arrive | i,j |
|
||||||
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
|
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
|
||||||
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
|
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
|
||||||
|
|
||||||
Scenario: Partly Segregated Intersection, Two Segregated Roads
|
Scenario: Partly Segregated Intersection, Two Segregated Roads
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -209,11 +209,11 @@ Feature: Collapse
|
|||||||
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
|
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
|
||||||
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
|
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
|
||||||
| g,j | second,second | depart,arrive | g,j |
|
| g,j | second,second | depart,arrive | g,j |
|
||||||
| g,f | second,first,first | depart,turn left,arrive | g,e,f |
|
| g,f | second,first,first | depart,turn left,arrive | g,b,f |
|
||||||
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
|
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
|
||||||
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
|
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
|
||||||
| i,h | second,second | depart,arrive | i,h |
|
| i,h | second,second | depart,arrive | i,h |
|
||||||
| i,c | second,first,first | depart,turn left,arrive | i,b,c |
|
| i,c | second,first,first | depart,turn left,arrive | i,e,c |
|
||||||
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
|
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
|
||||||
|
|
||||||
Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second
|
Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second
|
||||||
@@ -263,11 +263,11 @@ Feature: Collapse
|
|||||||
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
|
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
|
||||||
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
|
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
|
||||||
| g,j | second,second | depart,arrive | g,j |
|
| g,j | second,second | depart,arrive | g,j |
|
||||||
| g,f | second,first,first | depart,turn left,arrive | g,e,f |
|
| g,f | second,first,first | depart,turn left,arrive | g,b,f |
|
||||||
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
|
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
|
||||||
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
|
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
|
||||||
| i,h | second,second | depart,arrive | i,h |
|
| i,h | second,second | depart,arrive | i,h |
|
||||||
| i,c | second,first,first | depart,turn left,arrive | i,b,c |
|
| i,c | second,first,first | depart,turn left,arrive | i,e,c |
|
||||||
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
|
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
|
||||||
|
|
||||||
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles
|
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles
|
||||||
@@ -300,20 +300,20 @@ Feature: Collapse
|
|||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
||||||
| a,d | first,first | depart,arrive | a,d |
|
| a,d | first,first | depart,arrive | a,d |
|
||||||
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
|
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
|
||||||
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
|
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
|
||||||
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
||||||
| e,h | first,first | depart,arrive | e,h |
|
| e,h | first,first | depart,arrive | e,h |
|
||||||
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
|
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
|
||||||
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
|
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
|
||||||
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
||||||
| k,l | second,second | depart,arrive | k,l |
|
| k,l | second,second | depart,arrive | k,l |
|
||||||
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
|
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
|
||||||
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
|
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
|
||||||
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
||||||
| i,j | second,second | depart,arrive | i,j |
|
| i,j | second,second | depart,arrive | i,j |
|
||||||
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
|
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
|
||||||
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
|
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
|
||||||
|
|
||||||
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2)
|
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2)
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -345,28 +345,29 @@ Feature: Collapse
|
|||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
|
||||||
| a,d | first,first | depart,arrive | a,d |
|
| a,d | first,first | depart,arrive | a,d |
|
||||||
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
|
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
|
||||||
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
|
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
|
||||||
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
|
||||||
| e,h | first,first | depart,arrive | e,h |
|
| e,h | first,first | depart,arrive | e,h |
|
||||||
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
|
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
|
||||||
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
|
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
|
||||||
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
|
||||||
| k,l | second,second | depart,arrive | k,l |
|
| k,l | second,second | depart,arrive | k,l |
|
||||||
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
|
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
|
||||||
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
|
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
|
||||||
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
|
||||||
| i,j | second,second | depart,arrive | i,j |
|
| i,j | second,second | depart,arrive | i,j |
|
||||||
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
|
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
|
||||||
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
|
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
|
||||||
|
|
||||||
Scenario: Entering a segregated road
|
Scenario: Entering a segregated road
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a f g
|
h
|
||||||
| | . '
|
a f | g
|
||||||
b-e '
|
| | i '
|
||||||
/ /
|
b-e ' |
|
||||||
|
/ / j
|
||||||
/ /
|
/ /
|
||||||
c d
|
c d
|
||||||
"""
|
"""
|
||||||
@@ -376,7 +377,8 @@ Feature: Collapse
|
|||||||
| abc | primary | first | yes |
|
| abc | primary | first | yes |
|
||||||
| def | primary | first | yes |
|
| def | primary | first | yes |
|
||||||
| be | primary | first | no |
|
| be | primary | first | no |
|
||||||
| ge | primary | second | no |
|
| gie | primary | second | no |
|
||||||
|
| hij | primary | maple | no |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
@@ -385,7 +387,7 @@ Feature: Collapse
|
|||||||
| a,g | first,second,second | depart,turn left,arrive | a,b,g |
|
| a,g | first,second,second | depart,turn left,arrive | a,b,g |
|
||||||
| d,g | first,second,second | depart,turn right,arrive | d,e,g |
|
| d,g | first,second,second | depart,turn right,arrive | d,e,g |
|
||||||
| g,f | second,first,first | depart,turn right,arrive | g,e,f |
|
| g,f | second,first,first | depart,turn right,arrive | g,e,f |
|
||||||
| g,c | second,first,first | depart,turn left,arrive | g,e,c |
|
| g,c | second,first,first | depart,end of road left,arrive | g,e,c |
|
||||||
|
|
||||||
Scenario: Do not collapse turning roads
|
Scenario: Do not collapse turning roads
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -603,7 +605,7 @@ Feature: Collapse
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| i,h | in,road,road | depart,turn left,arrive | i,f,h |
|
| i,h | in,road,road | depart,turn slight left,arrive | i,c,h |
|
||||||
| a,d | road,road | depart,arrive | a,d |
|
| a,d | road,road | depart,arrive | a,d |
|
||||||
| a,j | road,out,out | depart,turn slight right,arrive | a,b,j |
|
| a,j | road,out,out | depart,turn slight right,arrive | a,b,j |
|
||||||
|
|
||||||
@@ -1010,7 +1012,7 @@ Feature: Collapse
|
|||||||
| f,j | hohe,hohe | depart,arrive | f,j |
|
| f,j | hohe,hohe | depart,arrive | f,j |
|
||||||
| a,t | hohe,a100,a100 | depart,on ramp right,arrive | a,b,t |
|
| a,t | hohe,a100,a100 | depart,on ramp right,arrive | a,b,t |
|
||||||
| f,e | | | |
|
| f,e | | | |
|
||||||
| q,j | a100,hohe,hohe | depart,turn right,arrive | q,p,j |
|
| q,j | a100,hohe,hohe | depart,turn right,arrive | q,i,j |
|
||||||
| q,e | a100,hohebruecke,hohe | depart,turn left,arrive | q,p,e |
|
| q,e | a100,hohebruecke,hohe | depart,turn left,arrive | q,p,e |
|
||||||
|
|
||||||
Scenario: Forking before a turn (forky)
|
Scenario: Forking before a turn (forky)
|
||||||
|
|||||||
@@ -687,7 +687,7 @@ Feature: Slipways and Dedicated Turn Lanes
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| s,f | sabc,ae,dbef,dbef | depart,turn slight right,turn right,arrive | s,a,e,f |
|
| s,f | sabc,ae,dbef,dbef | depart,fork slight right,turn right,arrive | s,a,e,f |
|
||||||
|
|
||||||
@sliproads
|
@sliproads
|
||||||
Scenario: Traffic Signal on Sliproad
|
Scenario: Traffic Signal on Sliproad
|
||||||
|
|||||||
@@ -13,19 +13,23 @@ Feature: Divided road entry
|
|||||||
d-------e-----f
|
d-------e-----f
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
g
|
i---g---j
|
||||||
|
|
|
||||||
|
|
|
||||||
|
h
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name | highway | oneway |
|
| nodes | name | highway | oneway |
|
||||||
| abc | main st | residential | -1 |
|
| abc | main st | residential | -1 |
|
||||||
| def | main st | residential | yes |
|
| def | main st | residential | yes |
|
||||||
| be | main st | residential | |
|
| be | main st | residential | |
|
||||||
| eg | side st | residential | |
|
| egh | side st | residential | |
|
||||||
|
| igj | maple st | residential | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| g,a | side st,main st,main st| depart,end of road left,arrive |
|
| h,a | side st,main st,main st| depart,end of road left,arrive |
|
||||||
|
|
||||||
|
|
||||||
# Similar to previous one, but the joining way is tagged with the side-street name
|
# Similar to previous one, but the joining way is tagged with the side-street name
|
||||||
@@ -37,18 +41,22 @@ Feature: Divided road entry
|
|||||||
d-------e-----f
|
d-------e-----f
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
g
|
i---g---j
|
||||||
|
|
|
||||||
|
|
|
||||||
|
h
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name | highway | oneway |
|
| nodes | name | highway | oneway |
|
||||||
| abc | main st | residential | -1 |
|
| abc | main st | residential | -1 |
|
||||||
| def | main st | residential | yes |
|
| def | main st | residential | yes |
|
||||||
| beg | side st | residential | |
|
| begh | side st | residential | |
|
||||||
|
| igj | maple st | residential | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| g,a | side st,main st,main st| depart,end of road left,arrive |
|
| h,a | side st,main st,main st| depart,end of road left,arrive |
|
||||||
|
|
||||||
|
|
||||||
# Center join named after crossroad
|
# Center join named after crossroad
|
||||||
@@ -100,3 +108,32 @@ Feature: Divided road entry
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| g,a | side st,main st,main st| depart,turn left,arrive |
|
| g,a | side st,main st,main st| depart,turn left,arrive |
|
||||||
|
|
||||||
|
# Verify end of road left turn across divided roads
|
||||||
|
Scenario: Join on a divided road, named after the side street
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-----h--b-----c
|
||||||
|
| |
|
||||||
|
d-----i--e-----f
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
m---j--g---n
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
k l
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | highway | oneway |
|
||||||
|
| ahbc | main st | residential | -1 |
|
||||||
|
| dief | main st | residential | yes |
|
||||||
|
| begl | side st | residential | -1 |
|
||||||
|
| hijk | side st | residential | yes |
|
||||||
|
| mjgn | maple st| residential | no |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| l,a | side st,main st,main st| depart,end of road left,arrive |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,3 +46,23 @@ Feature: Driveways intersections
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations |
|
||||||
| a,d | ,second | depart,arrive | a,d |
|
| a,d | ,second | depart,arrive | a,d |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Road with a turn to service road
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
/-----------------e
|
||||||
|
a---b------------------c
|
||||||
|
`-----------------d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway |
|
||||||
|
| abc | trunk | road | yes |
|
||||||
|
| bd | service | serv | yes |
|
||||||
|
| be | service | serv | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns | locations |
|
||||||
|
| a,d | road,serv,serv | depart,turn slight right,arrive | a,b,d |
|
||||||
|
| a,e | road,serv,serv | depart,turn slight left,arrive | a,b,e |
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
@guidance
|
||||||
|
Feature: Internal Intersection Model
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
|
||||||
|
Scenario: Dual-carriage way intersection
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
| |
|
||||||
|
c--d--e--f
|
||||||
|
| |
|
||||||
|
g--h--i--j
|
||||||
|
| |
|
||||||
|
k l
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway | name |
|
||||||
|
| adhk | yes | Broken Land Parkway |
|
||||||
|
| lieb | yes | Broken Land Parkway |
|
||||||
|
| fed | yes | Snowden River Parkway |
|
||||||
|
| dc | yes | Patuxent Woods Drive |
|
||||||
|
| gh | yes | Patuxent Woods Drive |
|
||||||
|
| hij | yes | Snowden River Parkway |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns | # |
|
||||||
|
| a,k | Broken Land Parkway,Broken Land Parkway | depart,arrive ||
|
||||||
|
| l,b | Broken Land Parkway,Broken Land Parkway | depart,arrive ||
|
||||||
|
# | g,j | Patuxent Woods Drive,Snowden River Parkway,Snowden River Parkway | depart,continue,arrive | did not work as expected - might be another issue to handle in post process? |
|
||||||
|
# | f,c | Snowden River Parkway,Patuxent Woods Drive,Patuxent Woods Drive | depart,continue,arrive | did not work as expected - might be another issue to handle in post process? |
|
||||||
|
| a,c | Broken Land Parkway,Patuxent Woods Drive,Patuxent Woods Drive | depart,turn right,arrive ||
|
||||||
|
| g,k | Patuxent Woods Drive,Broken Land Parkway,Broken Land Parkway | depart,turn right,arrive ||
|
||||||
|
| l,j | Broken Land Parkway,Snowden River Parkway,Snowden River Parkway | depart,turn right,arrive ||
|
||||||
|
| f,b | Snowden River Parkway,Broken Land Parkway,Broken Land Parkway | depart,turn right,arrive ||
|
||||||
|
| a,j | Broken Land Parkway,Snowden River Parkway,Snowden River Parkway | depart,turn left,arrive ||
|
||||||
|
| g,b | Patuxent Woods Drive,Broken Land Parkway,Broken Land Parkway | depart,turn left,arrive ||
|
||||||
|
| l,c | Broken Land Parkway,Patuxent Woods Drive,Patuxent Woods Drive | depart,turn left,arrive ||
|
||||||
|
| f,k | Snowden River Parkway,Broken Land Parkway,Broken Land Parkway | depart,turn left,arrive ||
|
||||||
|
| a,b | Broken Land Parkway,Broken Land Parkway,Broken Land Parkway | depart,continue uturn,arrive ||
|
||||||
|
| g,c | Patuxent Woods Drive,Patuxent Woods Drive,Patuxent Woods Drive | depart,continue uturn,arrive ||
|
||||||
|
| l,k | Broken Land Parkway,Broken Land Parkway,Broken Land Parkway | depart,continue uturn,arrive ||
|
||||||
|
| f,j | Snowden River Parkway,Snowden River Parkway,Snowden River Parkway | depart,continue uturn,arrive ||
|
||||||
@@ -64,9 +64,9 @@ Feature: Exceptions for routing onto low-priority roads
|
|||||||
| bc | service | |
|
| bc | service | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| e,c | service, | depart,arrive |
|
| e,c | service, | depart,arrive |
|
||||||
| c,e | ,service,service | depart,turn straight,arrive |
|
| c,e | ,service | depart,arrive |
|
||||||
|
|
||||||
Scenario: Straight onto low-priority
|
Scenario: Straight onto low-priority
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ Feature: Maneuver tag support
|
|||||||
| maneuver | abc | c | cgi | turn | sharp_right |
|
| maneuver | abc | c | cgi | turn | sharp_right |
|
||||||
| maneuver | hij | i | cde | turn | sharp_left |
|
| maneuver | hij | i | cde | turn | sharp_left |
|
||||||
| maneuver | abc | c | cde | turn | slight_left |
|
| maneuver | abc | c | cde | turn | slight_left |
|
||||||
|
| maneuver | cde | c | cgi | turn | straight |
|
||||||
|
| manoeuvre| cgi | c | abc | turn | right |
|
||||||
|
|
||||||
|
And the relations
|
||||||
|
| type | way:from | node:via | way:to | manoeuvre | maneuver | direction |
|
||||||
|
| maneuver | cgi | c | cde | fork | turn | slight_right |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
@@ -35,6 +41,9 @@ Feature: Maneuver tag support
|
|||||||
| b,g | A Street,C Street,C Street | depart,turn sharp right,arrive |
|
| b,g | A Street,C Street,C Street | depart,turn sharp right,arrive |
|
||||||
# Testing re-awakening suppressed turns
|
# Testing re-awakening suppressed turns
|
||||||
| a,e | A Street,B Street,B Street | depart,turn slight left,arrive |
|
| a,e | A Street,B Street,B Street | depart,turn slight left,arrive |
|
||||||
|
| e,i | B Street,C Street,C Street | depart,turn straight,arrive |
|
||||||
|
| i,e | C Street,B Street,B Street | depart,fork slight right,arrive |
|
||||||
|
| i,a | C Street,A Street,A Street | depart,turn right,arrive |
|
||||||
|
|
||||||
Scenario: single via-way
|
Scenario: single via-way
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@@ -384,9 +384,9 @@ Feature: Merge Segregated Roads
|
|||||||
| cd | right | no |
|
| cd | right | no |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | intersections |
|
| waypoints | route | intersections |
|
||||||
| a,d | left,circle,circle,right,right | true:90;false:90 true:120 false:270;true:60 true:180 false:300;true:90 false:240 true:270;true:270 |
|
| a,d | left,circle,right,right | true:90,false:90 true:120 false:270;true:60 true:180 false:300;true:90 false:240 true:270;true:270 |
|
||||||
| g,d | bottom,circle,right,right | true:0;true:60 false:180 false:300;true:90 false:240 true:270;true:270 |
|
| g,d | bottom,circle,right,right | true:0;true:60 false:180 false:300;true:90 false:240 true:270;true:270 |
|
||||||
|
|
||||||
Scenario: Middle Island
|
Scenario: Middle Island
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -644,7 +644,7 @@ Feature: Merge Segregated Roads
|
|||||||
| k,j | marianne,albrecht,luise,luise | depart,turn left,turn left,arrive |
|
| k,j | marianne,albrecht,luise,luise | depart,turn left,turn left,arrive |
|
||||||
| k,d | marianne,schwert,schwert | depart,turn right,arrive |
|
| k,d | marianne,schwert,schwert | depart,turn right,arrive |
|
||||||
| i,j | luise,luise | depart,arrive |
|
| i,j | luise,luise | depart,arrive |
|
||||||
| i,d | luise,albrecht,schwert,schwert | depart,turn left,turn straight,arrive |
|
| i,d | luise,albrecht,schwert | depart,turn left,arrive |
|
||||||
| i,l | luise,albrecht,marianne,marianne | depart,turn left,turn left,arrive |
|
| i,l | luise,albrecht,marianne,marianne | depart,turn left,turn left,arrive |
|
||||||
|
|
||||||
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
|
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ Feature: Motorway Guidance
|
|||||||
| a,e | abcde,abcde | depart,arrive |
|
| a,e | abcde,abcde | depart,arrive |
|
||||||
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
|
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
|
||||||
| a,i | abcde,chi,chi | depart,off ramp slight right,arrive |
|
| a,i | abcde,chi,chi | depart,off ramp slight right,arrive |
|
||||||
| f,i | fgc,chi,chi | depart,off ramp right,arrive |
|
| f,i | fgc,chi,chi | depart,off ramp slight right,arrive |
|
||||||
|
|
||||||
Scenario: On And Off Ramp Left
|
Scenario: On And Off Ramp Left
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -221,7 +221,7 @@ Feature: Motorway Guidance
|
|||||||
| a,e | abcde,abcde | depart,arrive |
|
| a,e | abcde,abcde | depart,arrive |
|
||||||
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
|
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
|
||||||
| a,i | abcde,chi,chi | depart,off ramp slight left,arrive |
|
| a,i | abcde,chi,chi | depart,off ramp slight left,arrive |
|
||||||
| f,i | fgc,chi,chi | depart,off ramp left,arrive |
|
| f,i | fgc,chi,chi | depart,off ramp slight left,arrive |
|
||||||
|
|
||||||
Scenario: Merging Motorways
|
Scenario: Merging Motorways
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -848,6 +848,7 @@ Feature: Simple Turns
|
|||||||
| h,a | Heide,Perle,Perle | depart,turn left,arrive | true:16;true:90 true:195 true:270 true:345;true:90 |
|
| h,a | Heide,Perle,Perle | depart,turn left,arrive | true:16;true:90 true:195 true:270 true:345;true:90 |
|
||||||
|
|
||||||
#http://www.openstreetmap.org/#map=19/52.53293/13.32956
|
#http://www.openstreetmap.org/#map=19/52.53293/13.32956
|
||||||
|
# adjusted ways to reflect the case geometry for 2/3/2018
|
||||||
Scenario: Curved Exit from Curved Road
|
Scenario: Curved Exit from Curved Road
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@@ -874,16 +875,16 @@ Feature: Simple Turns
|
|||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name | oneway | lanes | highway |
|
| nodes | name | oneway | lanes | highway |
|
||||||
| abcd | Siemens | no | 5 | secondary |
|
| ab | Siemens | no | 5 | secondary |
|
||||||
| defg | Erna | no | 3 | secondary |
|
| bcdefg | Erna | no | 3 | secondary |
|
||||||
| dhij | Siemens | no | | residential |
|
| dhij | Siemens | no | | residential |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,j | Siemens,Siemens,Siemens | depart,continue slight right,arrive |
|
| a,j | Siemens,Siemens,Siemens | depart,turn slight right,arrive |
|
||||||
| a,g | Siemens,Erna | depart,arrive |
|
| a,g | Siemens,Erna | depart,arrive |
|
||||||
| g,j | Erna,Siemens,Siemens | depart,turn left,arrive |
|
| g,j | Erna,Siemens,Siemens | depart,turn left,arrive |
|
||||||
| g,a | Erna,Siemens | depart,arrive |
|
| g,a | Erna,Siemens | depart,arrive |
|
||||||
|
|
||||||
#http://www.openstreetmap.org/#map=19/52.51303/13.32170
|
#http://www.openstreetmap.org/#map=19/52.51303/13.32170
|
||||||
Scenario: Ernst Reuter Platz
|
Scenario: Ernst Reuter Platz
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ Feature: Turn Lane Guidance
|
|||||||
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
|
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
|
||||||
| i,h | cross,road,road | depart,turn right,arrive | ,, |
|
| i,h | cross,road,road | depart,turn right,arrive | ,, |
|
||||||
| i,j | cross,cross | depart,arrive | ;;left:false straight:true, |
|
| i,j | cross,cross | depart,arrive | ;;left:false straight:true, |
|
||||||
| i,l | cross,cross,cross | depart,continue uturn,arrive | ;,left:true straight:false;left:true straight:false;left:false straight:true, |
|
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false;left:true straight:false;left:true straight:false;left:false straight:true, |
|
||||||
|
|
||||||
@partition-lanes
|
@partition-lanes
|
||||||
Scenario: Turn Lanes at Segregated Road
|
Scenario: Turn Lanes at Segregated Road
|
||||||
@@ -614,8 +614,9 @@ Feature: Turn Lane Guidance
|
|||||||
| |
|
| |
|
||||||
| |
|
| |
|
||||||
b d
|
b d
|
||||||
h c
|
h-----c
|
||||||
' -- g - - f
|
| `-f
|
||||||
|
g
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
@@ -936,48 +937,52 @@ Feature: Turn Lane Guidance
|
|||||||
Scenario: Partitioned turn, Slight Curve - maxspeed
|
Scenario: Partitioned turn, Slight Curve - maxspeed
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
f e
|
f e
|
||||||
| |
|
| |
|
||||||
| |
|
i | |
|
||||||
| c
|
| | c
|
||||||
a - b ' |
|
h - a - b ' |
|
||||||
g d
|
j g d
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name | highway | oneway | turn:lanes:forward | maxspeed |
|
| nodes | name | highway | oneway | turn:lanes:forward | maxspeed |
|
||||||
|
| ha | road | primary | yes | | 1 |
|
||||||
| ab | road | primary | yes | left\|right | 1 |
|
| ab | road | primary | yes | left\|right | 1 |
|
||||||
| bc | cross | primary | yes | | 1 |
|
| bc | cross | primary | yes | | 1 |
|
||||||
| fbg | cross | primary | yes | | 1 |
|
| fbg | cross | primary | yes | | 1 |
|
||||||
| dce | cross | primary | yes | | 1 |
|
| dce | cross | primary | yes | | 1 |
|
||||||
|
| iaj | kross | primary | no | | 1 |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes | locations |
|
| waypoints | route | turns | lanes | locations |
|
||||||
| a,g | road,cross,cross | depart,turn right,arrive | ,left:false right:true, | a,b,g |
|
| h,g | road,cross,cross | depart,turn right,arrive | ;,left:false right:true, | h,b,g |
|
||||||
| a,e | road,cross,cross | depart,end of road left,arrive | ;left:true right:false,left:true right:false, | a,c,e |
|
| h,e | road,cross,cross | depart,end of road left,arrive | ;,left:true right:false;left:true right:false, | h,b,e |
|
||||||
|
|
||||||
Scenario: Partitioned turn, Slight Curve
|
Scenario: Partitioned turn, Slight Curve
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
f e
|
f e
|
||||||
| |
|
| |
|
||||||
| |
|
i | |
|
||||||
| c
|
| | c
|
||||||
a - b ' |
|
h - a - b ' |
|
||||||
g d
|
j g d
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name | highway | oneway | turn:lanes:forward |
|
| nodes | name | highway | oneway | turn:lanes:forward |
|
||||||
|
| ha | road | primary | yes | |
|
||||||
| ab | road | primary | yes | left\|right |
|
| ab | road | primary | yes | left\|right |
|
||||||
| bc | cross | primary | yes | |
|
| bc | cross | primary | yes | |
|
||||||
| fbg | cross | primary | yes | |
|
| fbg | cross | primary | yes | |
|
||||||
| dce | cross | primary | yes | |
|
| dce | cross | primary | yes | |
|
||||||
|
| iaj | kross | primary | no | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes | locations |
|
| waypoints | route | turns | lanes | locations |
|
||||||
| a,g | road,cross,cross | depart,turn right,arrive | ,left:false right:true, | a,b,g |
|
| h,g | road,cross,cross | depart,turn right,arrive | ;,left:false right:true, | h,b,g |
|
||||||
| a,e | road,cross,cross | depart,end of road left,arrive | ;left:true right:false,left:true right:false, | a,c,e |
|
| h,e | road,cross,cross | depart,end of road left,arrive | ;,left:true right:false;left:true right:false, | h,b,e |
|
||||||
|
|
||||||
Scenario: Lane Parsing Issue #2694
|
Scenario: Lane Parsing Issue #2694
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -1243,4 +1248,4 @@ Feature: Turn Lane Guidance
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes | locations |
|
| waypoints | route | turns | lanes | locations |
|
||||||
| a,f | road1,road1,road1 | depart,continue uturn,arrive | ;left:false straight:true straight;right:false,left:true straight:false straight;right:false;;, | a,d,f |
|
| a,f | road1,road1,road1 | depart,continue uturn,arrive | ,;left:true straight:false straight;right:false;;, | a,c,f |
|
||||||
|
|||||||
@@ -899,9 +899,9 @@ Feature: Simple Turns
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | highway | name |
|
| nodes | highway | name | lanes |
|
||||||
| abc | primary | road |
|
| abc | primary | road | 3 |
|
||||||
| bd | residential | in |
|
| bd | residential | in | 1 |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | turns | route |
|
| waypoints | turns | route |
|
||||||
@@ -964,15 +964,15 @@ Feature: Simple Turns
|
|||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
g
|
g
|
||||||
|
|
|
||||||
f y
|
_--f-----y
|
||||||
i
|
i-' |
|
||||||
j k a b x
|
j-k-a]|[b---x
|
||||||
e c
|
e 'c
|
||||||
d
|
|'d'
|
||||||
|
|
|
||||||
h
|
h
|
||||||
|
|
|
||||||
q
|
q
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -1373,6 +1373,36 @@ Feature: Simple Turns
|
|||||||
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
|
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
|
||||||
| a,g | ab,befg,befg | depart,fork slight left,arrive |
|
| a,g | ab,befg,befg | depart,fork slight left,arrive |
|
||||||
|
|
||||||
|
@routing @car
|
||||||
|
Scenario: No turn instruction when turning from unnamed onto unnamed
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
b----------------c
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | ref |
|
||||||
|
| ab | trunk_link | | |
|
||||||
|
| db | secondary | | L 460 |
|
||||||
|
| bc | secondary | | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | ref | turns |
|
||||||
|
| d | c | ,, | L 460,, | depart,turn right,arrive |
|
||||||
|
| c | d | ,, | ,L 460,L 460 | depart,turn left,arrive |
|
||||||
|
|
||||||
# https://www.openstreetmap.org/#map=18/52.25130/10.42545
|
# https://www.openstreetmap.org/#map=18/52.25130/10.42545
|
||||||
Scenario: Turn for roads with no name, ref changes
|
Scenario: Turn for roads with no name, ref changes
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -1404,21 +1434,21 @@ Feature: Simple Turns
|
|||||||
Scenario: Turn for roads with no name, ref changes
|
Scenario: Turn for roads with no name, ref changes
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
x
|
x
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
d
|
d
|
||||||
. .
|
. .
|
||||||
. .
|
. .
|
||||||
. .
|
. .
|
||||||
e. . t . c . p. .f
|
e. . t . c . p. .f
|
||||||
. .
|
. .
|
||||||
. .
|
. .
|
||||||
. .
|
. .
|
||||||
b
|
b
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
a
|
a
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
@@ -1430,6 +1460,6 @@ Feature: Simple Turns
|
|||||||
| etcpf | primary | B 1 | | no |
|
| etcpf | primary | B 1 | | no |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| e,x | ,,, | depart,turn sharp left,turn right,arrive |
|
| e,x | ,, | depart,turn left,arrive |
|
||||||
| f,a | ,, | depart,turn left,arrive |
|
| f,a | ,, | depart,turn left,arrive |
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class OSRMBaseLoader{
|
|||||||
if (err) {
|
if (err) {
|
||||||
if (retryCount < 10) {
|
if (retryCount < 10) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
setTimeout(() => { tryConnect(this.scope.OSRM_PORT, retry); }, 10);
|
setTimeout(() => { tryConnect(this.scope.OSRM_IP, this.scope.OSRM_PORT, retry); }, 10);
|
||||||
} else {
|
} else {
|
||||||
callback(new Error("Could not connect to osrm-routed after ten retries."));
|
callback(new Error("Could not connect to osrm-routed after ten retries."));
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ class OSRMBaseLoader{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tryConnect(this.scope.OSRM_PORT, retry);
|
tryConnect(this.scope.OSRM_IP, this.scope.OSRM_PORT, retry);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ class OSRMDirectLoader extends OSRMBaseLoader {
|
|||||||
osrmUp (callback) {
|
osrmUp (callback) {
|
||||||
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
|
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
|
||||||
|
|
||||||
const command_arguments = util.format('%s -p %d -a %s', this.inputFile, this.scope.OSRM_PORT, this.scope.ROUTING_ALGORITHM);
|
const command_arguments = util.format('%s -p %d -i %s -a %s', this.inputFile, this.scope.OSRM_PORT, this.scope.OSRM_IP, this.scope.ROUTING_ALGORITHM);
|
||||||
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
|
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
|
||||||
if (err && err.signal !== 'SIGINT') {
|
if (err && err.signal !== 'SIGINT') {
|
||||||
this.child = null;
|
this.child = null;
|
||||||
@@ -107,7 +107,8 @@ class OSRMDatastoreLoader extends OSRMBaseLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadData (callback) {
|
loadData (callback) {
|
||||||
this.scope.runBin('osrm-datastore', this.inputFile, this.scope.environment, (err) => {
|
const command_arguments = util.format('--dataset-name=%s %s', this.scope.DATASET_NAME, this.inputFile);
|
||||||
|
this.scope.runBin('osrm-datastore', command_arguments, this.scope.environment, (err) => {
|
||||||
if (err) return callback(new Error('*** osrm-datastore exited with ' + err.code + ': ' + err));
|
if (err) return callback(new Error('*** osrm-datastore exited with ' + err.code + ': ' + err));
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
@@ -116,7 +117,7 @@ class OSRMDatastoreLoader extends OSRMBaseLoader {
|
|||||||
osrmUp (callback) {
|
osrmUp (callback) {
|
||||||
if (this.osrmIsRunning()) return callback();
|
if (this.osrmIsRunning()) return callback();
|
||||||
|
|
||||||
const command_arguments = util.format('--shared-memory=1 -p %d -a %s', this.scope.OSRM_PORT, this.scope.ROUTING_ALGORITHM);
|
const command_arguments = util.format('--dataset-name=%s -s -i %s -p %d -a %s', this.scope.DATASET_NAME, this.scope.OSRM_IP, this.scope.OSRM_PORT, this.scope.ROUTING_ALGORITHM);
|
||||||
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
|
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
|
||||||
if (err && err.signal !== 'SIGINT') {
|
if (err && err.signal !== 'SIGINT') {
|
||||||
this.child = null;
|
this.child = null;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
const net = require('net');
|
const net = require('net');
|
||||||
const Timeout = require('node-timeout');
|
const Timeout = require('node-timeout');
|
||||||
|
|
||||||
module.exports = function tryConnect(port, callback) {
|
module.exports = function tryConnect(host, port, callback) {
|
||||||
net.connect({ port: port, host: '127.0.0.1' })
|
net.connect({ port: port, host: host })
|
||||||
.on('connect', () => { callback(); })
|
.on('connect', () => { callback(); })
|
||||||
.on('error', () => {
|
.on('error', () => {
|
||||||
callback(new Error('Could not connect.'));
|
callback(new Error('Could not connect.'));
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
@datastore @options @help
|
||||||
|
Feature: osrm-datastore command line options
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
And the data has been contracted
|
||||||
|
|
||||||
|
Scenario: osrm-datastore - Help should be shown when no options are passed
|
||||||
|
When I try to run "osrm-datastore --dataset-name test_dataset_42 {processed_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
When I try to run "osrm-datastore --list"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should contain "test_dataset_42/static"
|
||||||
|
And stdout should contain "test_dataset_42/updatable"
|
||||||
|
|
||||||
|
Scenario: osrm-datastore - Only metric update should work
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
0,1,50
|
||||||
|
"""
|
||||||
|
And the data has been extracted
|
||||||
|
When I try to run "osrm-datastore {processed_file} --dataset-name cucumber/only_metric_test"
|
||||||
|
Then it should exit successfully
|
||||||
|
When I try to run "osrm-customize --segment-speed-file {speeds_file} {processed_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
When I try to run "osrm-datastore {processed_file} --dataset-name cucumber/only_metric_test --only-metric"
|
||||||
|
Then it should exit successfully
|
||||||
|
|
||||||
|
Scenario: osrm-datastore - Displaying help should work
|
||||||
|
When I try to run "osrm-datastore {processed_file} --help"
|
||||||
|
Then it should exit successfully
|
||||||
|
|
||||||
|
Scenario: osrm-datastore - Errors on invalid path
|
||||||
|
When I try to run "osrm-datastore invalid_path.osrm"
|
||||||
|
Then stderr should contain "[error] Config contains invalid file paths."
|
||||||
|
And stderr should contain "Missing/Broken"
|
||||||
|
And it should exit with an error
|
||||||
@@ -152,7 +152,7 @@ Feature: Turn Function Information
|
|||||||
And stdout should contain "number_of_roads 3"
|
And stdout should contain "number_of_roads 3"
|
||||||
And stdout should contain "source_priority_class 4"
|
And stdout should contain "source_priority_class 4"
|
||||||
And stdout should contain "target_priority_class 0"
|
And stdout should contain "target_priority_class 0"
|
||||||
And stdout should contain "target_priority_class 11"
|
And stdout should contain "target_priority_class 10"
|
||||||
# turning abd, give information about bc
|
# turning abd, give information about bc
|
||||||
And stdout should contain /roads_on_the_right \[1\] speed: [0-9]+, is_incoming: false, is_outgoing: true, highway_turn_classification: 4, access_turn_classification: 0/
|
And stdout should contain /roads_on_the_right \[1\] speed: [0-9]+, is_incoming: false, is_outgoing: true, highway_turn_classification: 4, access_turn_classification: 0/
|
||||||
# turning abc, give information about bd
|
# turning abc, give information about bd
|
||||||
@@ -180,7 +180,3 @@ Feature: Turn Function Information
|
|||||||
And stdout should contain /roads_on_the_right \[1\] speed: [0-9]+, is_incoming: true, is_outgoing: false, highway_turn_classification: 3, access_turn_classification: 0/
|
And stdout should contain /roads_on_the_right \[1\] speed: [0-9]+, is_incoming: true, is_outgoing: false, highway_turn_classification: 3, access_turn_classification: 0/
|
||||||
# turning abc, give information about about db
|
# turning abc, give information about about db
|
||||||
And stdout should contain /roads_on_the_left \[1\] speed: [0-9]+, is_incoming: true, is_outgoing: false, highway_turn_classification: 0, access_turn_classification: 1/
|
And stdout should contain /roads_on_the_left \[1\] speed: [0-9]+, is_incoming: true, is_outgoing: false, highway_turn_classification: 0, access_turn_classification: 1/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,74 +1,88 @@
|
|||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
this.When(/^I request a travel time matrix I should get$/, (table, callback) => {
|
const durationsRegex = new RegExp(/^I request a travel time matrix I should get$/);
|
||||||
var NO_ROUTE = 2147483647; // MAX_INT
|
const distancesRegex = new RegExp(/^I request a travel distance matrix I should get$/);
|
||||||
|
|
||||||
var tableRows = table.raw();
|
const DURATIONS_NO_ROUTE = 2147483647; // MAX_INT
|
||||||
|
const DISTANCES_NO_ROUTE = 3.40282e+38; // MAX_FLOAT
|
||||||
|
|
||||||
if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
|
this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', callback);}.bind(this));
|
||||||
|
this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', callback);}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
var waypoints = [],
|
const durationsParse = function(v) { return isNaN(parseInt(v)); };
|
||||||
columnHeaders = tableRows[0].slice(1),
|
const distancesParse = function(v) { return isNaN(parseFloat(v)); };
|
||||||
rowHeaders = tableRows.map((h) => h[0]).slice(1),
|
|
||||||
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
|
|
||||||
|
|
||||||
if (symmetric) {
|
function tableParse(table, noRoute, annotation, callback) {
|
||||||
columnHeaders.forEach((nodeName) => {
|
|
||||||
var node = this.findNodeByName(nodeName);
|
const parse = annotation == 'distances' ? distancesParse : durationsParse;
|
||||||
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
|
const params = this.queryParams;
|
||||||
waypoints.push({ coord: node, type: 'loc' });
|
params.annotations = annotation == 'distances' ? 'distance' : 'duration';
|
||||||
|
|
||||||
|
var tableRows = table.raw();
|
||||||
|
|
||||||
|
if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
|
||||||
|
|
||||||
|
var waypoints = [],
|
||||||
|
columnHeaders = tableRows[0].slice(1),
|
||||||
|
rowHeaders = tableRows.map((h) => h[0]).slice(1),
|
||||||
|
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
|
||||||
|
|
||||||
|
if (symmetric) {
|
||||||
|
columnHeaders.forEach((nodeName) => {
|
||||||
|
var node = this.findNodeByName(nodeName);
|
||||||
|
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
|
||||||
|
waypoints.push({ coord: node, type: 'loc' });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
columnHeaders.forEach((nodeName) => {
|
||||||
|
var node = this.findNodeByName(nodeName);
|
||||||
|
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
|
||||||
|
waypoints.push({ coord: node, type: 'dst' });
|
||||||
|
});
|
||||||
|
rowHeaders.forEach((nodeName) => {
|
||||||
|
var node = this.findNodeByName(nodeName);
|
||||||
|
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
|
||||||
|
waypoints.push({ coord: node, type: 'src' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var actual = [];
|
||||||
|
actual.push(table.headers);
|
||||||
|
|
||||||
|
this.reprocessAndLoadData((e) => {
|
||||||
|
if (e) return callback(e);
|
||||||
|
// compute matrix
|
||||||
|
|
||||||
|
this.requestTable(waypoints, params, (err, response) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
if (!response.body.length) return callback(new Error('Invalid response body'));
|
||||||
|
|
||||||
|
var json = JSON.parse(response.body);
|
||||||
|
|
||||||
|
var result = json[annotation].map(row => {
|
||||||
|
var hashes = {};
|
||||||
|
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; });
|
||||||
|
return hashes;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
columnHeaders.forEach((nodeName) => {
|
|
||||||
var node = this.findNodeByName(nodeName);
|
|
||||||
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
|
|
||||||
waypoints.push({ coord: node, type: 'dst' });
|
|
||||||
});
|
|
||||||
rowHeaders.forEach((nodeName) => {
|
|
||||||
var node = this.findNodeByName(nodeName);
|
|
||||||
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
|
|
||||||
waypoints.push({ coord: node, type: 'src' });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var actual = [];
|
var testRow = (row, ri, cb) => {
|
||||||
actual.push(table.headers);
|
for (var k in result[ri]) {
|
||||||
|
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
|
||||||
this.reprocessAndLoadData((e) => {
|
result[ri][k] = row[k];
|
||||||
if (e) return callback(e);
|
} else if (row[k] === '' && result[ri][k] === noRoute) {
|
||||||
// compute matrix
|
result[ri][k] = '';
|
||||||
var params = this.queryParams;
|
} else {
|
||||||
|
result[ri][k] = result[ri][k].toString();
|
||||||
this.requestTable(waypoints, params, (err, response) => {
|
|
||||||
if (err) return callback(err);
|
|
||||||
if (!response.body.length) return callback(new Error('Invalid response body'));
|
|
||||||
|
|
||||||
var json = JSON.parse(response.body);
|
|
||||||
|
|
||||||
var result = json['durations'].map(row => {
|
|
||||||
var hashes = {};
|
|
||||||
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = isNaN(parseInt(v)) ? '' : v; });
|
|
||||||
return hashes;
|
|
||||||
});
|
|
||||||
|
|
||||||
var testRow = (row, ri, cb) => {
|
|
||||||
for (var k in result[ri]) {
|
|
||||||
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
|
|
||||||
result[ri][k] = row[k];
|
|
||||||
} else if (row[k] === '' && result[ri][k] === NO_ROUTE) {
|
|
||||||
result[ri][k] = '';
|
|
||||||
} else {
|
|
||||||
result[ri][k] = result[ri][k].toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result[ri][''] = row[''];
|
result[ri][''] = row[''];
|
||||||
cb(null, result[ri]);
|
cb(null, result[ri]);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.processRowsAndDiff(table, testRow, callback);
|
this.processRowsAndDiff(table, testRow, callback);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ module.exports = {
|
|||||||
matchRe = want.match(/^\/(.*)\/$/),
|
matchRe = want.match(/^\/(.*)\/$/),
|
||||||
// we use this for matching before/after bearing
|
// we use this for matching before/after bearing
|
||||||
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
|
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
|
||||||
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/);
|
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/),
|
||||||
|
matchRangeNumbers = want.match(/\d+\+\-\d+/);
|
||||||
|
|
||||||
function inRange(margin, got, want) {
|
function inRange(margin, got, want) {
|
||||||
var fromR = parseFloat(want) - margin,
|
var fromR = parseFloat(want) - margin,
|
||||||
@@ -105,6 +106,11 @@ module.exports = {
|
|||||||
return inRange(margin, got, matchAbs[1]);
|
return inRange(margin, got, matchAbs[1]);
|
||||||
} else if (matchRe) { // regex: /a,b,.*/
|
} else if (matchRe) { // regex: /a,b,.*/
|
||||||
return got.match(matchRe[1]);
|
return got.match(matchRe[1]);
|
||||||
|
} else if (matchRangeNumbers) {
|
||||||
|
let real_want_and_margin = want.split('+-'),
|
||||||
|
margin = parseFloat(real_want_and_margin[1].trim()),
|
||||||
|
real_want = parseFloat(real_want_and_margin[0].trim());
|
||||||
|
return inRange(margin, got, real_want);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ module.exports = function () {
|
|||||||
return callback(new Error('*** '+stxxl_config+ 'does not exist'));
|
return callback(new Error('*** '+stxxl_config+ 'does not exist'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.DATASET_NAME = 'cucumber';
|
||||||
this.PLATFORM_WINDOWS = process.platform.match(/^win.*/);
|
this.PLATFORM_WINDOWS = process.platform.match(/^win.*/);
|
||||||
this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env);
|
this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env);
|
||||||
this.DEFAULT_PROFILE = 'bicycle';
|
this.DEFAULT_PROFILE = 'bicycle';
|
||||||
@@ -43,7 +44,8 @@ module.exports = function () {
|
|||||||
this.TIMEZONE_NAMES = this.PLATFORM_WINDOWS ? 'win' : 'iana';
|
this.TIMEZONE_NAMES = this.PLATFORM_WINDOWS ? 'win' : 'iana';
|
||||||
|
|
||||||
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
|
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
|
||||||
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
|
this.OSRM_IP = process.env.OSRM_IP || '127.0.0.1';
|
||||||
|
this.HOST = `http://${this.OSRM_IP}:${this.OSRM_PORT}`;
|
||||||
|
|
||||||
this.OSRM_PROFILE = process.env.OSRM_PROFILE;
|
this.OSRM_PROFILE = process.env.OSRM_PROFILE;
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ module.exports = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.verifyOSRMIsNotRunning = (callback) => {
|
this.verifyOSRMIsNotRunning = (callback) => {
|
||||||
tryConnect(this.OSRM_PORT, (err) => {
|
tryConnect(this.OSRM_IP, this.OSRM_PORT, (err) => {
|
||||||
if (!err) return callback(new Error('*** osrm-routed is already running.'));
|
if (!err) return callback(new Error('*** osrm-routed is already running.'));
|
||||||
else callback();
|
else callback();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ module.exports = function () {
|
|||||||
.defer(rimraf, this.scenarioLogFile)
|
.defer(rimraf, this.scenarioLogFile)
|
||||||
.awaitAll(callback);
|
.awaitAll(callback);
|
||||||
// uncomment to get path to logfile
|
// uncomment to get path to logfile
|
||||||
// console.log(" Writing logging output to " + this.scenarioLogFile)
|
// console.log(' Writing logging output to ' + this.scenarioLogFile);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.After((scenario, callback) => {
|
this.After((scenario, callback) => {
|
||||||
|
|||||||
@@ -199,14 +199,26 @@ module.exports = function () {
|
|||||||
|
|
||||||
var merged = {};
|
var merged = {};
|
||||||
instructions.legs.map(l => {
|
instructions.legs.map(l => {
|
||||||
Object.keys(l.annotation).forEach(a => {
|
Object.keys(l.annotation).filter(a => !a.match(/metadata/)).forEach(a => {
|
||||||
if (!merged[a]) merged[a] = [];
|
if (!merged[a]) merged[a] = [];
|
||||||
merged[a].push(l.annotation[a].join(':'));
|
merged[a].push(l.annotation[a].join(':'));
|
||||||
});
|
});
|
||||||
|
if (l.annotation.metadata) {
|
||||||
|
merged.metadata = {};
|
||||||
|
Object.keys(l.annotation.metadata).forEach(a => {
|
||||||
|
if (!merged.metadata[a]) merged.metadata[a] = [];
|
||||||
|
merged.metadata[a].push(l.annotation.metadata[a].join(':'));
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Object.keys(merged).map(a => {
|
Object.keys(merged).filter(k => !k.match(/metadata/)).map(a => {
|
||||||
merged[a] = merged[a].join(',');
|
merged[a] = merged[a].join(',');
|
||||||
});
|
});
|
||||||
|
if (merged.metadata) {
|
||||||
|
Object.keys(merged.metadata).map(a => {
|
||||||
|
merged.metadata[a] = merged.metadata[a].join(',');
|
||||||
|
});
|
||||||
|
}
|
||||||
return merged;
|
return merged;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ module.exports = function () {
|
|||||||
// if header matches 'a:*', parse out the values for *
|
// if header matches 'a:*', parse out the values for *
|
||||||
// and return in that header
|
// and return in that header
|
||||||
headers.forEach((k) => {
|
headers.forEach((k) => {
|
||||||
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
|
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed' ];
|
||||||
|
let metadata_whitelist = [ 'datasource_names' ];
|
||||||
if (k.match(/^a:/)) {
|
if (k.match(/^a:/)) {
|
||||||
let a_type = k.slice(2);
|
let a_type = k.slice(2);
|
||||||
if (whitelist.indexOf(a_type) == -1)
|
if (whitelist.indexOf(a_type) == -1)
|
||||||
@@ -166,6 +167,13 @@ module.exports = function () {
|
|||||||
if (annotation && !annotation[a_type])
|
if (annotation && !annotation[a_type])
|
||||||
return cb(new Error('Annotation not found in response', a_type));
|
return cb(new Error('Annotation not found in response', a_type));
|
||||||
got[k] = annotation && annotation[a_type] || '';
|
got[k] = annotation && annotation[a_type] || '';
|
||||||
|
} else if (k.match(/^am:/)) {
|
||||||
|
let a_type = k.slice(3);
|
||||||
|
if (metadata_whitelist.indexOf(a_type) == -1)
|
||||||
|
return cb(new Error('Unrecognized annotation field', a_type));
|
||||||
|
if (annotation && (!annotation.metadata || !annotation.metadata[a_type]))
|
||||||
|
return cb(new Error('Annotation not found in response', a_type));
|
||||||
|
got[k] = (annotation && annotation.metadata && annotation.metadata[a_type]) || '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ Feature: Alternative route
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
And a grid size of 200 meters
|
And a grid size of 200 meters
|
||||||
|
# Force data preparation to single-threaded to ensure consistent
|
||||||
|
# results for alternative generation during tests (alternative
|
||||||
|
# finding is highly sensitive to graph shape, which is in turn
|
||||||
|
# affected by parallelism during generation)
|
||||||
|
And the contract extra arguments "--threads 1"
|
||||||
|
And the extract extra arguments "--threads 1"
|
||||||
|
And the customize extra arguments "--threads 1"
|
||||||
|
And the partition extra arguments "--threads 1"
|
||||||
|
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ Feature: Alternative route
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
Given a grid size of 200 meters
|
Given a grid size of 200 meters
|
||||||
|
# Force data preparation to single-threaded to ensure consistent
|
||||||
|
# results for alternative generation during tests (alternative
|
||||||
|
# finding is highly sensitive to graph shape, which is in turn
|
||||||
|
# affected by parallelism during generation)
|
||||||
|
And the contract extra arguments "--threads 1"
|
||||||
|
And the extract extra arguments "--threads 1"
|
||||||
|
And the customize extra arguments "--threads 1"
|
||||||
|
And the partition extra arguments "--threads 1"
|
||||||
|
|
||||||
Scenario: Alternative Loop Paths
|
Scenario: Alternative Loop Paths
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@@ -60,6 +60,39 @@ Feature: Annotations
|
|||||||
| a | i | abcdefghi,abcdefghi | 1:0:1:0:1:0:0:0 | 50:10:50:10:50:10:10:10 |
|
| a | i | abcdefghi,abcdefghi | 1:0:1:0:1:0:0:0 | 50:10:50:10:50:10:10:10 |
|
||||||
| i | a | abcdefghi,abcdefghi | 0:1:0:0:0:0:0:1 | 10:50:10:10:10:10:10:50 |
|
| i | a | abcdefghi,abcdefghi | 0:1:0:0:0:0:0:1 | 10:50:10:10:10:10:10:50 |
|
||||||
|
|
||||||
|
Scenario: datasource name annotations
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
|
||||||
|
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,180,1
|
||||||
|
2,1,180,1
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| annotations | datasources |
|
||||||
|
|
||||||
|
# Note - the source names here are specific to how the tests are constructed,
|
||||||
|
# so if this test is moved around (changes line number) or support code
|
||||||
|
# changes how the filenames are generated, this test will need to be updated
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | am:datasource_names |
|
||||||
|
| a | c | abc,abc | lua profile:63_datasource_name_annotations_speeds |
|
||||||
|
| c | a | abc,abc | lua profile:63_datasource_name_annotations_speeds |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Speed annotations should handle zero segments
|
Scenario: Speed annotations should handle zero segments
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ Feature: Approach parameter
|
|||||||
| from | to | approaches | route |
|
| from | to | approaches | route |
|
||||||
| s | e | unrestricted curb | ab,bc |
|
| s | e | unrestricted curb | ab,bc |
|
||||||
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Oneway Test #
|
# Oneway Test #
|
||||||
###############
|
###############
|
||||||
@@ -226,3 +227,90 @@ Feature: Approach parameter
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | approaches | route |
|
| from | to | approaches | route |
|
||||||
| s | e | unrestricted curb | ab,bc |
|
| s | e | unrestricted curb | ab,bc |
|
||||||
|
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Left-side countries #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
Scenario: [Left-hand-side] Start End same approach, option unrestricted for Start and End
|
||||||
|
Given the profile file "car" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.left_hand_driving = true
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
s e
|
||||||
|
a------b------c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | approaches | route |
|
||||||
|
| s | e | unrestricted unrestricted | ab,bc |
|
||||||
|
|
||||||
|
Scenario: [Left-hand-side] Start End same approach, option unrestricted for Start and curb for End
|
||||||
|
Given the profile file "car" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.left_hand_driving = true
|
||||||
|
"""
|
||||||
|
And 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,bc |
|
||||||
|
|
||||||
|
Scenario: [Left-hand-side] Start End opposite approach, option unrestricted for Start and End
|
||||||
|
Given the profile file "car" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.left_hand_driving = true
|
||||||
|
"""
|
||||||
|
And 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: [Left-hand-side] Start End opposite approach, option unrestricted for Start and curb for End
|
||||||
|
Given the profile file "car" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.left_hand_driving = true
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
s e
|
||||||
|
a------b------c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | approaches | route |
|
||||||
|
| s | e | unrestricted curb | ab,bc |
|
||||||
@@ -108,12 +108,12 @@ Feature: Bearing parameter
|
|||||||
| ha | yes | ring |
|
| ha | yes | ring |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | bearings | route | bearing |
|
| from | to | bearings | route | bearing |
|
||||||
| 0 | q | 0 90 | ia,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,90->0 |
|
| 0 | q | 0 90 | ia,ring,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,0->90,90->0 |
|
||||||
| 0 | a | 45 90 | jb,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,90->0 |
|
| 0 | a | 45 90 | jb,ring,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,0->90,90->0 |
|
||||||
| 0 | q | 90 90 | kc,ring,ring,ring | 0->90,90->180,270->0,90->0 |
|
| 0 | q | 90 90 | kc,ring,ring,ring,ring | 0->90,90->180,270->0,0->90,90->0 |
|
||||||
| 0 | a | 135 90 | ld,ring,ring,ring | 0->135,135->270,270->0,90->0 |
|
| 0 | a | 135 90 | ld,ring,ring,ring,ring | 0->135,135->270,270->0,0->90,90->0 |
|
||||||
| 0 | a | 180 90 | me,ring,ring,ring | 0->180,180->270,270->0,90->0 |
|
| 0 | a | 180 90 | me,ring,ring,ring,ring | 0->180,180->270,270->0,0->90,90->0 |
|
||||||
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
|
| 0 | a | 225 90 | nf,ring,ring,ring | 0->225,225->0,0->90,90->0 |
|
||||||
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
|
| 0 | a | 270 90 | og,ring,ring,ring | 0->270,270->0,0->90,90->0 |
|
||||||
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
|
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
|
||||||
|
|||||||
@@ -226,3 +226,22 @@ Feature: Distance calculation
|
|||||||
| x | v | xv,xv | 424m +-1 |
|
| x | v | xv,xv | 424m +-1 |
|
||||||
| x | w | xw,xw | 360m +-1 |
|
| x | w | xw,xw | 360m +-1 |
|
||||||
| x | y | xy,xy | 316m +-1 |
|
| x | y | xy,xy | 316m +-1 |
|
||||||
|
|
||||||
|
|
||||||
|
# Check rounding errors
|
||||||
|
Scenario: Distances Long distances
|
||||||
|
Given a grid size of 1000 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcd |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | distance |
|
||||||
|
| a | b | 1000m +-3 |
|
||||||
|
| a | c | 2000m +-3 |
|
||||||
|
| a | d | 3000m +-3 |
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
@matrix @testbot
|
@matrix @testbot
|
||||||
Feature: Basic Distance Matrix
|
Feature: Basic Distance Matrix
|
||||||
# note that results are travel time, specified in 1/10th of seconds
|
# note that results of travel distance are in metres
|
||||||
# since testbot uses a default speed of 100m/10s, the result matches
|
|
||||||
# the number of meters as long as the way type is the default 'primary'
|
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
|
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix of minimal network
|
Scenario: Testbot - Travel distance matrix of minimal network
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b
|
a b
|
||||||
@@ -18,12 +16,99 @@ Feature: Basic Distance Matrix
|
|||||||
| nodes |
|
| nodes |
|
||||||
| ab |
|
| ab |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b |
|
| | a | b |
|
||||||
| a | 0 | 10 |
|
| a | 0 | 100+-1 |
|
||||||
| b | 10 | 0 |
|
| b | 100+-1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix with different way speeds
|
Scenario: Testbot - Travel distance matrix of minimal network with toll exclude
|
||||||
|
Given the query options
|
||||||
|
| exclude | toll |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | toll | # |
|
||||||
|
| ab | motorway | | not drivable for exclude=motorway |
|
||||||
|
| cd | primary | | always drivable |
|
||||||
|
| ac | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 100+-1 | | |
|
||||||
|
| b | 100+-1 | 0 | | |
|
||||||
|
| c | | | 0 | 100+-1 |
|
||||||
|
| d | | | 100+-1 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | # |
|
||||||
|
| ab | motorway | not drivable for exclude=motorway |
|
||||||
|
| cd | residential | |
|
||||||
|
| ac | residential | |
|
||||||
|
| bd | residential | |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 300+-2 | 100+-2 | 200+-2 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway |
|
||||||
|
And the extract extra arguments "--small-component-size 4"
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
ab efgh
|
||||||
|
cd
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | # |
|
||||||
|
| be | motorway | not drivable for exclude=motorway |
|
||||||
|
| abcd | residential | |
|
||||||
|
| efgh | residential | |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | e |
|
||||||
|
| a | 0 | 50+-1 | |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway,toll |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b e f
|
||||||
|
c d g h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | toll | # |
|
||||||
|
| be | motorway | | not drivable for exclude=motorway |
|
||||||
|
| dg | primary | yes | not drivable for exclude=toll |
|
||||||
|
| abcd | residential | | |
|
||||||
|
| efgh | residential | | |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | e | g |
|
||||||
|
| a | 0 | 100+-1 | | |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix with different way speeds
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b c d
|
a b c d
|
||||||
@@ -35,40 +120,25 @@ Feature: Basic Distance Matrix
|
|||||||
| bc | secondary |
|
| bc | secondary |
|
||||||
| cd | tertiary |
|
| cd | tertiary |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 10 | 30 | 60 |
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
| b | 10 | 0 | 20 | 50 |
|
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
||||||
| c | 30 | 20 | 0 | 30 |
|
| c | 200+-1 | 100+-1 | 0 | 100+-1 |
|
||||||
| d | 60 | 50 | 30 | 0 |
|
| d | 300+-1 | 200+-1 | 100+-1 | 0 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d |
|
| | a | b | c | d |
|
||||||
| a | 0 | 10 | 30 | 60 |
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a |
|
||||||
| a | 0 |
|
| a | 0 |
|
||||||
| b | 10 |
|
| b | 100+-1 |
|
||||||
| c | 30 |
|
| c | 200+-1 |
|
||||||
| d | 60 |
|
| d | 300+-1 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix with fuzzy match
|
Scenario: Testbot - Travel distance matrix of small grid
|
||||||
Given the node map
|
|
||||||
"""
|
|
||||||
a b
|
|
||||||
"""
|
|
||||||
|
|
||||||
And the ways
|
|
||||||
| nodes |
|
|
||||||
| ab |
|
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
|
||||||
| | a | b |
|
|
||||||
| a | 0 | 10 |
|
|
||||||
| b | 10 | 0 |
|
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix of small grid
|
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b c
|
a b c
|
||||||
@@ -83,14 +153,14 @@ Feature: Basic Distance Matrix
|
|||||||
| be |
|
| be |
|
||||||
| cf |
|
| cf |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e | f |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
| b | 10 | 0 | 10 | 20 |
|
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
||||||
| e | 20 | 10 | 0 | 10 |
|
| e | 200+-1 | 100+-1 | 0 | 100+-1 |
|
||||||
| f | 30 | 20 | 10 | 0 |
|
| f | 300+-1 | 200+-1 | 100+-1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix of network with unroutable parts
|
Scenario: Testbot - Travel distance matrix of network with unroutable parts
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b
|
a b
|
||||||
@@ -100,12 +170,12 @@ Feature: Basic Distance Matrix
|
|||||||
| nodes | oneway |
|
| nodes | oneway |
|
||||||
| ab | yes |
|
| ab | yes |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b |
|
| | a | b |
|
||||||
| a | 0 | 10 |
|
| a | 0 | 100+-1 |
|
||||||
| b | | 0 |
|
| b | | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix of network with oneways
|
Scenario: Testbot - Travel distance matrix of network with oneways
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
x a b y
|
x a b y
|
||||||
@@ -118,14 +188,14 @@ Feature: Basic Distance Matrix
|
|||||||
| xa | |
|
| xa | |
|
||||||
| by | |
|
| by | |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | x | y | d | e |
|
| | x | y | d | e |
|
||||||
| x | 0 | 30 | 40 | 30 |
|
| x | 0 | 300+-2 | 400+-2 | 300+-2 |
|
||||||
| y | 50 | 0 | 30 | 20 |
|
| y | 500+-2 | 0 | 300+-2 | 200+-2 |
|
||||||
| d | 20 | 30 | 0 | 30 |
|
| d | 200+-2 | 300+-2 | 0 | 300+-2 |
|
||||||
| e | 30 | 40 | 10 | 0 |
|
| e | 300+-2 | 400+-2 | 100+-2 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Rectangular travel time matrix
|
Scenario: Testbot - Rectangular travel distance matrix
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b c
|
a b c
|
||||||
@@ -140,51 +210,57 @@ Feature: Basic Distance Matrix
|
|||||||
| be |
|
| be |
|
||||||
| cf |
|
| cf |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I route I should get
|
||||||
| | a | b | e | f |
|
| from | to | distance |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| e | a | 200m +- 1 |
|
||||||
|
| e | b | 100m +- 1 |
|
||||||
|
| f | a | 300m +- 1 |
|
||||||
|
| f | b | 200m +- 1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a | b | e | f |
|
||||||
| a | 0 |
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
| b | 10 |
|
|
||||||
| e | 20 |
|
|
||||||
| f | 30 |
|
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| a | 0 |
|
||||||
| b | 10 | 0 | 10 | 20 |
|
| b | 100+-1 |
|
||||||
|
| e | 200+-1 |
|
||||||
|
| f | 300+-1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b |
|
| | a | b | e | f |
|
||||||
| a | 0 | 10 |
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
| b | 10 | 0 |
|
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
||||||
| e | 20 | 10 |
|
|
||||||
| f | 30 | 20 |
|
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| a | 0 | 100+-1 |
|
||||||
| b | 10 | 0 | 10 | 20 |
|
| b | 100+-1 | 0 |
|
||||||
| e | 20 | 10 | 0 | 10 |
|
| e | 200+-1 | 100+-1 |
|
||||||
|
| f | 300+-1 | 200+-1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e |
|
| | a | b | e | f |
|
||||||
| a | 0 | 10 | 20 |
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
| b | 10 | 0 | 10 |
|
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
||||||
| e | 20 | 10 | 0 |
|
| e | 200+-1 | 100+-1 | 0 | 100+-1 |
|
||||||
| f | 30 | 20 | 10 |
|
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | e | f |
|
| | a | b | e |
|
||||||
| a | 0 | 10 | 20 | 30 |
|
| a | 0 | 100+-1 | 200+-1 |
|
||||||
| b | 10 | 0 | 10 | 20 |
|
| b | 100+-1 | 0 | 100+-1 |
|
||||||
| e | 20 | 10 | 0 | 10 |
|
| e | 200+-1 | 100+-1 | 0 |
|
||||||
| f | 30 | 20 | 10 | 0 |
|
| f | 300+-1 | 200+-1 | 100+-1 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | e | f |
|
||||||
|
| a | 0 | 100+-1 | 200+-1 | 300+-1 |
|
||||||
|
| b | 100+-1 | 0 | 100+-1 | 200+-1 |
|
||||||
|
| e | 200+-1 | 100+-1 | 0 | 100+-1 |
|
||||||
|
| f | 300+-1 | 200+-1 | 100+-1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time 3x2 matrix
|
Scenario: Testbot - Travel distance 3x2 matrix
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b c
|
a b c
|
||||||
@@ -199,10 +275,11 @@ Feature: Basic Distance Matrix
|
|||||||
| be |
|
| be |
|
||||||
| cf |
|
| cf |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
|
||||||
| | b | e | f |
|
When I request a travel distance matrix I should get
|
||||||
| a | 10 | 20 | 30 |
|
| | b | e | f |
|
||||||
| b | 0 | 10 | 20 |
|
| a | 100+-1 | 200+-1 | 300+-1 |
|
||||||
|
| b | 0 | 100+-1 | 200+-1 |
|
||||||
|
|
||||||
Scenario: Testbot - All coordinates are from same small component
|
Scenario: Testbot - All coordinates are from same small component
|
||||||
Given a grid size of 300 meters
|
Given a grid size of 300 meters
|
||||||
@@ -221,10 +298,10 @@ Feature: Basic Distance Matrix
|
|||||||
| da |
|
| da |
|
||||||
| fg |
|
| fg |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | f | g |
|
| | f | g |
|
||||||
| f | 0 | 30 |
|
| f | 0 | 300+-2 |
|
||||||
| g | 30 | 0 |
|
| g | 300+-2 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Coordinates are from different small component and snap to big CC
|
Scenario: Testbot - Coordinates are from different small component and snap to big CC
|
||||||
Given a grid size of 300 meters
|
Given a grid size of 300 meters
|
||||||
@@ -244,14 +321,25 @@ Feature: Basic Distance Matrix
|
|||||||
| fg |
|
| fg |
|
||||||
| hi |
|
| hi |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I route I should get
|
||||||
| | f | g | h | i |
|
| from | to | distance |
|
||||||
| f | 0 | 30 | 0 | 30 |
|
| f | g | 300m |
|
||||||
| g | 30 | 0 | 30 | 0 |
|
| f | i | 300m |
|
||||||
| h | 0 | 30 | 0 | 30 |
|
| g | f | 300m |
|
||||||
| i | 30 | 0 | 30 | 0 |
|
| g | h | 300m |
|
||||||
|
| h | g | 300m |
|
||||||
|
| h | i | 300m |
|
||||||
|
| i | f | 300m |
|
||||||
|
| i | h | 300m |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix with loops
|
When I request a travel distance matrix I should get
|
||||||
|
| | f | g | h | i |
|
||||||
|
| f | 0 | 300+-2 | 0 | 300+-2 |
|
||||||
|
| g | 300+-2 | 0 | 300+-2 | 0 |
|
||||||
|
| h | 0 | 300+-2 | 0 | 300+-2 |
|
||||||
|
| i | 300+-2 | 0 | 300+-2 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix with loops
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a 1 2 b
|
a 1 2 b
|
||||||
@@ -265,14 +353,15 @@ Feature: Basic Distance Matrix
|
|||||||
| cd | yes |
|
| cd | yes |
|
||||||
| da | yes |
|
| da | yes |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | 1 | 2 | 3 | 4 |
|
| | 1 | 2 | 3 | 4 |
|
||||||
| 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
|
| 1 | 0 | 100+-1 | 400+-1 | 500+-1 |
|
||||||
| 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
|
| 2 | 700+-1 | 0 | 300+-1 | 400+-1 |
|
||||||
| 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
|
| 3 | 400+-1 | 500+-1 | 0 | 100+-1 |
|
||||||
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
|
| 4 | 300+-1 | 400+-1 | 700+-1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix based on segment durations
|
|
||||||
|
Scenario: Testbot - Travel distance matrix based on segment durations
|
||||||
Given the profile file
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
local functions = require('testbot')
|
local functions = require('testbot')
|
||||||
@@ -301,20 +390,19 @@ Feature: Basic Distance Matrix
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
| abcd |
|
| abcd |
|
||||||
| ce |
|
| ce |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a | b | c | d | e |
|
| | a | b | c | d | e |
|
||||||
| a | 0 | 11 | 22 | 33 | 33 |
|
| a | 0 | 100+-2 | 200+-2 | 300+-2 | 400+-2 |
|
||||||
| b | 11 | 0 | 11 | 22 | 22 |
|
| b | 100+-2 | 0 | 100+-2 | 200+-2 | 300+-2 |
|
||||||
| c | 22 | 11 | 0 | 11 | 11 |
|
| c | 200+-2 | 100+-2 | 0 | 100+-2 | 200+-2 |
|
||||||
| d | 33 | 22 | 11 | 0 | 22 |
|
| d | 300+-2 | 200+-2 | 100+-2 | 0 | 300+-2 |
|
||||||
| e | 33 | 22 | 11 | 22 | 0 |
|
| e | 400+-2 | 300+-2 | 200+-2 | 300+-2 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel distance matrix for alternative loop paths
|
||||||
Scenario: Testbot - Travel time matrix for alternative loop paths
|
|
||||||
Given the profile file
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
local functions = require('testbot')
|
local functions = require('testbot')
|
||||||
@@ -350,62 +438,132 @@ Feature: Basic Distance Matrix
|
|||||||
| dc | yes |
|
| dc | yes |
|
||||||
| ca | yes |
|
| ca | yes |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
| 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
|
| 1 | 0 | 1100+-5 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 |
|
||||||
| 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
|
| 2 | 100+-5 | 0 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 |
|
||||||
| 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
|
| 3 | 900+-5 | 800+-5 | 0 | 1100+-5 | 300+-5 | 200+-5 | 600+-5 | 500+-5 |
|
||||||
| 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
|
| 4 | 1000+-5 | 900+-5 | 100+-5 | 0 | 400+-5 | 300+-5 | 700+-5 | 600+-5 |
|
||||||
| 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
|
| 5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | 0 | 1100+-5 | 300+-5 | 200+-5 |
|
||||||
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
|
| 6 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | 100+-5 | 0 | 400+-5 | 300+-5 |
|
||||||
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
|
| 7 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | 0 | 1100+-5 |
|
||||||
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
|
| 8 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | 100+-5 | 0 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | 1 |
|
||||||
|
| 1 | 0 |
|
||||||
|
| 2 | 100+-5 |
|
||||||
|
| 3 | 900+-5 |
|
||||||
|
| 4 | 1000+-5 |
|
||||||
|
| 5 | 600+-5 |
|
||||||
|
| 6 | 700+-5 |
|
||||||
|
| 7 | 300+-5 |
|
||||||
|
| 8 | 400+-5 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix with ties
|
Scenario: Testbot - Travel distance matrix with ties
|
||||||
Given the profile file
|
Given the node map
|
||||||
"""
|
|
||||||
local functions = require('testbot')
|
|
||||||
functions.process_segment = function(profile, segment)
|
|
||||||
segment.weight = 1
|
|
||||||
segment.duration = 1
|
|
||||||
end
|
|
||||||
functions.process_turn = function(profile, turn)
|
|
||||||
if turn.angle >= 0 then
|
|
||||||
turn.duration = 16
|
|
||||||
else
|
|
||||||
turn.duration = 4
|
|
||||||
end
|
|
||||||
turn.weight = 0
|
|
||||||
end
|
|
||||||
return functions
|
|
||||||
"""
|
|
||||||
And the node map
|
|
||||||
"""
|
"""
|
||||||
a b
|
a b
|
||||||
|
|
||||||
c d
|
c d
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
| ab |
|
| ab |
|
||||||
| ac |
|
| ac |
|
||||||
| bd |
|
| bd |
|
||||||
| dc |
|
| dc |
|
||||||
|
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | distance | time | weight |
|
| from | to | route | distance | time | weight |
|
||||||
| a | c | ac,ac | 200m | 5s | 5 |
|
| a | c | ac,ac | 200m | 20s | 20 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I route I should get
|
||||||
| | a | b | c | d |
|
| from | to | route | distance |
|
||||||
| a | 0 | 1 | 5 | 10 |
|
| a | b | ab,ab | 450m |
|
||||||
|
| a | c | ac,ac | 200m |
|
||||||
|
| a | d | ac,dc,dc | 500m +- 1 |
|
||||||
|
|
||||||
When I request a travel time matrix I should get
|
When I request a travel distance matrix I should get
|
||||||
| | a |
|
| | a | b | c | d |
|
||||||
| a | 0 |
|
| a | 0 | 450+-2 | 200+-2 | 500+-2 |
|
||||||
| b | 1 |
|
|
||||||
| c | 15 |
|
When I request a travel distance matrix I should get
|
||||||
| d | 10 |
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 450+-2 |
|
||||||
|
| c | 200+-2 |
|
||||||
|
| d | 500+-2 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | c |
|
||||||
|
| a | 0 | 200+-2 |
|
||||||
|
| c | 200+-2 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
# Check rounding errors
|
||||||
|
Scenario: Testbot - Long distances in tables
|
||||||
|
Given a grid size of 1000 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcd |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 1000+-3 | 2000+-3 | 3000+-3 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - OneToMany vs ManyToOne
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| ac | |
|
||||||
|
| bc | |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b |
|
||||||
|
| b | 240.4 | 0 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 240.4 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Varying distances between nodes
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c d
|
||||||
|
|
||||||
|
e
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
f
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| feabcd | yes |
|
||||||
|
| ec | |
|
||||||
|
| fd | |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | b | c | d | e | f |
|
||||||
|
| a | 0 | 100+-1 | 300+-1 | 650+-1 | 1930+-1 | 1533+-1 |
|
||||||
|
| b | 760+-1 | 0 | 200+-1 | 550+-1 | 1830+-1 | 1433+-1 |
|
||||||
|
| c | 560+-2 | 660+-2 | 0 | 350+-1 | 1630+-1 | 1233+-1 |
|
||||||
|
| d | 1480+-2 | 1580+-1 | 1780+-1 | 0 | 1280+-1 | 883+-1 |
|
||||||
|
| e | 200+-2 | 300+-2 | 500+-1 | 710+-1 | 0 | 1593+-1 |
|
||||||
|
| f | 597+-1 | 696+-1 | 896+-1 | 1108+-1 | 400+-3 | 0 |
|
||||||
|
|||||||
@@ -0,0 +1,512 @@
|
|||||||
|
@matrix @testbot
|
||||||
|
Feature: Basic Duration Matrix
|
||||||
|
# note that results of travel time are in seconds
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix of minimal network
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b |
|
||||||
|
| a | 0 | 10 |
|
||||||
|
| b | 10 | 0 |
|
||||||
|
|
||||||
|
@ch
|
||||||
|
Scenario: Testbot - Travel time matrix of minimal network with toll exclude
|
||||||
|
Given the query options
|
||||||
|
| exclude | toll |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | toll | # |
|
||||||
|
| ab | motorway | | not drivable for exclude=motorway |
|
||||||
|
| cd | primary | | always drivable |
|
||||||
|
| ac | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 15 | | |
|
||||||
|
| b | 15 | 0 | | |
|
||||||
|
| c | | | 0 | 10 |
|
||||||
|
| d | | | 10 | 0 |
|
||||||
|
|
||||||
|
@ch
|
||||||
|
Scenario: Testbot - Travel time matrix of minimal network with motorway exclude
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | # |
|
||||||
|
| ab | motorway | not drivable for exclude=motorway |
|
||||||
|
| cd | residential | |
|
||||||
|
| ac | residential | |
|
||||||
|
| bd | residential | |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 45 | 15 | 30 |
|
||||||
|
|
||||||
|
@ch
|
||||||
|
Scenario: Testbot - Travel time matrix of minimal network disconnected motorway exclude
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
ab efgh
|
||||||
|
cd
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | # |
|
||||||
|
| be | motorway | not drivable for exclude=motorway |
|
||||||
|
| abcd | residential | |
|
||||||
|
| efgh | residential | |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e |
|
||||||
|
| a | 0 | 7.5 | |
|
||||||
|
|
||||||
|
@ch
|
||||||
|
Scenario: Testbot - Travel time matrix of minimal network with motorway and toll excludes
|
||||||
|
Given the query options
|
||||||
|
| exclude | motorway,toll |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b e f
|
||||||
|
c d g h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | toll | # |
|
||||||
|
| be | motorway | | not drivable for exclude=motorway |
|
||||||
|
| dg | primary | yes | not drivable for exclude=toll |
|
||||||
|
| abcd | residential | | |
|
||||||
|
| efgh | residential | | |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e | g |
|
||||||
|
| a | 0 | 15 | | |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix with different way speeds
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| bc | secondary |
|
||||||
|
| cd | tertiary |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 10 | 30 | 60 |
|
||||||
|
| b | 10 | 0 | 20 | 50 |
|
||||||
|
| c | 30 | 20 | 0 | 30 |
|
||||||
|
| d | 60 | 50 | 30 | 0 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 10 | 30 | 60 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 10 |
|
||||||
|
| c | 30 |
|
||||||
|
| d | 60 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix of small grid
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
d e f
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| def |
|
||||||
|
| ad |
|
||||||
|
| be |
|
||||||
|
| cf |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e | f |
|
||||||
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
| b | 10 | 0 | 10 | 20 |
|
||||||
|
| e | 20 | 10 | 0 | 10 |
|
||||||
|
| f | 30 | 20 | 10 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix of network with unroutable parts
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b |
|
||||||
|
| a | 0 | 10 |
|
||||||
|
| b | | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix of network with oneways
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
x a b y
|
||||||
|
d e
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abeda | yes |
|
||||||
|
| xa | |
|
||||||
|
| by | |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | x | y | d | e |
|
||||||
|
| x | 0 | 30 | 40 | 30 |
|
||||||
|
| y | 50 | 0 | 30 | 20 |
|
||||||
|
| d | 20 | 30 | 0 | 30 |
|
||||||
|
| e | 30 | 40 | 10 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Rectangular travel time matrix
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
d e f
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| def |
|
||||||
|
| ad |
|
||||||
|
| be |
|
||||||
|
| cf |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e | f |
|
||||||
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 10 |
|
||||||
|
| e | 20 |
|
||||||
|
| f | 30 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e | f |
|
||||||
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
| b | 10 | 0 | 10 | 20 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b |
|
||||||
|
| a | 0 | 10 |
|
||||||
|
| b | 10 | 0 |
|
||||||
|
| e | 20 | 10 |
|
||||||
|
| f | 30 | 20 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e | f |
|
||||||
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
| b | 10 | 0 | 10 | 20 |
|
||||||
|
| e | 20 | 10 | 0 | 10 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e |
|
||||||
|
| a | 0 | 10 | 20 |
|
||||||
|
| b | 10 | 0 | 10 |
|
||||||
|
| e | 20 | 10 | 0 |
|
||||||
|
| f | 30 | 20 | 10 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | e | f |
|
||||||
|
| a | 0 | 10 | 20 | 30 |
|
||||||
|
| b | 10 | 0 | 10 | 20 |
|
||||||
|
| e | 20 | 10 | 0 | 10 |
|
||||||
|
| f | 30 | 20 | 10 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time 3x2 matrix
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
d e f
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| def |
|
||||||
|
| ad |
|
||||||
|
| be |
|
||||||
|
| cf |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | b | e | f |
|
||||||
|
| a | 10 | 20 | 30 |
|
||||||
|
| b | 0 | 10 | 20 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - All coordinates are from same small component
|
||||||
|
Given a grid size of 300 meters
|
||||||
|
Given the extract extra arguments "--small-component-size 4"
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b f
|
||||||
|
d e g
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| be |
|
||||||
|
| ed |
|
||||||
|
| da |
|
||||||
|
| fg |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | f | g |
|
||||||
|
| f | 0 | 30 |
|
||||||
|
| g | 30 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Coordinates are from different small component and snap to big CC
|
||||||
|
Given a grid size of 300 meters
|
||||||
|
Given the extract extra arguments "--small-component-size 4"
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b f h
|
||||||
|
d e g i
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| be |
|
||||||
|
| ed |
|
||||||
|
| da |
|
||||||
|
| fg |
|
||||||
|
| hi |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | f | g | h | i |
|
||||||
|
| f | 0 | 30 | 0 | 30 |
|
||||||
|
| g | 30 | 0 | 30 | 0 |
|
||||||
|
| h | 0 | 30 | 0 | 30 |
|
||||||
|
| i | 30 | 0 | 30 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix with loops
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 b
|
||||||
|
d 4 3 c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| bc | yes |
|
||||||
|
| cd | yes |
|
||||||
|
| da | yes |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | 1 | 2 | 3 | 4 |
|
||||||
|
| 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
|
||||||
|
| 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
|
||||||
|
| 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
|
||||||
|
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix based on segment durations
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
local functions = require('testbot')
|
||||||
|
functions.setup_testbot = functions.setup
|
||||||
|
|
||||||
|
functions.setup = function()
|
||||||
|
local profile = functions.setup_testbot()
|
||||||
|
profile.traffic_signal_penalty = 0
|
||||||
|
profile.u_turn_penalty = 0
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
|
segment.weight = 2
|
||||||
|
segment.duration = 11
|
||||||
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a-b-c-d
|
||||||
|
.
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcd |
|
||||||
|
| ce |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d | e |
|
||||||
|
| a | 0 | 11 | 22 | 33 | 33 |
|
||||||
|
| b | 11 | 0 | 11 | 22 | 22 |
|
||||||
|
| c | 22 | 11 | 0 | 11 | 11 |
|
||||||
|
| d | 33 | 22 | 11 | 0 | 22 |
|
||||||
|
| e | 33 | 22 | 11 | 22 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix for alternative loop paths
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
local functions = require('testbot')
|
||||||
|
functions.setup_testbot = functions.setup
|
||||||
|
|
||||||
|
functions.setup = function()
|
||||||
|
local profile = functions.setup_testbot()
|
||||||
|
profile.traffic_signal_penalty = 0
|
||||||
|
profile.u_turn_penalty = 0
|
||||||
|
profile.weight_precision = 3
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
|
segment.weight = 777
|
||||||
|
segment.duration = 3
|
||||||
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a 2 1 b
|
||||||
|
7 4
|
||||||
|
8 3
|
||||||
|
c 5 6 d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| bd | yes |
|
||||||
|
| dc | yes |
|
||||||
|
| ca | yes |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||||
|
| 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
|
||||||
|
| 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
|
||||||
|
| 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
|
||||||
|
| 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
|
||||||
|
| 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
|
||||||
|
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
|
||||||
|
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
|
||||||
|
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Travel time matrix with ties
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
local functions = require('testbot')
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
|
segment.weight = 1
|
||||||
|
segment.duration = 1
|
||||||
|
end
|
||||||
|
functions.process_turn = function(profile, turn)
|
||||||
|
if turn.angle >= 0 then
|
||||||
|
turn.duration = 16
|
||||||
|
else
|
||||||
|
turn.duration = 4
|
||||||
|
end
|
||||||
|
turn.weight = 0
|
||||||
|
end
|
||||||
|
return functions
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| ac |
|
||||||
|
| bd |
|
||||||
|
| dc |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | distance | time | weight |
|
||||||
|
| a | c | ac,ac | 200m | 5s | 5 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b | c | d |
|
||||||
|
| a | 0 | 1 | 5 | 10 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 1 |
|
||||||
|
| c | 15 |
|
||||||
|
| d | 10 |
|
||||||
|
|
||||||
|
Scenario: Testbot - OneToMany vs ManyToOne
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| ac | |
|
||||||
|
| bc | |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | b |
|
||||||
|
| b | 24.1 | 0 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| b | 24.1 |
|
||||||
@@ -39,5 +39,64 @@ Feature: Fixed bugs, kept to check for regressions
|
|||||||
| de | yes |
|
| de | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| 1 | 2 | bcd,bcd |
|
| 1 | 2 | bcd,bcd |
|
||||||
|
|
||||||
|
#############################
|
||||||
|
# This test models the OSM map at the location for
|
||||||
|
# https://github.com/Project-OSRM/osrm-backend/issues/5039
|
||||||
|
#############################
|
||||||
|
Scenario: Mixed Entry and Exit and segregated
|
||||||
|
Given the profile file "car" initialized with
|
||||||
|
"""
|
||||||
|
profile.properties.left_hand_driving = true
|
||||||
|
"""
|
||||||
|
Given the node locations
|
||||||
|
| node | lon | lat |
|
||||||
|
| a | 171.12889297029 | -42.58425289548 |
|
||||||
|
| b | 171.1299357 | -42.5849295 |
|
||||||
|
| c | 171.1295427 | -42.5849385 |
|
||||||
|
| d | 171.1297356 | -42.5852029 |
|
||||||
|
| e | 171.1296909 | -42.5851986 |
|
||||||
|
| f | 171.1295097 | -42.585007 |
|
||||||
|
| g | 171.1298225 | -42.5851928 |
|
||||||
|
| h | 171.1300262 | -42.5859122 |
|
||||||
|
| i | 171.1292651 | -42.584698 |
|
||||||
|
| j | 171.1297209 | -42.5848569 |
|
||||||
|
| k | 171.1297188 | -42.5854056 |
|
||||||
|
| l | 171.1298326 | -42.5857266 |
|
||||||
|
| m | 171.1298871 | -42.5848922 |
|
||||||
|
| n | 171.1296505 | -42.585189 |
|
||||||
|
| o | 171.1295206 | -42.5850862 |
|
||||||
|
| p | 171.1296106 | -42.5848862 |
|
||||||
|
| q | 171.1299784 | -42.5850191 |
|
||||||
|
| r | 171.1298867 | -42.5851671 |
|
||||||
|
| s | 171.1306955 | -42.5845812 |
|
||||||
|
| t | 171.129525 | -42.584807 |
|
||||||
|
| u | 171.1299705 | -42.584984 |
|
||||||
|
| v | 171.1299067 | -42.5849073 |
|
||||||
|
| w | 171.1302061 | -42.5848173 |
|
||||||
|
| x | 171.12975 | -42.5855753 |
|
||||||
|
| y | 171.129969 | -42.585079 |
|
||||||
|
| 1 | 171.131511926651| -42.584306746421966 |
|
||||||
|
| 2 | 171.128743886947| -42.58414875714669 |
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed | name | ref | surface | junction | oneway |
|
||||||
|
| ws | primary | 100 | Taramakau Highway | SH 6 | asphalt | | |
|
||||||
|
| kxlh | trunk | | Otira Highway | SH 73 | | | |
|
||||||
|
| ai | primary | 100 | Kumara Junction Highway | SH 6 | asphalt | | |
|
||||||
|
| qyrgdenof | primary | 100 | Kumara Junction | | | roundabout | yes |
|
||||||
|
| ke | trunk | | Otira Highway | SH 73 | | | yes |
|
||||||
|
| itj | primary | 100 | Kumara Junction Highway | SH 6 | | | yes |
|
||||||
|
| gk | trunk | | Otira Highway | SH 73 | | | yes |
|
||||||
|
| fi | primary | 100 | Kumara Junction Highway | SH 6 | | | yes |
|
||||||
|
| wq | primary | 100 | Taramakau Highway | SH 6 | | | yes |
|
||||||
|
| vw | primary | 100 | Taramakau Highway | SH 6 | | | yes |
|
||||||
|
| vbuq | primary | 100 | Kumara Junction | | | roundabout | yes |
|
||||||
|
| jmv | primary | 100 | Kumara Junction | | | roundabout | yes |
|
||||||
|
| fcpj | primary | 100 | Kumara Junction | | | roundabout | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| 1,2 | Taramakau Highway,Kumara Junction Highway,Kumara Junction Highway,Kumara Junction Highway | depart,Kumara Junction-exit-2,exit rotary slight left,arrive |
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,40 @@ Feature: Multi level routing
|
|||||||
| l | 144.7 | 60 |
|
| l | 144.7 | 60 |
|
||||||
| o | 124.7 | 0 |
|
| o | 124.7 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | f | l | o |
|
||||||
|
| a | 0+-2 | 2287+-2 | 1443+-2 | 1243+-2 |
|
||||||
|
| f | 2284+-2 | 0+-2 | 1241+-2 | 1443+-2 |
|
||||||
|
| l | 1443+-2 | 1244+-2 | 0+-2 | 600+-2 |
|
||||||
|
| o | 1243+-2 | 1444+-2 | 600+-2 | 0+-2 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | f | l | o |
|
||||||
|
| a | 0 | 2287.2+-2 | 1443+-2 | 1243+-2 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a |
|
||||||
|
| a | 0 |
|
||||||
|
| f | 2284.5+-2 |
|
||||||
|
| l | 1443.1 |
|
||||||
|
| o | 1243 |
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | f | l | o |
|
||||||
|
| a | 0 | 2287+-2 | 1443+-2 | 1243+-2 |
|
||||||
|
| o | 1243 | 1444+-2 | 600+-2 | 0+-2 |
|
||||||
|
|
||||||
|
|
||||||
|
When I request a travel distance matrix I should get
|
||||||
|
| | a | o |
|
||||||
|
| a | 0+-2 | 1243+-2 |
|
||||||
|
| f | 2284+-2 | 1443+-2 |
|
||||||
|
| l | 1443+-2 | 600+-2 |
|
||||||
|
| o | 1243+-2 | 0+-2 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Testbot - Multi level routing: horizontal road
|
Scenario: Testbot - Multi level routing: horizontal road
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Feature: Traffic - speeds
|
|||||||
| a | d | ad,ad | 27 km/h | 1275.7,0 | 1 |
|
| a | d | ad,ad | 27 km/h | 1275.7,0 | 1 |
|
||||||
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
|
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
|
||||||
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
|
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
|
||||||
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 | 1:0:0 |
|
| a | g | ad,df,fb,fb | 30 km/h | 1295.7,487.5,304.7,0 | 1:0:0 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file weights, ETA based on file durations
|
Scenario: Weighting based on speed file weights, ETA based on file durations
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef OSMR_CONTRACTOR_CONTRACTED_METRIC_HPP
|
||||||
|
#define OSMR_CONTRACTOR_CONTRACTED_METRIC_HPP
|
||||||
|
|
||||||
|
#include "contractor/query_graph.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace contractor
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <storage::Ownership Ownership> struct ContractedMetric
|
||||||
|
{
|
||||||
|
detail::QueryGraph<Ownership> graph;
|
||||||
|
std::vector<util::ViewOrVector<bool, Ownership>> edge_filter;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
using ContractedMetric = detail::ContractedMetric<storage::Ownership::Container>;
|
||||||
|
using ContractedMetricView = detail::ContractedMetric<storage::Ownership::View>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
#ifndef OSRM_CONTRACTOR_FILES_HPP
|
#ifndef OSRM_CONTRACTOR_FILES_HPP
|
||||||
#define OSRM_CONTRACTOR_FILES_HPP
|
#define OSRM_CONTRACTOR_FILES_HPP
|
||||||
|
|
||||||
#include "contractor/query_graph.hpp"
|
#include "contractor/serialization.hpp"
|
||||||
|
|
||||||
#include "util/serialization.hpp"
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
|
||||||
#include "storage/serialization.hpp"
|
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -15,59 +12,45 @@ namespace contractor
|
|||||||
namespace files
|
namespace files
|
||||||
{
|
{
|
||||||
// reads .osrm.hsgr file
|
// reads .osrm.hsgr file
|
||||||
template <typename QueryGraphT, typename EdgeFilterT>
|
template <typename ContractedMetricT>
|
||||||
inline void readGraph(const boost::filesystem::path &path,
|
inline void readGraph(const boost::filesystem::path &path,
|
||||||
unsigned &checksum,
|
std::unordered_map<std::string, ContractedMetricT> &metrics,
|
||||||
QueryGraphT &graph,
|
|
||||||
std::vector<EdgeFilterT> &edge_filter,
|
|
||||||
std::uint32_t &connectivity_checksum)
|
std::uint32_t &connectivity_checksum)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
static_assert(std::is_same<ContractedMetric, ContractedMetricT>::value ||
|
||||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
std::is_same<ContractedMetricView, ContractedMetricT>::value,
|
||||||
"graph must be of type QueryGraph<>");
|
"metric must be of type ContractedMetric<>");
|
||||||
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
|
|
||||||
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
|
|
||||||
"edge_filter must be a container of vector<bool> or vector_view<bool>");
|
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
reader.ReadInto(checksum);
|
reader.ReadInto("/ch/connectivity_checksum", connectivity_checksum);
|
||||||
util::serialization::read(reader, graph);
|
|
||||||
auto count = reader.ReadElementCount64();
|
for (auto &pair : metrics)
|
||||||
edge_filter.resize(count);
|
|
||||||
for (const auto index : util::irange<std::size_t>(0, count))
|
|
||||||
{
|
{
|
||||||
storage::serialization::read(reader, edge_filter[index]);
|
serialization::read(reader, "/ch/metrics/" + pair.first, pair.second);
|
||||||
}
|
}
|
||||||
reader.ReadInto(connectivity_checksum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.hsgr file
|
// writes .osrm.hsgr file
|
||||||
template <typename QueryGraphT, typename EdgeFilterT>
|
template <typename ContractedMetricT>
|
||||||
inline void writeGraph(const boost::filesystem::path &path,
|
inline void writeGraph(const boost::filesystem::path &path,
|
||||||
unsigned checksum,
|
const std::unordered_map<std::string, ContractedMetricT> &metrics,
|
||||||
const QueryGraphT &graph,
|
|
||||||
const std::vector<EdgeFilterT> &edge_filter,
|
|
||||||
const std::uint32_t connectivity_checksum)
|
const std::uint32_t connectivity_checksum)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
static_assert(std::is_same<ContractedMetric, ContractedMetricT>::value ||
|
||||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
std::is_same<ContractedMetricView, ContractedMetricT>::value,
|
||||||
"graph must be of type QueryGraph<>");
|
"metric must be of type ContractedMetric<>");
|
||||||
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
"edge_filter must be a container of vector<bool> or vector_view<bool>");
|
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
|
||||||
|
|
||||||
writer.WriteOne(checksum);
|
writer.WriteElementCount64("/ch/connectivity_checksum", 1);
|
||||||
util::serialization::write(writer, graph);
|
writer.WriteFrom("/ch/connectivity_checksum", connectivity_checksum);
|
||||||
writer.WriteElementCount64(edge_filter.size());
|
|
||||||
for (const auto &filter : edge_filter)
|
for (const auto &pair : metrics)
|
||||||
{
|
{
|
||||||
storage::serialization::write(writer, filter);
|
serialization::write(writer, "/ch/metrics/" + pair.first, pair.second);
|
||||||
}
|
}
|
||||||
writer.WriteOne(connectivity_checksum);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,23 +128,24 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
|
|
||||||
template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT graph)
|
template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT graph)
|
||||||
{
|
{
|
||||||
std::vector<Edge> edges;
|
util::Log() << "Converting contracted graph with " << graph.GetNumberOfEdges()
|
||||||
edges.reserve(graph.GetNumberOfEdges());
|
<< " to edge list (" << (graph.GetNumberOfEdges() * sizeof(Edge)) << " bytes)";
|
||||||
|
std::vector<Edge> edges(graph.GetNumberOfEdges());
|
||||||
|
|
||||||
util::UnbufferedLog log;
|
|
||||||
log << "Getting edges of minimized graph ";
|
|
||||||
util::Percent p(log, graph.GetNumberOfNodes());
|
|
||||||
const NodeID number_of_nodes = graph.GetNumberOfNodes();
|
|
||||||
if (graph.GetNumberOfNodes())
|
|
||||||
{
|
{
|
||||||
Edge new_edge;
|
util::UnbufferedLog log;
|
||||||
|
log << "Getting edges of minimized graph ";
|
||||||
|
util::Percent p(log, graph.GetNumberOfNodes());
|
||||||
|
const NodeID number_of_nodes = graph.GetNumberOfNodes();
|
||||||
|
std::size_t edge_index = 0;
|
||||||
for (const auto node : util::irange(0u, number_of_nodes))
|
for (const auto node : util::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
p.PrintStatus(node);
|
p.PrintStatus(node);
|
||||||
for (auto edge : graph.GetAdjacentEdgeRange(node))
|
for (auto edge : graph.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const NodeID target = graph.GetTarget(edge);
|
const NodeID target = graph.GetTarget(edge);
|
||||||
const ContractorGraph::EdgeData &data = graph.GetEdgeData(edge);
|
const auto &data = graph.GetEdgeData(edge);
|
||||||
|
auto &new_edge = edges[edge_index++];
|
||||||
new_edge.source = node;
|
new_edge.source = node;
|
||||||
new_edge.target = target;
|
new_edge.target = target;
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
||||||
@@ -156,16 +157,12 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
|
|||||||
"edge id invalid");
|
"edge id invalid");
|
||||||
new_edge.data.forward = data.forward;
|
new_edge.data.forward = data.forward;
|
||||||
new_edge.data.backward = data.backward;
|
new_edge.data.backward = data.backward;
|
||||||
edges.push_back(new_edge);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BOOST_ASSERT(edge_index == edges.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort and remove duplicates
|
|
||||||
tbb::parallel_sort(edges.begin(), edges.end());
|
tbb::parallel_sort(edges.begin(), edges.end());
|
||||||
auto new_end = std::unique(edges.begin(), edges.end());
|
|
||||||
edges.resize(new_end - edges.begin());
|
|
||||||
edges.shrink_to_fit();
|
|
||||||
|
|
||||||
return edges;
|
return edges;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef OSRM_CONTRACTOR_SERIALIZATION_HPP
|
||||||
|
#define OSRM_CONTRACTOR_SERIALIZATION_HPP
|
||||||
|
|
||||||
|
#include "contractor/contracted_metric.hpp"
|
||||||
|
|
||||||
|
#include "util/serialization.hpp"
|
||||||
|
|
||||||
|
#include "storage/serialization.hpp"
|
||||||
|
#include "storage/tar.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace contractor
|
||||||
|
{
|
||||||
|
namespace serialization
|
||||||
|
{
|
||||||
|
|
||||||
|
template <storage::Ownership Ownership>
|
||||||
|
void write(storage::tar::FileWriter &writer,
|
||||||
|
const std::string &name,
|
||||||
|
const detail::ContractedMetric<Ownership> &metric)
|
||||||
|
{
|
||||||
|
util::serialization::write(writer, name + "/contracted_graph", metric.graph);
|
||||||
|
|
||||||
|
writer.WriteElementCount64(name + "/exclude", metric.edge_filter.size());
|
||||||
|
for (const auto index : util::irange<std::size_t>(0, metric.edge_filter.size()))
|
||||||
|
{
|
||||||
|
storage::serialization::write(writer,
|
||||||
|
name + "/exclude/" + std::to_string(index) + "/edge_filter",
|
||||||
|
metric.edge_filter[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <storage::Ownership Ownership>
|
||||||
|
void read(storage::tar::FileReader &reader,
|
||||||
|
const std::string &name,
|
||||||
|
detail::ContractedMetric<Ownership> &metric)
|
||||||
|
{
|
||||||
|
util::serialization::read(reader, name + "/contracted_graph", metric.graph);
|
||||||
|
|
||||||
|
metric.edge_filter.resize(reader.ReadElementCount64(name + "/exclude"));
|
||||||
|
for (const auto index : util::irange<std::size_t>(0, metric.edge_filter.size()))
|
||||||
|
{
|
||||||
|
storage::serialization::read(reader,
|
||||||
|
name + "/exclude/" + std::to_string(index) + "/edge_filter",
|
||||||
|
metric.edge_filter[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,7 +21,8 @@ struct CustomizationConfig final : storage::IOConfig
|
|||||||
".osrm.partition",
|
".osrm.partition",
|
||||||
".osrm.cells",
|
".osrm.cells",
|
||||||
".osrm.ebg_nodes",
|
".osrm.ebg_nodes",
|
||||||
".osrm.properties"},
|
".osrm.properties",
|
||||||
|
".osrm.enw"},
|
||||||
{},
|
{},
|
||||||
{".osrm.cell_metrics", ".osrm.mldgr"}),
|
{".osrm.cell_metrics", ".osrm.mldgr"}),
|
||||||
requested_num_threads(0)
|
requested_num_threads(0)
|
||||||
|
|||||||
@@ -16,28 +16,109 @@ namespace osrm
|
|||||||
namespace customizer
|
namespace customizer
|
||||||
{
|
{
|
||||||
|
|
||||||
using EdgeBasedGraphEdgeData = partitioner::EdgeBasedGraphEdgeData;
|
struct EdgeBasedGraphEdgeData
|
||||||
|
|
||||||
struct MultiLevelEdgeBasedGraph
|
|
||||||
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
|
|
||||||
{
|
{
|
||||||
using Base =
|
NodeID turn_id; // ID of the edge based node (node based edge)
|
||||||
partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
|
|
||||||
using Base::Base;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MultiLevelEdgeBasedGraphView
|
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
|
||||||
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
|
|
||||||
|
namespace serialization
|
||||||
{
|
{
|
||||||
using Base = partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
|
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||||
using Base::Base;
|
void read(storage::tar::FileReader &reader,
|
||||||
|
const std::string &name,
|
||||||
|
MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||||
|
|
||||||
|
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||||
|
void write(storage::tar::FileWriter &writer,
|
||||||
|
const std::string &name,
|
||||||
|
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||||
|
class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using SuperT = partitioner::MultiLevelGraph<EdgeDataT, Ownership>;
|
||||||
|
using PartitionerGraphT = partitioner::MultiLevelGraph<partitioner::EdgeBasedGraphEdgeData,
|
||||||
|
storage::Ownership::Container>;
|
||||||
|
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using NodeArrayEntry = typename SuperT::NodeArrayEntry;
|
||||||
|
using EdgeArrayEntry = typename SuperT::EdgeArrayEntry;
|
||||||
|
using EdgeOffset = typename SuperT::EdgeOffset;
|
||||||
|
|
||||||
|
MultiLevelGraph() = default;
|
||||||
|
MultiLevelGraph(MultiLevelGraph &&) = default;
|
||||||
|
MultiLevelGraph(const MultiLevelGraph &) = default;
|
||||||
|
MultiLevelGraph &operator=(MultiLevelGraph &&) = default;
|
||||||
|
MultiLevelGraph &operator=(const MultiLevelGraph &) = default;
|
||||||
|
|
||||||
|
MultiLevelGraph(PartitionerGraphT &&graph,
|
||||||
|
Vector<EdgeWeight> node_weights_,
|
||||||
|
Vector<EdgeDuration> node_durations_)
|
||||||
|
: node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_))
|
||||||
|
{
|
||||||
|
util::ViewOrVector<PartitionerGraphT::EdgeArrayEntry, storage::Ownership::Container>
|
||||||
|
original_edge_array;
|
||||||
|
|
||||||
|
std::tie(SuperT::node_array,
|
||||||
|
original_edge_array,
|
||||||
|
SuperT::node_to_edge_offset,
|
||||||
|
SuperT::connectivity_checksum) = std::move(graph).data();
|
||||||
|
|
||||||
|
SuperT::edge_array.reserve(original_edge_array.size());
|
||||||
|
for (const auto &edge : original_edge_array)
|
||||||
|
{
|
||||||
|
SuperT::edge_array.push_back({edge.target, {edge.data.turn_id}});
|
||||||
|
is_forward_edge.push_back(edge.data.forward);
|
||||||
|
is_backward_edge.push_back(edge.data.backward);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiLevelGraph(Vector<NodeArrayEntry> node_array_,
|
||||||
|
Vector<EdgeArrayEntry> edge_array_,
|
||||||
|
Vector<EdgeOffset> node_to_edge_offset_,
|
||||||
|
Vector<EdgeWeight> node_weights_,
|
||||||
|
Vector<EdgeDuration> node_durations_,
|
||||||
|
Vector<bool> is_forward_edge_,
|
||||||
|
Vector<bool> is_backward_edge_)
|
||||||
|
: SuperT(std::move(node_array_), std::move(edge_array_), std::move(node_to_edge_offset_)),
|
||||||
|
node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
|
||||||
|
is_forward_edge(is_forward_edge_), is_backward_edge(is_backward_edge_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeWeight GetNodeWeight(NodeID node) const { return node_weights[node]; }
|
||||||
|
|
||||||
|
EdgeWeight GetNodeDuration(NodeID node) const { return node_durations[node]; }
|
||||||
|
|
||||||
|
bool IsForwardEdge(EdgeID edge) const { return is_forward_edge[edge]; }
|
||||||
|
|
||||||
|
bool IsBackwardEdge(EdgeID edge) const { return is_backward_edge[edge]; }
|
||||||
|
|
||||||
|
friend void
|
||||||
|
serialization::read<EdgeDataT, Ownership>(storage::tar::FileReader &reader,
|
||||||
|
const std::string &name,
|
||||||
|
MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||||
|
friend void
|
||||||
|
serialization::write<EdgeDataT, Ownership>(storage::tar::FileWriter &writer,
|
||||||
|
const std::string &name,
|
||||||
|
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Vector<EdgeWeight> node_weights;
|
||||||
|
Vector<EdgeDuration> node_durations;
|
||||||
|
Vector<bool> is_forward_edge;
|
||||||
|
Vector<bool> is_backward_edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StaticEdgeBasedGraphEdge : MultiLevelEdgeBasedGraph::InputEdge
|
using MultiLevelEdgeBasedGraph =
|
||||||
{
|
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
|
||||||
using Base = MultiLevelEdgeBasedGraph::InputEdge;
|
using MultiLevelEdgeBasedGraphView =
|
||||||
using Base::Base;
|
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
#include "customizer/serialization.hpp"
|
#include "customizer/serialization.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/tar.hpp"
|
||||||
|
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace customizer
|
namespace customizer
|
||||||
@@ -16,42 +18,94 @@ namespace files
|
|||||||
|
|
||||||
// reads .osrm.cell_metrics file
|
// reads .osrm.cell_metrics file
|
||||||
template <typename CellMetricT>
|
template <typename CellMetricT>
|
||||||
inline void readCellMetrics(const boost::filesystem::path &path, std::vector<CellMetricT> &metrics)
|
inline void readCellMetrics(const boost::filesystem::path &path,
|
||||||
|
std::unordered_map<std::string, std::vector<CellMetricT>> &metrics)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
|
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
|
||||||
std::is_same<CellMetric, CellMetricT>::value,
|
std::is_same<CellMetric, CellMetricT>::value,
|
||||||
"");
|
"");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
auto num_metrics = reader.ReadElementCount64();
|
for (auto &pair : metrics)
|
||||||
metrics.resize(num_metrics);
|
|
||||||
|
|
||||||
for (auto &metric : metrics)
|
|
||||||
{
|
{
|
||||||
serialization::read(reader, metric);
|
const auto &metric_name = pair.first;
|
||||||
|
auto &metric_exclude_classes = pair.second;
|
||||||
|
|
||||||
|
auto prefix = "/mld/metrics/" + metric_name + "/exclude";
|
||||||
|
auto num_exclude_classes = reader.ReadElementCount64(prefix);
|
||||||
|
metric_exclude_classes.resize(num_exclude_classes);
|
||||||
|
|
||||||
|
auto id = 0;
|
||||||
|
for (auto &metric : metric_exclude_classes)
|
||||||
|
{
|
||||||
|
serialization::read(reader, prefix + "/" + std::to_string(id++), metric);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.cell_metrics file
|
// writes .osrm.cell_metrics file
|
||||||
template <typename CellMetricT>
|
template <typename CellMetricT>
|
||||||
inline void writeCellMetrics(const boost::filesystem::path &path,
|
inline void
|
||||||
const std::vector<CellMetricT> &metrics)
|
writeCellMetrics(const boost::filesystem::path &path,
|
||||||
|
const std::unordered_map<std::string, std::vector<CellMetricT>> &metrics)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
|
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
|
||||||
std::is_same<CellMetric, CellMetricT>::value,
|
std::is_same<CellMetric, CellMetricT>::value,
|
||||||
"");
|
"");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
writer.WriteElementCount64(metrics.size());
|
for (const auto &pair : metrics)
|
||||||
for (const auto &metric : metrics)
|
|
||||||
{
|
{
|
||||||
serialization::write(writer, metric);
|
const auto &metric_name = pair.first;
|
||||||
|
const auto &metric_exclude_classes = pair.second;
|
||||||
|
|
||||||
|
auto prefix = "/mld/metrics/" + metric_name + "/exclude";
|
||||||
|
writer.WriteElementCount64(prefix, metric_exclude_classes.size());
|
||||||
|
|
||||||
|
auto id = 0;
|
||||||
|
for (auto &exclude_metric : metric_exclude_classes)
|
||||||
|
{
|
||||||
|
serialization::write(writer, prefix + "/" + std::to_string(id++), exclude_metric);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reads .osrm.mldgr file
|
||||||
|
template <typename MultiLevelGraphT>
|
||||||
|
inline void readGraph(const boost::filesystem::path &path,
|
||||||
|
MultiLevelGraphT &graph,
|
||||||
|
std::uint32_t &connectivity_checksum)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
|
||||||
|
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
storage::tar::FileReader reader{path, storage::tar::FileReader::VerifyFingerprint};
|
||||||
|
|
||||||
|
reader.ReadInto("/mld/connectivity_checksum", connectivity_checksum);
|
||||||
|
serialization::read(reader, "/mld/multilevelgraph", graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.mldgr file
|
||||||
|
template <typename MultiLevelGraphT>
|
||||||
|
inline void writeGraph(const boost::filesystem::path &path,
|
||||||
|
const MultiLevelGraphT &graph,
|
||||||
|
const std::uint32_t connectivity_checksum)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
|
||||||
|
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
storage::tar::FileWriter writer{path, storage::tar::FileWriter::GenerateFingerprint};
|
||||||
|
|
||||||
|
writer.WriteElementCount64("/mld/connectivity_checksum", 1);
|
||||||
|
writer.WriteFrom("/mld/connectivity_checksum", connectivity_checksum);
|
||||||
|
serialization::write(writer, "/mld/multilevelgraph", graph);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#ifndef OSRM_CUSTOMIZER_SERIALIZATION_HPP
|
#ifndef OSRM_CUSTOMIZER_SERIALIZATION_HPP
|
||||||
#define OSRM_CUSTOMIZER_SERIALIZATION_HPP
|
#define OSRM_CUSTOMIZER_SERIALIZATION_HPP
|
||||||
|
|
||||||
|
#include "customizer/edge_based_graph.hpp"
|
||||||
|
|
||||||
#include "partitioner/cell_storage.hpp"
|
#include "partitioner/cell_storage.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
|
||||||
#include "storage/serialization.hpp"
|
#include "storage/serialization.hpp"
|
||||||
#include "storage/shared_memory_ownership.hpp"
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
#include "storage/tar.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -15,17 +17,49 @@ namespace serialization
|
|||||||
{
|
{
|
||||||
|
|
||||||
template <storage::Ownership Ownership>
|
template <storage::Ownership Ownership>
|
||||||
inline void read(storage::io::FileReader &reader, detail::CellMetricImpl<Ownership> &metric)
|
inline void read(storage::tar::FileReader &reader,
|
||||||
|
const std::string &name,
|
||||||
|
detail::CellMetricImpl<Ownership> &metric)
|
||||||
{
|
{
|
||||||
storage::serialization::read(reader, metric.weights);
|
storage::serialization::read(reader, name + "/weights", metric.weights);
|
||||||
storage::serialization::read(reader, metric.durations);
|
storage::serialization::read(reader, name + "/durations", metric.durations);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <storage::Ownership Ownership>
|
template <storage::Ownership Ownership>
|
||||||
inline void write(storage::io::FileWriter &writer, const detail::CellMetricImpl<Ownership> &metric)
|
inline void write(storage::tar::FileWriter &writer,
|
||||||
|
const std::string &name,
|
||||||
|
const detail::CellMetricImpl<Ownership> &metric)
|
||||||
{
|
{
|
||||||
storage::serialization::write(writer, metric.weights);
|
storage::serialization::write(writer, name + "/weights", metric.weights);
|
||||||
storage::serialization::write(writer, metric.durations);
|
storage::serialization::write(writer, name + "/durations", metric.durations);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||||
|
inline void read(storage::tar::FileReader &reader,
|
||||||
|
const std::string &name,
|
||||||
|
MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||||
|
{
|
||||||
|
storage::serialization::read(reader, name + "/node_array", graph.node_array);
|
||||||
|
storage::serialization::read(reader, name + "/node_weights", graph.node_weights);
|
||||||
|
storage::serialization::read(reader, name + "/node_durations", graph.node_durations);
|
||||||
|
storage::serialization::read(reader, name + "/edge_array", graph.edge_array);
|
||||||
|
storage::serialization::read(reader, name + "/is_forward_edge", graph.is_forward_edge);
|
||||||
|
storage::serialization::read(reader, name + "/is_backward_edge", graph.is_backward_edge);
|
||||||
|
storage::serialization::read(reader, name + "/node_to_edge_offset", graph.node_to_edge_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||||
|
inline void write(storage::tar::FileWriter &writer,
|
||||||
|
const std::string &name,
|
||||||
|
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||||
|
{
|
||||||
|
storage::serialization::write(writer, name + "/node_array", graph.node_array);
|
||||||
|
storage::serialization::write(writer, name + "/node_weights", graph.node_weights);
|
||||||
|
storage::serialization::write(writer, name + "/node_durations", graph.node_durations);
|
||||||
|
storage::serialization::write(writer, name + "/edge_array", graph.edge_array);
|
||||||
|
storage::serialization::write(writer, name + "/is_forward_edge", graph.is_forward_edge);
|
||||||
|
storage::serialization::write(writer, name + "/is_backward_edge", graph.is_backward_edge);
|
||||||
|
storage::serialization::write(writer, name + "/node_to_edge_offset", graph.node_to_edge_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ template <typename AlgorithmT> const char *name();
|
|||||||
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
|
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
|
||||||
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
|
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
|
||||||
|
|
||||||
|
// Algorithm identifier
|
||||||
|
template <typename AlgorithmT> const char *identifier();
|
||||||
|
template <> inline const char *identifier<ch::Algorithm>() { return "ch"; }
|
||||||
|
template <> inline const char *identifier<mld::Algorithm>() { return "mld"; }
|
||||||
|
|
||||||
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
|
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -45,6 +50,9 @@ template <typename AlgorithmT> struct HasMapMatching final : std::false_type
|
|||||||
template <typename AlgorithmT> struct HasManyToManySearch final : std::false_type
|
template <typename AlgorithmT> struct HasManyToManySearch final : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <typename AlgorithmT> struct SupportsDistanceAnnotationType final : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
|
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -68,6 +76,9 @@ template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
|
|||||||
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
|
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <> struct SupportsDistanceAnnotationType<ch::Algorithm> final : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
|
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -91,6 +102,9 @@ template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
|
|||||||
template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
|
template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
template <> struct SupportsDistanceAnnotationType<mld::Algorithm> final : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
|
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,56 +34,55 @@ class NearestAPI final : public BaseAPI
|
|||||||
|
|
||||||
util::json::Array waypoints;
|
util::json::Array waypoints;
|
||||||
waypoints.values.resize(phantom_nodes.front().size());
|
waypoints.values.resize(phantom_nodes.front().size());
|
||||||
std::transform(phantom_nodes.front().begin(),
|
std::transform(
|
||||||
phantom_nodes.front().end(),
|
phantom_nodes.front().begin(),
|
||||||
waypoints.values.begin(),
|
phantom_nodes.front().end(),
|
||||||
[this](const PhantomNodeWithDistance &phantom_with_distance) {
|
waypoints.values.begin(),
|
||||||
auto &phantom_node = phantom_with_distance.phantom_node;
|
[this](const PhantomNodeWithDistance &phantom_with_distance) {
|
||||||
auto waypoint = MakeWaypoint(phantom_node);
|
auto &phantom_node = phantom_with_distance.phantom_node;
|
||||||
waypoint.values["distance"] = phantom_with_distance.distance;
|
auto waypoint = MakeWaypoint(phantom_node);
|
||||||
|
waypoint.values["distance"] = phantom_with_distance.distance;
|
||||||
|
|
||||||
util::json::Array nodes;
|
util::json::Array nodes;
|
||||||
|
|
||||||
std::uint64_t from_node = 0;
|
std::uint64_t from_node = 0;
|
||||||
std::uint64_t to_node = 0;
|
std::uint64_t to_node = 0;
|
||||||
|
|
||||||
std::vector<NodeID> forward_geometry;
|
datafacade::BaseDataFacade::NodeForwardRange forward_geometry;
|
||||||
if (phantom_node.forward_segment_id.enabled)
|
if (phantom_node.forward_segment_id.enabled)
|
||||||
{
|
{
|
||||||
auto segment_id = phantom_node.forward_segment_id.id;
|
auto segment_id = phantom_node.forward_segment_id.id;
|
||||||
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
|
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
|
||||||
forward_geometry =
|
forward_geometry = facade.GetUncompressedForwardGeometry(geometry_id);
|
||||||
facade.GetUncompressedForwardGeometry(geometry_id);
|
|
||||||
|
|
||||||
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
||||||
forward_geometry[phantom_node.fwd_segment_position]);
|
forward_geometry(phantom_node.fwd_segment_position));
|
||||||
to_node = static_cast<std::uint64_t>(osm_node_id);
|
to_node = static_cast<std::uint64_t>(osm_node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantom_node.reverse_segment_id.enabled)
|
if (phantom_node.reverse_segment_id.enabled)
|
||||||
{
|
{
|
||||||
auto segment_id = phantom_node.reverse_segment_id.id;
|
auto segment_id = phantom_node.reverse_segment_id.id;
|
||||||
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
|
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
|
||||||
std::vector<NodeID> geometry =
|
const auto geometry = facade.GetUncompressedForwardGeometry(geometry_id);
|
||||||
facade.GetUncompressedForwardGeometry(geometry_id);
|
auto osm_node_id =
|
||||||
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
facade.GetOSMNodeIDOfNode(geometry(phantom_node.fwd_segment_position + 1));
|
||||||
geometry[phantom_node.fwd_segment_position + 1]);
|
from_node = static_cast<std::uint64_t>(osm_node_id);
|
||||||
from_node = static_cast<std::uint64_t>(osm_node_id);
|
}
|
||||||
}
|
else if (phantom_node.forward_segment_id.enabled &&
|
||||||
else if (phantom_node.forward_segment_id.enabled &&
|
phantom_node.fwd_segment_position > 0)
|
||||||
phantom_node.fwd_segment_position > 0)
|
{
|
||||||
{
|
// In the case of one way, rely on forward segment only
|
||||||
// In the case of one way, rely on forward segment only
|
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
||||||
auto osm_node_id = facade.GetOSMNodeIDOfNode(
|
forward_geometry(phantom_node.fwd_segment_position - 1));
|
||||||
forward_geometry[phantom_node.fwd_segment_position - 1]);
|
from_node = static_cast<std::uint64_t>(osm_node_id);
|
||||||
from_node = static_cast<std::uint64_t>(osm_node_id);
|
}
|
||||||
}
|
nodes.values.push_back(from_node);
|
||||||
nodes.values.push_back(from_node);
|
nodes.values.push_back(to_node);
|
||||||
nodes.values.push_back(to_node);
|
waypoint.values["nodes"] = std::move(nodes);
|
||||||
waypoint.values["nodes"] = std::move(nodes);
|
|
||||||
|
|
||||||
return waypoint;
|
return waypoint;
|
||||||
});
|
});
|
||||||
|
|
||||||
response.values["code"] = "Ok";
|
response.values["code"] = "Ok";
|
||||||
response.values["waypoints"] = std::move(waypoints);
|
response.values["waypoints"] = std::move(waypoints);
|
||||||
|
|||||||
@@ -148,6 +148,9 @@ class RouteAPI : public BaseAPI
|
|||||||
// processing is performed
|
// processing is performed
|
||||||
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);
|
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);
|
||||||
|
|
||||||
|
// Collapse segregated steps before others
|
||||||
|
steps = guidance::collapseSegregatedTurnInstructions(std::move(steps));
|
||||||
|
|
||||||
/* Perform step-based post-processing.
|
/* Perform step-based post-processing.
|
||||||
*
|
*
|
||||||
* Using post-processing on basis of route-steps for a single leg at a time
|
* Using post-processing on basis of route-steps for a single leg at a time
|
||||||
@@ -321,6 +324,23 @@ class RouteAPI : public BaseAPI
|
|||||||
}
|
}
|
||||||
annotation.values["nodes"] = std::move(nodes);
|
annotation.values["nodes"] = std::move(nodes);
|
||||||
}
|
}
|
||||||
|
// Add any supporting metadata, if needed
|
||||||
|
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
|
||||||
|
{
|
||||||
|
const auto MAX_DATASOURCE_ID = 255u;
|
||||||
|
util::json::Object metadata;
|
||||||
|
util::json::Array datasource_names;
|
||||||
|
for (auto i = 0u; i < MAX_DATASOURCE_ID; i++)
|
||||||
|
{
|
||||||
|
const auto name = facade.GetDatasourceName(i);
|
||||||
|
// Length of 0 indicates the first empty name, so we can stop here
|
||||||
|
if (name.size() == 0)
|
||||||
|
break;
|
||||||
|
datasource_names.values.push_back(std::string(facade.GetDatasourceName(i)));
|
||||||
|
}
|
||||||
|
metadata.values["datasource_names"] = datasource_names;
|
||||||
|
annotation.values["metadata"] = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
annotations.push_back(std::move(annotation));
|
annotations.push_back(std::move(annotation));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,10 @@ class TableAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void MakeResponse(const std::vector<EdgeWeight> &durations,
|
virtual void
|
||||||
const std::vector<PhantomNode> &phantoms,
|
MakeResponse(const std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> &tables,
|
||||||
util::json::Object &response) const
|
const std::vector<PhantomNode> &phantoms,
|
||||||
|
util::json::Object &response) const
|
||||||
{
|
{
|
||||||
auto number_of_sources = parameters.sources.size();
|
auto number_of_sources = parameters.sources.size();
|
||||||
auto number_of_destinations = parameters.destinations.size();
|
auto number_of_destinations = parameters.destinations.size();
|
||||||
@@ -64,8 +65,18 @@ class TableAPI final : public BaseAPI
|
|||||||
response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations);
|
response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations);
|
||||||
}
|
}
|
||||||
|
|
||||||
response.values["durations"] =
|
if (parameters.annotations & TableParameters::AnnotationsType::Duration)
|
||||||
MakeTable(durations, number_of_sources, number_of_destinations);
|
{
|
||||||
|
response.values["durations"] =
|
||||||
|
MakeDurationTable(tables.first, number_of_sources, number_of_destinations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters.annotations & TableParameters::AnnotationsType::Distance)
|
||||||
|
{
|
||||||
|
response.values["distances"] =
|
||||||
|
MakeDistanceTable(tables.second, number_of_sources, number_of_destinations);
|
||||||
|
}
|
||||||
|
|
||||||
response.values["code"] = "Ok";
|
response.values["code"] = "Ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +108,9 @@ class TableAPI final : public BaseAPI
|
|||||||
return json_waypoints;
|
return json_waypoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual util::json::Array MakeTable(const std::vector<EdgeWeight> &values,
|
virtual util::json::Array MakeDurationTable(const std::vector<EdgeWeight> &values,
|
||||||
std::size_t number_of_rows,
|
std::size_t number_of_rows,
|
||||||
std::size_t number_of_columns) const
|
std::size_t number_of_columns) const
|
||||||
{
|
{
|
||||||
util::json::Array json_table;
|
util::json::Array json_table;
|
||||||
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
|
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
|
||||||
@@ -116,6 +127,7 @@ class TableAPI final : public BaseAPI
|
|||||||
{
|
{
|
||||||
return util::json::Value(util::json::Null());
|
return util::json::Value(util::json::Null());
|
||||||
}
|
}
|
||||||
|
// division by 10 because the duration is in deciseconds (10s)
|
||||||
return util::json::Value(util::json::Number(duration / 10.));
|
return util::json::Value(util::json::Number(duration / 10.));
|
||||||
});
|
});
|
||||||
json_table.values.push_back(std::move(json_row));
|
json_table.values.push_back(std::move(json_row));
|
||||||
@@ -123,6 +135,34 @@ class TableAPI final : public BaseAPI
|
|||||||
return json_table;
|
return json_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual util::json::Array MakeDistanceTable(const std::vector<EdgeDistance> &values,
|
||||||
|
std::size_t number_of_rows,
|
||||||
|
std::size_t number_of_columns) const
|
||||||
|
{
|
||||||
|
util::json::Array json_table;
|
||||||
|
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
|
||||||
|
{
|
||||||
|
util::json::Array json_row;
|
||||||
|
auto row_begin_iterator = values.begin() + (row * number_of_columns);
|
||||||
|
auto row_end_iterator = values.begin() + ((row + 1) * number_of_columns);
|
||||||
|
json_row.values.resize(number_of_columns);
|
||||||
|
std::transform(row_begin_iterator,
|
||||||
|
row_end_iterator,
|
||||||
|
json_row.values.begin(),
|
||||||
|
[](const EdgeDistance distance) {
|
||||||
|
if (distance == INVALID_EDGE_DISTANCE)
|
||||||
|
{
|
||||||
|
return util::json::Value(util::json::Null());
|
||||||
|
}
|
||||||
|
// round to single decimal place
|
||||||
|
return util::json::Value(
|
||||||
|
util::json::Number(std::round(distance * 10) / 10.));
|
||||||
|
});
|
||||||
|
json_table.values.push_back(std::move(json_row));
|
||||||
|
}
|
||||||
|
return json_table;
|
||||||
|
}
|
||||||
|
|
||||||
const TableParameters ¶meters;
|
const TableParameters ¶meters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,16 @@ struct TableParameters : public BaseParameters
|
|||||||
std::vector<std::size_t> sources;
|
std::vector<std::size_t> sources;
|
||||||
std::vector<std::size_t> destinations;
|
std::vector<std::size_t> destinations;
|
||||||
|
|
||||||
|
enum class AnnotationsType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Duration = 0x01,
|
||||||
|
Distance = 0x02,
|
||||||
|
All = Duration | Distance
|
||||||
|
};
|
||||||
|
|
||||||
|
AnnotationsType annotations = AnnotationsType::Duration;
|
||||||
|
|
||||||
TableParameters() = default;
|
TableParameters() = default;
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
TableParameters(std::vector<std::size_t> sources_,
|
TableParameters(std::vector<std::size_t> sources_,
|
||||||
@@ -70,6 +80,16 @@ struct TableParameters : public BaseParameters
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
TableParameters(std::vector<std::size_t> sources_,
|
||||||
|
std::vector<std::size_t> destinations_,
|
||||||
|
const AnnotationsType annotations_,
|
||||||
|
Args... args_)
|
||||||
|
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
|
||||||
|
destinations{std::move(destinations_)}, annotations{annotations_}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool IsValid() const
|
bool IsValid() const
|
||||||
{
|
{
|
||||||
if (!BaseParameters::IsValid())
|
if (!BaseParameters::IsValid())
|
||||||
@@ -79,7 +99,7 @@ struct TableParameters : public BaseParameters
|
|||||||
if (coordinates.size() < 2)
|
if (coordinates.size() < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's her fault
|
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's their fault
|
||||||
|
|
||||||
// 2/ len(srcs) and len(dsts) smaller or equal to len(locations)
|
// 2/ len(srcs) and len(dsts) smaller or equal to len(locations)
|
||||||
if (sources.size() > coordinates.size())
|
if (sources.size() > coordinates.size())
|
||||||
@@ -100,6 +120,26 @@ struct TableParameters : public BaseParameters
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
inline bool operator&(TableParameters::AnnotationsType lhs, TableParameters::AnnotationsType rhs)
|
||||||
|
{
|
||||||
|
return static_cast<bool>(
|
||||||
|
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(lhs) &
|
||||||
|
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TableParameters::AnnotationsType operator|(TableParameters::AnnotationsType lhs,
|
||||||
|
TableParameters::AnnotationsType rhs)
|
||||||
|
{
|
||||||
|
return (TableParameters::AnnotationsType)(
|
||||||
|
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(lhs) |
|
||||||
|
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TableParameters::AnnotationsType &operator|=(TableParameters::AnnotationsType &lhs,
|
||||||
|
TableParameters::AnnotationsType rhs)
|
||||||
|
{
|
||||||
|
return lhs = lhs | rhs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ inline std::string encodeBase64(const std::string &x) { return encodeBase64(x.da
|
|||||||
// Encode any sufficiently trivial object to Base64.
|
// Encode any sufficiently trivial object to Base64.
|
||||||
template <typename T> std::string encodeBase64Bytewise(const T &x)
|
template <typename T> std::string encodeBase64Bytewise(const T &x)
|
||||||
{
|
{
|
||||||
#if not defined __GNUC__ or __GNUC__ > 4
|
#if !defined(__GNUC__) || (__GNUC__ > 4)
|
||||||
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ inline std::string decodeBase64(const std::string &encoded)
|
|||||||
// Decodes from Base 64 to any sufficiently trivial object.
|
// Decodes from Base 64 to any sufficiently trivial object.
|
||||||
template <typename T> T decodeBase64Bytewise(const std::string &encoded)
|
template <typename T> T decodeBase64Bytewise(const std::string &encoded)
|
||||||
{
|
{
|
||||||
#if not defined __GNUC__ or __GNUC__ > 4
|
#if !defined(__GNUC__) || (__GNUC__ > 4)
|
||||||
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -32,20 +32,35 @@ template <typename AlgorithmT, typename FacadeT> class DataWatchdogImpl;
|
|||||||
template <typename AlgorithmT>
|
template <typename AlgorithmT>
|
||||||
class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>> final
|
class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>> final
|
||||||
{
|
{
|
||||||
using mutex_type = typename storage::SharedMonitor<storage::SharedDataTimestamp>::mutex_type;
|
using mutex_type = typename storage::SharedMonitor<storage::SharedRegionRegister>::mutex_type;
|
||||||
using Facade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
|
using Facade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataWatchdogImpl() : active(true), timestamp(0)
|
DataWatchdogImpl(const std::string &dataset_name) : dataset_name(dataset_name), active(true)
|
||||||
{
|
{
|
||||||
// create the initial facade before launching the watchdog thread
|
// create the initial facade before launching the watchdog thread
|
||||||
{
|
{
|
||||||
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
||||||
|
|
||||||
|
auto &shared_register = barrier.data();
|
||||||
|
auto static_region_id = shared_register.Find(dataset_name + "/static");
|
||||||
|
auto updatable_region_id = shared_register.Find(dataset_name + "/updatable");
|
||||||
|
if (static_region_id == storage::SharedRegionRegister::INVALID_REGION_ID ||
|
||||||
|
updatable_region_id == storage::SharedRegionRegister::INVALID_REGION_ID)
|
||||||
|
{
|
||||||
|
throw util::exception("Could not find shared memory region for \"" + dataset_name +
|
||||||
|
"/data\". Did you run osrm-datastore?");
|
||||||
|
}
|
||||||
|
static_shared_region = &shared_register.GetRegion(static_region_id);
|
||||||
|
updatable_shared_region = &shared_register.GetRegion(updatable_region_id);
|
||||||
|
static_region = *static_shared_region;
|
||||||
|
updatable_region = *updatable_shared_region;
|
||||||
|
|
||||||
facade_factory =
|
facade_factory =
|
||||||
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
|
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
|
||||||
std::make_shared<datafacade::SharedMemoryAllocator>(barrier.data().region));
|
std::make_shared<datafacade::SharedMemoryAllocator>(
|
||||||
timestamp = barrier.data().timestamp;
|
std::vector<storage::SharedRegionRegister::ShmKey>{
|
||||||
|
static_region.shm_key, updatable_region.shm_key}));
|
||||||
}
|
}
|
||||||
|
|
||||||
watcher = std::thread(&DataWatchdogImpl::Run, this);
|
watcher = std::thread(&DataWatchdogImpl::Run, this);
|
||||||
@@ -74,30 +89,46 @@ class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacad
|
|||||||
{
|
{
|
||||||
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
||||||
|
|
||||||
while (active && timestamp == barrier.data().timestamp)
|
while (active && static_region.timestamp == static_shared_region->timestamp &&
|
||||||
|
updatable_region.timestamp == updatable_shared_region->timestamp)
|
||||||
{
|
{
|
||||||
barrier.wait(current_region_lock);
|
barrier.wait(current_region_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timestamp != barrier.data().timestamp)
|
if (!active)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (static_region.timestamp != static_shared_region->timestamp)
|
||||||
{
|
{
|
||||||
auto region = barrier.data().region;
|
static_region = *static_shared_region;
|
||||||
facade_factory =
|
|
||||||
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
|
|
||||||
std::make_shared<datafacade::SharedMemoryAllocator>(region));
|
|
||||||
timestamp = barrier.data().timestamp;
|
|
||||||
util::Log() << "updated facade to region " << region << " with timestamp "
|
|
||||||
<< timestamp;
|
|
||||||
}
|
}
|
||||||
|
if (updatable_region.timestamp != updatable_shared_region->timestamp)
|
||||||
|
{
|
||||||
|
updatable_region = *updatable_shared_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
util::Log() << "updated facade to regions " << (int)static_region.shm_key << " and "
|
||||||
|
<< (int)updatable_region.shm_key << " with timestamps "
|
||||||
|
<< static_region.timestamp << " and " << updatable_region.timestamp;
|
||||||
|
|
||||||
|
facade_factory =
|
||||||
|
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
|
||||||
|
std::make_shared<datafacade::SharedMemoryAllocator>(
|
||||||
|
std::vector<storage::SharedRegionRegister::ShmKey>{
|
||||||
|
static_region.shm_key, updatable_region.shm_key}));
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Log() << "DataWatchdog thread stopped";
|
util::Log() << "DataWatchdog thread stopped";
|
||||||
}
|
}
|
||||||
|
|
||||||
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
|
const std::string dataset_name;
|
||||||
|
storage::SharedMonitor<storage::SharedRegionRegister> barrier;
|
||||||
std::thread watcher;
|
std::thread watcher;
|
||||||
bool active;
|
bool active;
|
||||||
unsigned timestamp;
|
storage::SharedRegion static_region;
|
||||||
|
storage::SharedRegion updatable_region;
|
||||||
|
storage::SharedRegion *static_shared_region;
|
||||||
|
storage::SharedRegion *updatable_shared_region;
|
||||||
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT> facade_factory;
|
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT> facade_factory;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define OSRM_ENGINE_DATAFACADE_ALGORITHM_DATAFACADE_HPP
|
#define OSRM_ENGINE_DATAFACADE_ALGORITHM_DATAFACADE_HPP
|
||||||
|
|
||||||
#include "contractor/query_edge.hpp"
|
#include "contractor/query_edge.hpp"
|
||||||
|
#include "customizer/edge_based_graph.hpp"
|
||||||
#include "extractor/edge_based_edge.hpp"
|
#include "extractor/edge_based_edge.hpp"
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
|
|
||||||
@@ -59,22 +60,32 @@ template <> class AlgorithmDataFacade<CH>
|
|||||||
template <> class AlgorithmDataFacade<MLD>
|
template <> class AlgorithmDataFacade<MLD>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
|
using EdgeData = customizer::EdgeBasedGraphEdgeData;
|
||||||
using EdgeRange = util::range<EdgeID>;
|
using EdgeRange = util::range<EdgeID>;
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
virtual unsigned GetNumberOfNodes() const = 0;
|
virtual unsigned GetNumberOfNodes() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetMaxBorderNodeID() const = 0;
|
||||||
|
|
||||||
virtual unsigned GetNumberOfEdges() const = 0;
|
virtual unsigned GetNumberOfEdges() const = 0;
|
||||||
|
|
||||||
virtual unsigned GetOutDegree(const NodeID n) const = 0;
|
virtual unsigned GetOutDegree(const NodeID n) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeWeight GetNodeWeight(const NodeID node) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed
|
||||||
|
|
||||||
|
virtual bool IsForwardEdge(EdgeID edge) const = 0;
|
||||||
|
|
||||||
|
virtual bool IsBackwardEdge(EdgeID edge) const = 0;
|
||||||
|
|
||||||
virtual NodeID GetTarget(const EdgeID e) const = 0;
|
virtual NodeID GetTarget(const EdgeID e) const = 0;
|
||||||
|
|
||||||
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
|
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
|
||||||
|
|
||||||
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
|
|
||||||
|
|
||||||
virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
|
virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
|
||||||
|
|
||||||
virtual const partitioner::CellStorageView &GetCellStorage() const = 0;
|
virtual const partitioner::CellStorageView &GetCellStorage() const = 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef OSRM_ENGINE_DATAFACADE_CONTIGUOUS_BLOCK_ALLOCATOR_HPP_
|
#ifndef OSRM_ENGINE_DATAFACADE_CONTIGUOUS_BLOCK_ALLOCATOR_HPP_
|
||||||
#define OSRM_ENGINE_DATAFACADE_CONTIGUOUS_BLOCK_ALLOCATOR_HPP_
|
#define OSRM_ENGINE_DATAFACADE_CONTIGUOUS_BLOCK_ALLOCATOR_HPP_
|
||||||
|
|
||||||
#include "storage/shared_datatype.hpp"
|
#include "storage/shared_data_index.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -16,8 +16,7 @@ class ContiguousBlockAllocator
|
|||||||
virtual ~ContiguousBlockAllocator() = default;
|
virtual ~ContiguousBlockAllocator() = default;
|
||||||
|
|
||||||
// interface to give access to the datafacades
|
// interface to give access to the datafacades
|
||||||
virtual storage::DataLayout &GetLayout() = 0;
|
virtual const storage::SharedDataIndex &GetIndex() = 0;
|
||||||
virtual char *GetMemory() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace datafacade
|
} // namespace datafacade
|
||||||
|
|||||||
@@ -9,44 +9,13 @@
|
|||||||
#include "engine/approach.hpp"
|
#include "engine/approach.hpp"
|
||||||
#include "engine/geospatial_query.hpp"
|
#include "engine/geospatial_query.hpp"
|
||||||
|
|
||||||
#include "customizer/edge_based_graph.hpp"
|
|
||||||
|
|
||||||
#include "extractor/datasources.hpp"
|
|
||||||
#include "extractor/edge_based_node.hpp"
|
|
||||||
#include "extractor/intersection_bearings_container.hpp"
|
|
||||||
#include "extractor/maneuver_override.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_lane_types.hpp"
|
|
||||||
|
|
||||||
#include "guidance/turn_bearing.hpp"
|
|
||||||
#include "guidance/turn_data_container.hpp"
|
|
||||||
#include "guidance/turn_instruction.hpp"
|
|
||||||
|
|
||||||
#include "contractor/query_graph.hpp"
|
|
||||||
|
|
||||||
#include "partitioner/cell_storage.hpp"
|
|
||||||
#include "partitioner/multi_level_partition.hpp"
|
|
||||||
|
|
||||||
#include "storage/shared_datatype.hpp"
|
#include "storage/shared_datatype.hpp"
|
||||||
#include "storage/shared_memory_ownership.hpp"
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
#include "storage/view_factory.hpp"
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/exception_utils.hpp"
|
#include "util/exception_utils.hpp"
|
||||||
#include "util/filtered_graph.hpp"
|
|
||||||
#include "util/guidance/bearing_class.hpp"
|
|
||||||
#include "util/guidance/entry_class.hpp"
|
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
#include "util/name_table.hpp"
|
|
||||||
#include "util/packed_vector.hpp"
|
|
||||||
#include "util/range_table.hpp"
|
|
||||||
#include "util/rectangle.hpp"
|
|
||||||
#include "util/static_graph.hpp"
|
|
||||||
#include "util/static_rtree.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -81,44 +50,22 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
|
|||||||
// allocator that keeps the allocation data
|
// allocator that keeps the allocation data
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||||
|
|
||||||
void InitializeGraphPointer(storage::DataLayout &data_layout,
|
|
||||||
char *memory_block,
|
|
||||||
const std::size_t exclude_index)
|
|
||||||
{
|
|
||||||
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
|
|
||||||
memory_block, storage::DataLayout::CH_GRAPH_NODE_LIST);
|
|
||||||
|
|
||||||
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
|
|
||||||
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
|
|
||||||
|
|
||||||
auto filter_block_id = static_cast<storage::DataLayout::BlockID>(
|
|
||||||
storage::DataLayout::CH_EDGE_FILTER_0 + exclude_index);
|
|
||||||
|
|
||||||
auto edge_filter_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, filter_block_id);
|
|
||||||
|
|
||||||
util::vector_view<GraphNode> node_list(
|
|
||||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
|
|
||||||
util::vector_view<GraphEdge> edge_list(
|
|
||||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
|
|
||||||
|
|
||||||
util::vector_view<bool> edge_filter(edge_filter_ptr,
|
|
||||||
data_layout.num_entries[filter_block_id]);
|
|
||||||
m_query_graph = QueryGraph({node_list, edge_list}, edge_filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
ContiguousInternalMemoryAlgorithmDataFacade(
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator_, std::size_t exclude_index)
|
std::shared_ptr<ContiguousBlockAllocator> allocator_,
|
||||||
|
const std::string &metric_name,
|
||||||
|
std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
InitializeInternalPointers(allocator->GetIndex(), metric_name, exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
void InitializeInternalPointers(const storage::SharedDataIndex &index,
|
||||||
char *memory_block,
|
const std::string &metric_name,
|
||||||
const std::size_t exclude_index)
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeGraphPointer(data_layout, memory_block, exclude_index);
|
m_query_graph =
|
||||||
|
make_filtered_graph_view(index, "/ch/metrics/" + metric_name, exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// search graph access
|
// search graph access
|
||||||
@@ -186,11 +133,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
using RTreeNode = SharedRTree::TreeNode;
|
using RTreeNode = SharedRTree::TreeNode;
|
||||||
|
|
||||||
extractor::ClassData exclude_mask;
|
extractor::ClassData exclude_mask;
|
||||||
std::string m_timestamp;
|
|
||||||
extractor::ProfileProperties *m_profile_properties;
|
extractor::ProfileProperties *m_profile_properties;
|
||||||
extractor::Datasources *m_datasources;
|
extractor::Datasources *m_datasources;
|
||||||
|
|
||||||
unsigned m_check_sum;
|
std::uint32_t m_check_sum;
|
||||||
util::vector_view<util::Coordinate> m_coordinate_list;
|
util::vector_view<util::Coordinate> m_coordinate_list;
|
||||||
extractor::PackedOSMIDsView m_osmnodeid_list;
|
extractor::PackedOSMIDsView m_osmnodeid_list;
|
||||||
util::vector_view<std::uint32_t> m_lane_description_offsets;
|
util::vector_view<std::uint32_t> m_lane_description_offsets;
|
||||||
@@ -209,13 +155,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
util::vector_view<extractor::StorageManeuverOverride> m_maneuver_overrides;
|
util::vector_view<extractor::StorageManeuverOverride> m_maneuver_overrides;
|
||||||
util::vector_view<NodeID> m_maneuver_override_node_sequences;
|
util::vector_view<NodeID> m_maneuver_override_node_sequences;
|
||||||
|
|
||||||
std::unique_ptr<SharedRTree> m_static_rtree;
|
SharedRTree m_static_rtree;
|
||||||
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
|
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
|
||||||
boost::filesystem::path file_index_path;
|
boost::filesystem::path file_index_path;
|
||||||
|
|
||||||
extractor::IntersectionBearingsView intersection_bearings_view;
|
extractor::IntersectionBearingsView intersection_bearings_view;
|
||||||
|
|
||||||
util::NameTable m_name_table;
|
extractor::NameTableView m_name_table;
|
||||||
// the look-up table for entry classes. An entry class lists the possibility of entry for all
|
// the look-up table for entry classes. An entry class lists the possibility of entry for all
|
||||||
// available turns. Such a class id is stored with every edge.
|
// available turns. Such a class id is stored with every edge.
|
||||||
util::vector_view<util::guidance::EntryClass> m_entry_class_table;
|
util::vector_view<util::guidance::EntryClass> m_entry_class_table;
|
||||||
@@ -223,328 +169,62 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
// allocator that keeps the allocation data
|
// allocator that keeps the allocation data
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||||
|
|
||||||
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout,
|
void InitializeInternalPointers(const storage::SharedDataIndex &index,
|
||||||
char *memory_block,
|
const std::string &metric_name,
|
||||||
const std::size_t exclude_index)
|
|
||||||
{
|
|
||||||
m_profile_properties = data_layout.GetBlockPtr<extractor::ProfileProperties>(
|
|
||||||
memory_block, storage::DataLayout::PROPERTIES);
|
|
||||||
|
|
||||||
exclude_mask = m_profile_properties->excludable_classes[exclude_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto timestamp_ptr =
|
|
||||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::TIMESTAMP);
|
|
||||||
m_timestamp.resize(data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP));
|
|
||||||
std::copy(timestamp_ptr,
|
|
||||||
timestamp_ptr + data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP),
|
|
||||||
m_timestamp.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeChecksumPointer(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
m_check_sum =
|
|
||||||
*data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::HSGR_CHECKSUM);
|
|
||||||
util::Log() << "set checksum: " << m_check_sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeRTreePointers(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
|
|
||||||
|
|
||||||
const auto file_index_ptr =
|
|
||||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::FILE_INDEX_PATH);
|
|
||||||
file_index_path = boost::filesystem::path(file_index_ptr);
|
|
||||||
if (!boost::filesystem::exists(file_index_path))
|
|
||||||
{
|
|
||||||
util::Log(logDEBUG) << "Leaf file name " << file_index_path.string();
|
|
||||||
throw util::exception("Could not load " + file_index_path.string() +
|
|
||||||
"Is any data loaded into shared memory?" + SOURCE_REF);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto tree_nodes_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,
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
const auto coordinate_list_ptr =
|
|
||||||
layout.GetBlockPtr<util::Coordinate>(memory_ptr, storage::DataLayout::COORDINATE_LIST);
|
|
||||||
m_coordinate_list.reset(coordinate_list_ptr,
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
|
|
||||||
char *memory_ptr)
|
|
||||||
{
|
|
||||||
const auto edge_based_node_list_ptr = layout.GetBlockPtr<extractor::EdgeBasedNode>(
|
|
||||||
memory_ptr, storage::DataLayout::EDGE_BASED_NODE_DATA_LIST);
|
|
||||||
util::vector_view<extractor::EdgeBasedNode> edge_based_node_data_list(
|
|
||||||
edge_based_node_list_ptr,
|
|
||||||
layout.num_entries[storage::DataLayout::EDGE_BASED_NODE_DATA_LIST]);
|
|
||||||
|
|
||||||
const auto annotation_data_list_ptr =
|
|
||||||
layout.GetBlockPtr<extractor::NodeBasedEdgeAnnotation>(
|
|
||||||
memory_ptr, storage::DataLayout::ANNOTATION_DATA_LIST);
|
|
||||||
util::vector_view<extractor::NodeBasedEdgeAnnotation> annotation_data(
|
|
||||||
annotation_data_list_ptr,
|
|
||||||
layout.num_entries[storage::DataLayout::ANNOTATION_DATA_LIST]);
|
|
||||||
|
|
||||||
edge_based_node_data = extractor::EdgeBasedNodeDataView(
|
|
||||||
std::move(edge_based_node_data_list), std::move(annotation_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
|
||||||
{
|
|
||||||
const auto lane_data_id_ptr =
|
|
||||||
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
|
|
||||||
util::vector_view<LaneDataID> lane_data_ids(
|
|
||||||
lane_data_id_ptr, layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
|
|
||||||
|
|
||||||
const auto turn_instruction_list_ptr = layout.GetBlockPtr<guidance::TurnInstruction>(
|
|
||||||
memory_ptr, storage::DataLayout::TURN_INSTRUCTION);
|
|
||||||
util::vector_view<guidance::TurnInstruction> turn_instructions(
|
|
||||||
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
|
||||||
|
|
||||||
const auto entry_class_id_list_ptr =
|
|
||||||
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
|
|
||||||
util::vector_view<EntryClassID> entry_class_ids(
|
|
||||||
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
|
||||||
|
|
||||||
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing>(
|
|
||||||
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
|
||||||
util::vector_view<guidance::TurnBearing> pre_turn_bearings(
|
|
||||||
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
|
||||||
|
|
||||||
const auto post_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing>(
|
|
||||||
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
|
||||||
util::vector_view<guidance::TurnBearing> post_turn_bearings(
|
|
||||||
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
|
||||||
|
|
||||||
turn_data = guidance::TurnDataView(std::move(turn_instructions),
|
|
||||||
std::move(lane_data_ids),
|
|
||||||
std::move(entry_class_ids),
|
|
||||||
std::move(pre_turn_bearings),
|
|
||||||
std::move(post_turn_bearings));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto name_data_ptr =
|
|
||||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::NAME_CHAR_DATA);
|
|
||||||
const auto name_data_size = data_layout.num_entries[storage::DataLayout::NAME_CHAR_DATA];
|
|
||||||
m_name_table.reset(name_data_ptr, name_data_ptr + name_data_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeTurnLaneDescriptionsPointers(storage::DataLayout &data_layout,
|
|
||||||
char *memory_block)
|
|
||||||
{
|
|
||||||
auto offsets_ptr = data_layout.GetBlockPtr<std::uint32_t>(
|
|
||||||
memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS);
|
|
||||||
util::vector_view<std::uint32_t> offsets(
|
|
||||||
offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]);
|
|
||||||
m_lane_description_offsets = std::move(offsets);
|
|
||||||
|
|
||||||
auto masks_ptr = data_layout.GetBlockPtr<extractor::TurnLaneType::Mask>(
|
|
||||||
memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS);
|
|
||||||
|
|
||||||
util::vector_view<extractor::TurnLaneType::Mask> masks(
|
|
||||||
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
|
|
||||||
m_lane_description_masks = std::move(masks);
|
|
||||||
|
|
||||||
const auto lane_tupel_id_pair_ptr =
|
|
||||||
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
|
|
||||||
memory_block, storage::DataLayout::TURN_LANE_DATA);
|
|
||||||
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
|
|
||||||
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
|
|
||||||
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto turn_weight_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
|
||||||
memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES);
|
|
||||||
m_turn_weight_penalties = util::vector_view<TurnPenalty>(
|
|
||||||
turn_weight_penalties_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
|
|
||||||
auto turn_duration_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
|
||||||
memory_block, storage::DataLayout::TURN_DURATION_PENALTIES);
|
|
||||||
m_turn_duration_penalties = util::vector_view<TurnPenalty>(
|
|
||||||
turn_duration_penalties_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto geometries_index_ptr =
|
|
||||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::GEOMETRIES_INDEX);
|
|
||||||
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);
|
|
||||||
|
|
||||||
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_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_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_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_fwd_datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
|
|
||||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_DATASOURCES_LIST);
|
|
||||||
util::vector_view<DatasourceID> geometry_fwd_datasources_list(
|
|
||||||
geometries_fwd_datasources_list_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DATASOURCES_LIST]);
|
|
||||||
|
|
||||||
auto geometries_rev_datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
|
|
||||||
memory_block, storage::DataLayout::GEOMETRIES_REV_DATASOURCES_LIST);
|
|
||||||
util::vector_view<DatasourceID> geometry_rev_datasources_list(
|
|
||||||
geometries_rev_datasources_list_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DATASOURCES_LIST]);
|
|
||||||
|
|
||||||
segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices),
|
|
||||||
std::move(geometry_node_list),
|
|
||||||
std::move(geometry_fwd_weight_list),
|
|
||||||
std::move(geometry_rev_weight_list),
|
|
||||||
std::move(geometry_fwd_duration_list),
|
|
||||||
std::move(geometry_rev_duration_list),
|
|
||||||
std::move(geometry_fwd_datasources_list),
|
|
||||||
std::move(geometry_rev_datasources_list)};
|
|
||||||
|
|
||||||
m_datasources = data_layout.GetBlockPtr<extractor::Datasources>(
|
|
||||||
memory_block, storage::DataLayout::DATASOURCES_NAMES);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeIntersectionClassPointers(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
|
|
||||||
memory_block, storage::DataLayout::BEARING_CLASSID);
|
|
||||||
util::vector_view<BearingClassID> bearing_class_id(
|
|
||||||
bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]);
|
|
||||||
|
|
||||||
auto bearing_values_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
|
|
||||||
memory_block, storage::DataLayout::BEARING_VALUES);
|
|
||||||
util::vector_view<DiscreteBearing> bearing_values(
|
|
||||||
bearing_values_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]);
|
|
||||||
|
|
||||||
auto offsets_ptr =
|
|
||||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
|
|
||||||
auto blocks_ptr =
|
|
||||||
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::BEARING_BLOCKS);
|
|
||||||
util::vector_view<unsigned> bearing_offsets(
|
|
||||||
offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]);
|
|
||||||
util::vector_view<IndexBlock> bearing_blocks(
|
|
||||||
blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]);
|
|
||||||
|
|
||||||
util::RangeTable<16, storage::Ownership::View> bearing_range_table(
|
|
||||||
bearing_offsets, bearing_blocks, static_cast<unsigned>(bearing_values.size()));
|
|
||||||
|
|
||||||
intersection_bearings_view = extractor::IntersectionBearingsView{
|
|
||||||
std::move(bearing_values), std::move(bearing_class_id), std::move(bearing_range_table)};
|
|
||||||
|
|
||||||
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
|
|
||||||
memory_block, storage::DataLayout::ENTRY_CLASS);
|
|
||||||
util::vector_view<util::guidance::EntryClass> entry_class_table(
|
|
||||||
entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]);
|
|
||||||
m_entry_class_table = std::move(entry_class_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeManeuverOverridePointers(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto maneuver_overrides_ptr = data_layout.GetBlockPtr<extractor::StorageManeuverOverride>(
|
|
||||||
memory_block, storage::DataLayout::MANEUVER_OVERRIDES);
|
|
||||||
m_maneuver_overrides = util::vector_view<extractor::StorageManeuverOverride>(
|
|
||||||
maneuver_overrides_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::MANEUVER_OVERRIDES]);
|
|
||||||
|
|
||||||
auto maneuver_override_node_sequences_ptr = data_layout.GetBlockPtr<NodeID>(
|
|
||||||
memory_block, storage::DataLayout::MANEUVER_OVERRIDE_NODE_SEQUENCES);
|
|
||||||
m_maneuver_override_node_sequences = util::vector_view<NodeID>(
|
|
||||||
maneuver_override_node_sequences_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::MANEUVER_OVERRIDE_NODE_SEQUENCES]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
|
||||||
char *memory_block,
|
|
||||||
const std::size_t exclude_index)
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeChecksumPointer(data_layout, memory_block);
|
// TODO: For multi-metric support we need to have separate exclude classes per metric
|
||||||
InitializeNodeInformationPointers(data_layout, memory_block);
|
(void)metric_name;
|
||||||
InitializeEdgeBasedNodeDataInformationPointers(data_layout, memory_block);
|
|
||||||
InitializeEdgeInformationPointers(data_layout, memory_block);
|
m_profile_properties =
|
||||||
InitializeTurnPenalties(data_layout, memory_block);
|
index.GetBlockPtr<extractor::ProfileProperties>("/common/properties");
|
||||||
InitializeGeometryPointers(data_layout, memory_block);
|
|
||||||
InitializeTimestampPointer(data_layout, memory_block);
|
exclude_mask = m_profile_properties->excludable_classes[exclude_index];
|
||||||
InitializeNamePointers(data_layout, memory_block);
|
|
||||||
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
|
m_check_sum = *index.GetBlockPtr<std::uint32_t>("/common/connectivity_checksum");
|
||||||
InitializeProfilePropertiesPointer(data_layout, memory_block, exclude_index);
|
|
||||||
InitializeRTreePointers(data_layout, memory_block);
|
std::tie(m_coordinate_list, m_osmnodeid_list) =
|
||||||
InitializeIntersectionClassPointers(data_layout, memory_block);
|
make_nbn_data_view(index, "/common/nbn_data");
|
||||||
InitializeManeuverOverridePointers(data_layout, memory_block);
|
|
||||||
|
m_static_rtree = make_search_tree_view(index, "/common/rtree");
|
||||||
|
m_geospatial_query.reset(
|
||||||
|
new SharedGeospatialQuery(m_static_rtree, m_coordinate_list, *this));
|
||||||
|
|
||||||
|
edge_based_node_data = make_ebn_data_view(index, "/common/ebg_node_data");
|
||||||
|
|
||||||
|
turn_data = make_turn_data_view(index, "/common/turn_data");
|
||||||
|
|
||||||
|
m_name_table = make_name_table_view(index, "/common/names");
|
||||||
|
|
||||||
|
std::tie(m_lane_description_offsets, m_lane_description_masks) =
|
||||||
|
make_turn_lane_description_views(index, "/common/turn_lanes");
|
||||||
|
m_lane_tupel_id_pairs = make_lane_data_view(index, "/common/turn_lanes");
|
||||||
|
|
||||||
|
m_turn_weight_penalties = make_turn_weight_view(index, "/common/turn_penalty");
|
||||||
|
m_turn_duration_penalties = make_turn_duration_view(index, "/common/turn_penalty");
|
||||||
|
|
||||||
|
segment_data = make_segment_data_view(index, "/common/segment_data");
|
||||||
|
|
||||||
|
m_datasources = index.GetBlockPtr<extractor::Datasources>("/common/data_sources_names");
|
||||||
|
|
||||||
|
intersection_bearings_view =
|
||||||
|
make_intersection_bearings_view(index, "/common/intersection_bearings");
|
||||||
|
|
||||||
|
m_entry_class_table = make_entry_classes_view(index, "/common/entry_classes");
|
||||||
|
|
||||||
|
std::tie(m_maneuver_overrides, m_maneuver_override_node_sequences) =
|
||||||
|
make_maneuver_overrides_views(index, "/common/maneuver_overrides");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// allows switching between process_memory/shared_memory datafacade, based on the type of
|
// allows switching between process_memory/shared_memory datafacade, based on the type of
|
||||||
// allocator
|
// allocator
|
||||||
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_,
|
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_,
|
||||||
|
const std::string &metric_name,
|
||||||
const std::size_t exclude_index)
|
const std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
InitializeInternalPointers(allocator->GetIndex(), metric_name, exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// node and edge information access
|
// node and edge information access
|
||||||
@@ -558,72 +238,57 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
return m_osmnodeid_list[id];
|
return m_osmnodeid_list[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
|
NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const override final
|
||||||
{
|
{
|
||||||
|
return segment_data.GetForwardGeometry(id);
|
||||||
auto range = segment_data.GetForwardGeometry(id);
|
|
||||||
return std::vector<NodeID>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const override final
|
NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const override final
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetReverseGeometry(id);
|
return segment_data.GetReverseGeometry(id);
|
||||||
return std::vector<NodeID>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const override final
|
||||||
GetUncompressedForwardDurations(const EdgeID id) const override final
|
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetForwardDurations(id);
|
return segment_data.GetForwardDurations(id);
|
||||||
return std::vector<EdgeWeight>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const override final
|
||||||
GetUncompressedReverseDurations(const EdgeID id) const override final
|
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetReverseDurations(id);
|
return segment_data.GetReverseDurations(id);
|
||||||
return std::vector<EdgeWeight>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const override final
|
||||||
GetUncompressedForwardWeights(const EdgeID id) const override final
|
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetForwardWeights(id);
|
return segment_data.GetForwardWeights(id);
|
||||||
return std::vector<EdgeWeight>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const override final
|
||||||
GetUncompressedReverseWeights(const EdgeID id) const override final
|
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetReverseWeights(id);
|
return segment_data.GetReverseWeights(id);
|
||||||
return std::vector<EdgeWeight>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the data source ids that were used to supply the edge
|
// Returns the data source ids that were used to supply the edge
|
||||||
// weights.
|
// weights.
|
||||||
virtual std::vector<DatasourceID>
|
DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const override final
|
||||||
GetUncompressedForwardDatasources(const EdgeID id) const override final
|
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetForwardDatasources(id);
|
return segment_data.GetForwardDatasources(id);
|
||||||
return std::vector<DatasourceID>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the data source ids that were used to supply the edge
|
// Returns the data source ids that were used to supply the edge
|
||||||
// weights.
|
// weights.
|
||||||
virtual std::vector<DatasourceID>
|
DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const override final
|
||||||
GetUncompressedReverseDatasources(const EdgeID id) const override final
|
|
||||||
{
|
{
|
||||||
auto range = segment_data.GetReverseDatasources(id);
|
return segment_data.GetReverseDatasources(id);
|
||||||
return std::vector<DatasourceID>{range.begin(), range.end()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
|
TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
|
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
|
||||||
return m_turn_weight_penalties[id];
|
return m_turn_weight_penalties[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const override final
|
TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_turn_duration_penalties.size() > id);
|
BOOST_ASSERT(m_turn_duration_penalties.size() > id);
|
||||||
return m_turn_duration_penalties[id];
|
return m_turn_duration_penalties[id];
|
||||||
@@ -763,7 +428,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
input_coordinate, bearing, bearing_range, approach);
|
input_coordinate, bearing, bearing_range, approach);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetCheckSum() const override final { return m_check_sum; }
|
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
||||||
|
|
||||||
GeometryID GetGeometryIndex(const NodeID id) const override final
|
GeometryID GetGeometryIndex(const NodeID id) const override final
|
||||||
{
|
{
|
||||||
@@ -836,8 +501,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
return m_datasources->GetSourceName(id);
|
return m_datasources->GetSourceName(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetTimestamp() const override final { return m_timestamp; }
|
|
||||||
|
|
||||||
bool GetContinueStraightDefault() const override final
|
bool GetContinueStraightDefault() const override final
|
||||||
{
|
{
|
||||||
return m_profile_properties->continue_straight_at_waypoint;
|
return m_profile_properties->continue_straight_at_waypoint;
|
||||||
@@ -954,10 +617,10 @@ class ContiguousInternalMemoryDataFacade<CH>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
||||||
|
const std::string &metric_name,
|
||||||
const std::size_t exclude_index)
|
const std::size_t exclude_index)
|
||||||
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
|
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, exclude_index)
|
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, metric_name, exclude_index)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -974,122 +637,15 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
|
|
||||||
QueryGraph query_graph;
|
QueryGraph query_graph;
|
||||||
|
|
||||||
void InitializeInternalPointers(storage::DataLayout &data_layout,
|
void InitializeInternalPointers(const storage::SharedDataIndex &index,
|
||||||
char *memory_block,
|
const std::string &metric_name,
|
||||||
const std::size_t exclude_index)
|
const std::size_t exclude_index)
|
||||||
{
|
{
|
||||||
InitializeMLDDataPointers(data_layout, memory_block, exclude_index);
|
mld_partition = make_partition_view(index, "/mld/multilevelpartition");
|
||||||
InitializeGraphPointer(data_layout, memory_block);
|
mld_cell_metric =
|
||||||
}
|
make_filtered_cell_metric_view(index, "/mld/metrics/" + metric_name, exclude_index);
|
||||||
|
mld_cell_storage = make_cell_storage_view(index, "/mld/cellstorage");
|
||||||
void InitializeMLDDataPointers(storage::DataLayout &data_layout,
|
query_graph = make_multi_level_graph_view(index, "/mld/multilevelgraph");
|
||||||
char *memory_block,
|
|
||||||
const std::size_t exclude_index)
|
|
||||||
{
|
|
||||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0);
|
|
||||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
|
|
||||||
|
|
||||||
auto level_data =
|
|
||||||
data_layout.GetBlockPtr<partitioner::MultiLevelPartitionView::LevelData>(
|
|
||||||
memory_block, storage::DataLayout::MLD_LEVEL_DATA);
|
|
||||||
|
|
||||||
auto mld_partition_ptr = data_layout.GetBlockPtr<PartitionID>(
|
|
||||||
memory_block, storage::DataLayout::MLD_PARTITION);
|
|
||||||
auto partition_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION);
|
|
||||||
util::vector_view<PartitionID> partition(mld_partition_ptr, partition_entries_count);
|
|
||||||
|
|
||||||
auto mld_chilren_ptr = data_layout.GetBlockPtr<CellID>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
|
||||||
auto children_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
|
||||||
util::vector_view<CellID> cell_to_children(mld_chilren_ptr, children_entries_count);
|
|
||||||
|
|
||||||
mld_partition =
|
|
||||||
partitioner::MultiLevelPartitionView{level_data, partition, cell_to_children};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto weights_block_id = static_cast<storage::DataLayout::BlockID>(
|
|
||||||
storage::DataLayout::MLD_CELL_WEIGHTS_0 + exclude_index);
|
|
||||||
const auto durations_block_id = static_cast<storage::DataLayout::BlockID>(
|
|
||||||
storage::DataLayout::MLD_CELL_DURATIONS_0 + exclude_index);
|
|
||||||
|
|
||||||
if (data_layout.GetBlockSize(weights_block_id) > 0)
|
|
||||||
{
|
|
||||||
auto mld_cell_weights_ptr =
|
|
||||||
data_layout.GetBlockPtr<EdgeWeight>(memory_block, weights_block_id);
|
|
||||||
auto mld_cell_durations_ptr =
|
|
||||||
data_layout.GetBlockPtr<EdgeDuration>(memory_block, durations_block_id);
|
|
||||||
auto weight_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS_0);
|
|
||||||
auto duration_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS_0);
|
|
||||||
BOOST_ASSERT(weight_entries_count == duration_entries_count);
|
|
||||||
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
|
|
||||||
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
|
|
||||||
duration_entries_count);
|
|
||||||
|
|
||||||
mld_cell_metric = customizer::CellMetricView{std::move(weights), std::move(durations)};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
auto mld_source_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
|
|
||||||
auto mld_destination_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELL_DESTINATION_BOUNDARY);
|
|
||||||
auto mld_cells_ptr = data_layout.GetBlockPtr<partitioner::CellStorageView::CellData>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELLS);
|
|
||||||
auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr<std::uint64_t>(
|
|
||||||
memory_block, storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
|
||||||
|
|
||||||
auto source_boundary_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
|
|
||||||
auto destination_boundary_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DESTINATION_BOUNDARY);
|
|
||||||
auto cells_entries_counts = data_layout.GetBlockEntries(storage::DataLayout::MLD_CELLS);
|
|
||||||
auto cell_level_offsets_entries_count =
|
|
||||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
|
||||||
|
|
||||||
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
|
|
||||||
source_boundary_entries_count);
|
|
||||||
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
|
|
||||||
destination_boundary_entries_count);
|
|
||||||
util::vector_view<partitioner::CellStorageView::CellData> cells(mld_cells_ptr,
|
|
||||||
cells_entries_counts);
|
|
||||||
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
|
|
||||||
cell_level_offsets_entries_count);
|
|
||||||
|
|
||||||
mld_cell_storage = partitioner::CellStorageView{std::move(source_boundary),
|
|
||||||
std::move(destination_boundary),
|
|
||||||
std::move(cells),
|
|
||||||
std::move(level_offsets)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block)
|
|
||||||
{
|
|
||||||
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
|
|
||||||
memory_block, storage::DataLayout::MLD_GRAPH_NODE_LIST);
|
|
||||||
|
|
||||||
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
|
|
||||||
memory_block, storage::DataLayout::MLD_GRAPH_EDGE_LIST);
|
|
||||||
|
|
||||||
auto graph_node_to_offset_ptr = data_layout.GetBlockPtr<QueryGraph::EdgeOffset>(
|
|
||||||
memory_block, storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET);
|
|
||||||
|
|
||||||
util::vector_view<GraphNode> node_list(
|
|
||||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]);
|
|
||||||
util::vector_view<GraphEdge> edge_list(
|
|
||||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]);
|
|
||||||
util::vector_view<QueryGraph::EdgeOffset> node_to_offset(
|
|
||||||
graph_node_to_offset_ptr,
|
|
||||||
data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]);
|
|
||||||
|
|
||||||
query_graph =
|
|
||||||
QueryGraph(std::move(node_list), std::move(edge_list), std::move(node_to_offset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocator that keeps the allocation data
|
// allocator that keeps the allocation data
|
||||||
@@ -1097,10 +653,12 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade(
|
ContiguousInternalMemoryAlgorithmDataFacade(
|
||||||
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
|
std::shared_ptr<ContiguousBlockAllocator> allocator_,
|
||||||
|
const std::string &metric_name,
|
||||||
|
const std::size_t exclude_index)
|
||||||
: allocator(std::move(allocator_))
|
: allocator(std::move(allocator_))
|
||||||
{
|
{
|
||||||
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
|
InitializeInternalPointers(allocator->GetIndex(), metric_name, exclude_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const override
|
const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const override
|
||||||
@@ -1115,6 +673,8 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
// search graph access
|
// search graph access
|
||||||
unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); }
|
unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); }
|
||||||
|
|
||||||
|
unsigned GetMaxBorderNodeID() const override final { return query_graph.GetMaxBorderNodeID(); }
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); }
|
unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); }
|
||||||
|
|
||||||
unsigned GetOutDegree(const NodeID n) const override final
|
unsigned GetOutDegree(const NodeID n) const override final
|
||||||
@@ -1122,6 +682,31 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
return query_graph.GetOutDegree(n);
|
return query_graph.GetOutDegree(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
||||||
|
{
|
||||||
|
return query_graph.GetAdjacentEdgeRange(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeWeight GetNodeWeight(const NodeID node) const override final
|
||||||
|
{
|
||||||
|
return query_graph.GetNodeWeight(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeDuration GetNodeDuration(const NodeID node) const override final
|
||||||
|
{
|
||||||
|
return query_graph.GetNodeDuration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsForwardEdge(const NodeID node) const override final
|
||||||
|
{
|
||||||
|
return query_graph.IsForwardEdge(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsBackwardEdge(const NodeID node) const override final
|
||||||
|
{
|
||||||
|
return query_graph.IsBackwardEdge(node);
|
||||||
|
}
|
||||||
|
|
||||||
NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); }
|
NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); }
|
||||||
|
|
||||||
const EdgeData &GetEdgeData(const EdgeID e) const override final
|
const EdgeData &GetEdgeData(const EdgeID e) const override final
|
||||||
@@ -1129,11 +714,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
|
|||||||
return query_graph.GetEdgeData(e);
|
return query_graph.GetEdgeData(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
|
||||||
{
|
|
||||||
return query_graph.GetAdjacentEdgeRange(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final
|
EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final
|
||||||
{
|
{
|
||||||
return query_graph.GetBorderEdgeRange(level, node);
|
return query_graph.GetBorderEdgeRange(level, node);
|
||||||
@@ -1154,10 +734,10 @@ class ContiguousInternalMemoryDataFacade<MLD> final
|
|||||||
private:
|
private:
|
||||||
public:
|
public:
|
||||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
|
||||||
|
const std::string &metric_name,
|
||||||
const std::size_t exclude_index)
|
const std::size_t exclude_index)
|
||||||
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
|
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
|
||||||
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, exclude_index)
|
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, metric_name, exclude_index)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,10 +10,9 @@
|
|||||||
|
|
||||||
#include "extractor/class_data.hpp"
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/edge_based_node_segment.hpp"
|
#include "extractor/edge_based_node_segment.hpp"
|
||||||
//#include "extractor/guidance/turn_lane_types.hpp"
|
|
||||||
#include "extractor/maneuver_override.hpp"
|
#include "extractor/maneuver_override.hpp"
|
||||||
//#include "extractor/original_edge_data.hpp"
|
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
|
#include "extractor/segment_data_container.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "extractor/turn_lane_types.hpp"
|
#include "extractor/turn_lane_types.hpp"
|
||||||
|
|
||||||
@@ -25,12 +24,15 @@
|
|||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
|
#include "util/packed_vector.hpp"
|
||||||
#include "util/string_util.hpp"
|
#include "util/string_util.hpp"
|
||||||
#include "util/string_view.hpp"
|
#include "util/string_view.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include "osrm/coordinate.hpp"
|
#include "osrm/coordinate.hpp"
|
||||||
|
|
||||||
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
|
#include <boost/range/any_range.hpp>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -50,10 +52,27 @@ class BaseDataFacade
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using RTreeLeaf = extractor::EdgeBasedNodeSegment;
|
using RTreeLeaf = extractor::EdgeBasedNodeSegment;
|
||||||
|
|
||||||
|
using NodeForwardRange =
|
||||||
|
boost::iterator_range<extractor::SegmentDataView::SegmentNodeVector::const_iterator>;
|
||||||
|
using NodeReverseRange = boost::reversed_range<const NodeForwardRange>;
|
||||||
|
|
||||||
|
using WeightForwardRange =
|
||||||
|
boost::iterator_range<extractor::SegmentDataView::SegmentWeightVector::const_iterator>;
|
||||||
|
using WeightReverseRange = boost::reversed_range<const WeightForwardRange>;
|
||||||
|
|
||||||
|
using DurationForwardRange =
|
||||||
|
boost::iterator_range<extractor::SegmentDataView::SegmentDurationVector::const_iterator>;
|
||||||
|
using DurationReverseRange = boost::reversed_range<const DurationForwardRange>;
|
||||||
|
|
||||||
|
using DatasourceForwardRange =
|
||||||
|
boost::iterator_range<extractor::SegmentDataView::SegmentDatasourceVector::const_iterator>;
|
||||||
|
using DatasourceReverseRange = boost::reversed_range<const DatasourceForwardRange>;
|
||||||
|
|
||||||
BaseDataFacade() {}
|
BaseDataFacade() {}
|
||||||
virtual ~BaseDataFacade() {}
|
virtual ~BaseDataFacade() {}
|
||||||
|
|
||||||
virtual unsigned GetCheckSum() const = 0;
|
virtual std::uint32_t GetCheckSum() const = 0;
|
||||||
|
|
||||||
// node and edge information access
|
// node and edge information access
|
||||||
virtual util::Coordinate GetCoordinateOfNode(const NodeID id) const = 0;
|
virtual util::Coordinate GetCoordinateOfNode(const NodeID id) const = 0;
|
||||||
@@ -64,28 +83,27 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual ComponentID GetComponentID(const NodeID id) const = 0;
|
virtual ComponentID GetComponentID(const NodeID id) const = 0;
|
||||||
|
|
||||||
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const = 0;
|
virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0;
|
||||||
|
virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0;
|
||||||
|
|
||||||
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const = 0;
|
virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const = 0;
|
||||||
|
|
||||||
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const = 0;
|
virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const = 0;
|
||||||
|
|
||||||
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const = 0;
|
|
||||||
|
|
||||||
// Gets the weight values for each segment in an uncompressed geometry.
|
// Gets the weight values for each segment in an uncompressed geometry.
|
||||||
// Should always be 1 shorter than GetUncompressedGeometry
|
// Should always be 1 shorter than GetUncompressedGeometry
|
||||||
virtual std::vector<EdgeWeight> GetUncompressedForwardWeights(const EdgeID id) const = 0;
|
virtual WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const = 0;
|
||||||
virtual std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID id) const = 0;
|
virtual WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const = 0;
|
||||||
|
|
||||||
// Gets the duration values for each segment in an uncompressed geometry.
|
// Gets the duration values for each segment in an uncompressed geometry.
|
||||||
// Should always be 1 shorter than GetUncompressedGeometry
|
// Should always be 1 shorter than GetUncompressedGeometry
|
||||||
virtual std::vector<EdgeWeight> GetUncompressedForwardDurations(const EdgeID id) const = 0;
|
virtual DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const = 0;
|
||||||
virtual std::vector<EdgeWeight> GetUncompressedReverseDurations(const EdgeID id) const = 0;
|
virtual DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const = 0;
|
||||||
|
|
||||||
// Returns the data source ids that were used to supply the edge
|
// Returns the data source ids that were used to supply the edge
|
||||||
// weights. Will return an empty array when only the base profile is used.
|
// weights. Will return an empty array when only the base profile is used.
|
||||||
virtual std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID id) const = 0;
|
virtual DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const = 0;
|
||||||
virtual std::vector<DatasourceID> GetUncompressedReverseDatasources(const EdgeID id) const = 0;
|
virtual DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const = 0;
|
||||||
|
|
||||||
// Gets the name of a datasource
|
// Gets the name of a datasource
|
||||||
virtual StringView GetDatasourceName(const DatasourceID id) const = 0;
|
virtual StringView GetDatasourceName(const DatasourceID id) const = 0;
|
||||||
@@ -173,8 +191,6 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual StringView GetExitsForID(const NameID id) const = 0;
|
virtual StringView GetExitsForID(const NameID id) const = 0;
|
||||||
|
|
||||||
virtual std::string GetTimestamp() const = 0;
|
|
||||||
|
|
||||||
virtual bool GetContinueStraightDefault() const = 0;
|
virtual bool GetContinueStraightDefault() const = 0;
|
||||||
|
|
||||||
virtual double GetMapMatchingMaxSpeed() const = 0;
|
virtual double GetMapMatchingMaxSpeed() const = 0;
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef OSRM_ENGINE_DATAFACADE_MMAP_MEMORY_ALLOCATOR_HPP_
|
||||||
|
#define OSRM_ENGINE_DATAFACADE_MMAP_MEMORY_ALLOCATOR_HPP_
|
||||||
|
|
||||||
|
#include "engine/datafacade/contiguous_block_allocator.hpp"
|
||||||
|
|
||||||
|
#include "storage/storage_config.hpp"
|
||||||
|
|
||||||
|
#include "util/vector_view.hpp"
|
||||||
|
|
||||||
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace engine
|
||||||
|
{
|
||||||
|
namespace datafacade
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This allocator uses file backed mmap memory block as the data location.
|
||||||
|
*/
|
||||||
|
class MMapMemoryAllocator : public ContiguousBlockAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MMapMemoryAllocator(const storage::StorageConfig &config,
|
||||||
|
const boost::filesystem::path &memory_file);
|
||||||
|
~MMapMemoryAllocator() override final;
|
||||||
|
|
||||||
|
// interface to give access to the datafacades
|
||||||
|
const storage::SharedDataIndex &GetIndex() override final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
storage::SharedDataIndex index;
|
||||||
|
util::vector_view<char> mapped_memory;
|
||||||
|
boost::iostreams::mapped_file mapped_memory_file;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace datafacade
|
||||||
|
} // namespace engine
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif // OSRM_ENGINE_DATAFACADE_SHARED_MEMORY_ALLOCATOR_HPP_
|
||||||
@@ -27,12 +27,11 @@ class ProcessMemoryAllocator : public ContiguousBlockAllocator
|
|||||||
~ProcessMemoryAllocator() override final;
|
~ProcessMemoryAllocator() override final;
|
||||||
|
|
||||||
// interface to give access to the datafacades
|
// interface to give access to the datafacades
|
||||||
storage::DataLayout &GetLayout() override final;
|
const storage::SharedDataIndex &GetIndex() override final;
|
||||||
char *GetMemory() override final;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
storage::SharedDataIndex index;
|
||||||
std::unique_ptr<char[]> internal_memory;
|
std::unique_ptr<char[]> internal_memory;
|
||||||
std::unique_ptr<storage::DataLayout> internal_layout;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace datafacade
|
} // namespace datafacade
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "engine/datafacade/contiguous_block_allocator.hpp"
|
#include "engine/datafacade/contiguous_block_allocator.hpp"
|
||||||
|
|
||||||
#include "storage/shared_datatype.hpp"
|
#include "storage/shared_data_index.hpp"
|
||||||
#include "storage/shared_memory.hpp"
|
#include "storage/shared_memory.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -23,15 +23,16 @@ namespace datafacade
|
|||||||
class SharedMemoryAllocator : public ContiguousBlockAllocator
|
class SharedMemoryAllocator : public ContiguousBlockAllocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SharedMemoryAllocator(storage::SharedDataType data_region);
|
explicit SharedMemoryAllocator(
|
||||||
|
const std::vector<storage::SharedRegionRegister::ShmKey> &shm_keys);
|
||||||
~SharedMemoryAllocator() override final;
|
~SharedMemoryAllocator() override final;
|
||||||
|
|
||||||
// interface to give access to the datafacades
|
// interface to give access to the datafacades
|
||||||
storage::DataLayout &GetLayout() override final;
|
const storage::SharedDataIndex &GetIndex() override final;
|
||||||
char *GetMemory() override final;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<storage::SharedMemory> m_large_memory;
|
storage::SharedDataIndex index;
|
||||||
|
std::vector<std::unique_ptr<storage::SharedMemory>> memory_regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace datafacade
|
} // namespace datafacade
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
|
|||||||
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator)
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator)
|
||||||
: DataFacadeFactory(allocator, has_exclude_flags)
|
: DataFacadeFactory(allocator, has_exclude_flags)
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT_MSG(facades.size() >= 1, "At least one datafacade is needed");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ParameterT> std::shared_ptr<const Facade> Get(const ParameterT ¶ms) const
|
template <typename ParameterT> std::shared_ptr<const Facade> Get(const ParameterT ¶ms) const
|
||||||
@@ -45,13 +46,33 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
|
|||||||
template <typename AllocatorT>
|
template <typename AllocatorT>
|
||||||
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::true_type)
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::true_type)
|
||||||
{
|
{
|
||||||
for (const auto index : util::irange<std::size_t>(0, facades.size()))
|
const auto &index = allocator->GetIndex();
|
||||||
|
properties = index.template GetBlockPtr<extractor::ProfileProperties>("/common/properties");
|
||||||
|
const auto &metric_name = properties->GetWeightName();
|
||||||
|
|
||||||
|
std::vector<std::string> exclude_prefixes;
|
||||||
|
auto exclude_path = std::string("/") + routing_algorithms::identifier<AlgorithmT>() +
|
||||||
|
std::string("/metrics/") + metric_name + "/exclude/";
|
||||||
|
index.List(exclude_path, std::back_inserter(exclude_prefixes));
|
||||||
|
facades.resize(exclude_prefixes.size());
|
||||||
|
|
||||||
|
if (facades.empty())
|
||||||
{
|
{
|
||||||
facades[index] = std::make_shared<const Facade>(allocator, index);
|
throw util::exception(std::string("Could not find any metrics for ") +
|
||||||
|
routing_algorithms::name<AlgorithmT>() +
|
||||||
|
" in the data. Did you load the right dataset?");
|
||||||
}
|
}
|
||||||
|
|
||||||
properties = allocator->GetLayout().template GetBlockPtr<extractor::ProfileProperties>(
|
for (const auto &exclude_prefix : exclude_prefixes)
|
||||||
allocator->GetMemory(), storage::DataLayout::PROPERTIES);
|
{
|
||||||
|
auto index_begin = exclude_prefix.find_last_of("/");
|
||||||
|
BOOST_ASSERT_MSG(index_begin != std::string::npos,
|
||||||
|
"The exclude prefix needs to be a valid data path.");
|
||||||
|
std::size_t index =
|
||||||
|
std::stoi(exclude_prefix.substr(index_begin + 1, exclude_prefix.size()));
|
||||||
|
BOOST_ASSERT(index >= 0 && index < facades.size());
|
||||||
|
facades[index] = std::make_shared<const Facade>(allocator, metric_name, index);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto index : util::irange<std::size_t>(0, properties->class_names.size()))
|
for (const auto index : util::irange<std::size_t>(0, properties->class_names.size()))
|
||||||
{
|
{
|
||||||
@@ -67,7 +88,10 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
|
|||||||
template <typename AllocatorT>
|
template <typename AllocatorT>
|
||||||
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::false_type)
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::false_type)
|
||||||
{
|
{
|
||||||
facades[0] = std::make_shared<const Facade>(allocator, 0);
|
const auto &index = allocator->GetIndex();
|
||||||
|
properties = index.template GetBlockPtr<extractor::ProfileProperties>("/common/properties");
|
||||||
|
const auto &metric_name = properties->GetWeightName();
|
||||||
|
facades.push_back(std::make_shared<const Facade>(allocator, metric_name, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::false_type) const
|
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::false_type) const
|
||||||
@@ -124,7 +148,7 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::shared_ptr<const Facade>, extractor::MAX_EXCLUDABLE_CLASSES> facades;
|
std::vector<std::shared_ptr<const Facade>> facades;
|
||||||
std::unordered_map<std::string, extractor::ClassData> name_to_class;
|
std::unordered_map<std::string, extractor::ClassData> name_to_class;
|
||||||
const extractor::ProfileProperties *properties = nullptr;
|
const extractor::ProfileProperties *properties = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "engine/data_watchdog.hpp"
|
#include "engine/data_watchdog.hpp"
|
||||||
#include "engine/datafacade.hpp"
|
#include "engine/datafacade.hpp"
|
||||||
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
|
||||||
|
#include "engine/datafacade/mmap_memory_allocator.hpp"
|
||||||
#include "engine/datafacade/process_memory_allocator.hpp"
|
#include "engine/datafacade/process_memory_allocator.hpp"
|
||||||
#include "engine/datafacade_factory.hpp"
|
#include "engine/datafacade_factory.hpp"
|
||||||
|
|
||||||
@@ -25,6 +26,31 @@ template <typename AlgorithmT, template <typename A> class FacadeT> class DataFa
|
|||||||
virtual std::shared_ptr<const Facade> Get(const api::TileParameters &) const = 0;
|
virtual std::shared_ptr<const Facade> Get(const api::TileParameters &) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename AlgorithmT, template <typename A> class FacadeT>
|
||||||
|
class ExternalProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
||||||
|
|
||||||
|
ExternalProvider(const storage::StorageConfig &config,
|
||||||
|
const boost::filesystem::path &memory_file)
|
||||||
|
: facade_factory(std::make_shared<datafacade::MMapMemoryAllocator>(config, memory_file))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const override final
|
||||||
|
{
|
||||||
|
return facade_factory.Get(params);
|
||||||
|
}
|
||||||
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms) const override final
|
||||||
|
{
|
||||||
|
return facade_factory.Get(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DataFacadeFactory<FacadeT, AlgorithmT> facade_factory;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename AlgorithmT, template <typename A> class FacadeT>
|
template <typename AlgorithmT, template <typename A> class FacadeT>
|
||||||
class ImmutableProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
|
class ImmutableProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
|
||||||
{
|
{
|
||||||
@@ -57,6 +83,8 @@ class WatchingProvider : public DataFacadeProvider<AlgorithmT, FacadeT>
|
|||||||
public:
|
public:
|
||||||
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
|
||||||
|
|
||||||
|
WatchingProvider(const std::string &dataset_name) : watchdog(dataset_name) {}
|
||||||
|
|
||||||
std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const override final
|
std::shared_ptr<const Facade> Get(const api::TileParameters ¶ms) const override final
|
||||||
{
|
{
|
||||||
return watchdog.Get(params);
|
return watchdog.Get(params);
|
||||||
@@ -74,6 +102,8 @@ template <typename AlgorithmT>
|
|||||||
using WatchingProvider = detail::WatchingProvider<AlgorithmT, DataFacade>;
|
using WatchingProvider = detail::WatchingProvider<AlgorithmT, DataFacade>;
|
||||||
template <typename AlgorithmT>
|
template <typename AlgorithmT>
|
||||||
using ImmutableProvider = detail::ImmutableProvider<AlgorithmT, DataFacade>;
|
using ImmutableProvider = detail::ImmutableProvider<AlgorithmT, DataFacade>;
|
||||||
|
template <typename AlgorithmT>
|
||||||
|
using ExternalProvider = detail::ExternalProvider<AlgorithmT, DataFacade>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-78
@@ -7,8 +7,6 @@
|
|||||||
#include "engine/api/table_parameters.hpp"
|
#include "engine/api/table_parameters.hpp"
|
||||||
#include "engine/api/tile_parameters.hpp"
|
#include "engine/api/tile_parameters.hpp"
|
||||||
#include "engine/api/trip_parameters.hpp"
|
#include "engine/api/trip_parameters.hpp"
|
||||||
#include "engine/data_watchdog.hpp"
|
|
||||||
#include "engine/datafacade/contiguous_block_allocator.hpp"
|
|
||||||
#include "engine/datafacade_provider.hpp"
|
#include "engine/datafacade_provider.hpp"
|
||||||
#include "engine/engine_config.hpp"
|
#include "engine/engine_config.hpp"
|
||||||
#include "engine/plugins/match.hpp"
|
#include "engine/plugins/match.hpp"
|
||||||
@@ -19,9 +17,7 @@
|
|||||||
#include "engine/plugins/viaroute.hpp"
|
#include "engine/plugins/viaroute.hpp"
|
||||||
#include "engine/routing_algorithms.hpp"
|
#include "engine/routing_algorithms.hpp"
|
||||||
#include "engine/status.hpp"
|
#include "engine/status.hpp"
|
||||||
#include "util/exception.hpp"
|
|
||||||
#include "util/exception_utils.hpp"
|
|
||||||
#include "util/fingerprint.hpp"
|
|
||||||
#include "util/json_container.hpp"
|
#include "util/json_container.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -63,9 +59,16 @@ template <typename Algorithm> class Engine final : public EngineInterface
|
|||||||
{
|
{
|
||||||
if (config.use_shared_memory)
|
if (config.use_shared_memory)
|
||||||
{
|
{
|
||||||
util::Log(logDEBUG) << "Using shared memory with algorithm "
|
util::Log(logDEBUG) << "Using shared memory with name \"" << config.dataset_name
|
||||||
<< routing_algorithms::name<Algorithm>();
|
<< "\" with algorithm " << routing_algorithms::name<Algorithm>();
|
||||||
facade_provider = std::make_unique<WatchingProvider<Algorithm>>();
|
facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name);
|
||||||
|
}
|
||||||
|
else if (!config.memory_file.empty())
|
||||||
|
{
|
||||||
|
util::Log(logDEBUG) << "Using memory mapped filed at " << config.memory_file
|
||||||
|
<< " with algorithm " << routing_algorithms::name<Algorithm>();
|
||||||
|
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config,
|
||||||
|
config.memory_file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -116,8 +119,6 @@ template <typename Algorithm> class Engine final : public EngineInterface
|
|||||||
return tile_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
return tile_plugin.HandleRequest(GetAlgorithms(params), params, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckCompatibility(const EngineConfig &config);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename ParametersT> auto GetAlgorithms(const ParametersT ¶ms) const
|
template <typename ParametersT> auto GetAlgorithms(const ParametersT ¶ms) const
|
||||||
{
|
{
|
||||||
@@ -133,74 +134,6 @@ template <typename Algorithm> class Engine final : public EngineInterface
|
|||||||
const plugins::MatchPlugin match_plugin;
|
const plugins::MatchPlugin match_plugin;
|
||||||
const plugins::TilePlugin tile_plugin;
|
const plugins::TilePlugin tile_plugin;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompatibility(const EngineConfig &config)
|
|
||||||
{
|
|
||||||
if (config.use_shared_memory)
|
|
||||||
{
|
|
||||||
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
|
|
||||||
using mutex_type = typename decltype(barrier)::mutex_type;
|
|
||||||
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
|
||||||
|
|
||||||
auto mem = storage::makeSharedMemory(barrier.data().region);
|
|
||||||
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
|
|
||||||
return layout->GetBlockSize(storage::DataLayout::CH_GRAPH_NODE_LIST) > 4 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::CH_GRAPH_EDGE_LIST) > 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.hsgr")))
|
|
||||||
return false;
|
|
||||||
storage::io::FileReader in(config.storage_config.GetPath(".osrm.hsgr"),
|
|
||||||
storage::io::FileReader::VerifyFingerprint);
|
|
||||||
|
|
||||||
auto size = in.GetSize();
|
|
||||||
return size > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompatibility(const EngineConfig &config)
|
|
||||||
{
|
|
||||||
if (config.use_shared_memory)
|
|
||||||
{
|
|
||||||
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
|
|
||||||
using mutex_type = typename decltype(barrier)::mutex_type;
|
|
||||||
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
|
|
||||||
|
|
||||||
auto mem = storage::makeSharedMemory(barrier.data().region);
|
|
||||||
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
|
|
||||||
// checks that all the needed memory blocks are populated
|
|
||||||
// DataLayout::MLD_CELL_SOURCE_BOUNDARY and DataLayout::MLD_CELL_DESTINATION_BOUNDARY
|
|
||||||
// are not checked, because in situations where there are so few nodes in the graph that
|
|
||||||
// they all fit into one cell, they can be empty.
|
|
||||||
bool empty_data = layout->GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_CELLS) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_NODE_LIST) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_EDGE_LIST) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_CELL_WEIGHTS_0) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_CELL_DURATIONS_0) > 0 &&
|
|
||||||
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET) > 0;
|
|
||||||
return empty_data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.partition")) ||
|
|
||||||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.cells")) ||
|
|
||||||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.mldgr")) ||
|
|
||||||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.cell_metrics")))
|
|
||||||
return false;
|
|
||||||
storage::io::FileReader in(config.storage_config.GetPath(".osrm.partition"),
|
|
||||||
storage::io::FileReader::VerifyFingerprint);
|
|
||||||
|
|
||||||
auto size = in.GetSize();
|
|
||||||
return size > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,8 +88,10 @@ struct EngineConfig final
|
|||||||
int max_results_nearest = -1;
|
int max_results_nearest = -1;
|
||||||
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
|
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
|
||||||
bool use_shared_memory = true;
|
bool use_shared_memory = true;
|
||||||
|
boost::filesystem::path memory_file;
|
||||||
Algorithm algorithm = Algorithm::CH;
|
Algorithm algorithm = Algorithm::CH;
|
||||||
std::string verbosity;
|
std::string verbosity;
|
||||||
|
std::string dataset_name;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -434,11 +435,6 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
// Find the node-based-edge that this belongs to, and directly
|
// Find the node-based-edge that this belongs to, and directly
|
||||||
// calculate the forward_weight, forward_offset, reverse_weight, reverse_offset
|
// calculate the forward_weight, forward_offset, reverse_weight, reverse_offset
|
||||||
|
|
||||||
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.forward_segment_id.enabled || data.reverse_segment_id.enabled);
|
||||||
BOOST_ASSERT(!data.reverse_segment_id.enabled ||
|
BOOST_ASSERT(!data.reverse_segment_id.enabled ||
|
||||||
datafacade.GetGeometryIndex(data.forward_segment_id.id).id ==
|
datafacade.GetGeometryIndex(data.forward_segment_id.id).id ==
|
||||||
@@ -446,35 +442,70 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_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);
|
const auto component_id = datafacade.GetComponentID(data.forward_segment_id.id);
|
||||||
|
|
||||||
const std::vector<EdgeWeight> forward_weight_vector =
|
const auto forward_weights = datafacade.GetUncompressedForwardWeights(geometry_id);
|
||||||
datafacade.GetUncompressedForwardWeights(geometry_id);
|
const auto reverse_weights = datafacade.GetUncompressedReverseWeights(geometry_id);
|
||||||
const std::vector<EdgeWeight> reverse_weight_vector =
|
|
||||||
datafacade.GetUncompressedReverseWeights(geometry_id);
|
|
||||||
const std::vector<EdgeWeight> forward_duration_vector =
|
|
||||||
datafacade.GetUncompressedForwardDurations(geometry_id);
|
|
||||||
const std::vector<EdgeWeight> reverse_duration_vector =
|
|
||||||
datafacade.GetUncompressedReverseDurations(geometry_id);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
|
const auto forward_durations = datafacade.GetUncompressedForwardDurations(geometry_id);
|
||||||
|
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
|
||||||
|
|
||||||
|
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
|
||||||
|
|
||||||
|
const auto forward_weight_offset =
|
||||||
|
std::accumulate(forward_weights.begin(),
|
||||||
|
forward_weights.begin() + data.fwd_segment_position,
|
||||||
|
EdgeWeight{0});
|
||||||
|
|
||||||
|
const auto forward_duration_offset =
|
||||||
|
std::accumulate(forward_durations.begin(),
|
||||||
|
forward_durations.begin() + data.fwd_segment_position,
|
||||||
|
EdgeDuration{0});
|
||||||
|
|
||||||
|
EdgeDistance forward_distance_offset = 0;
|
||||||
|
for (auto current = forward_geometry.begin();
|
||||||
|
current < forward_geometry.begin() + data.fwd_segment_position;
|
||||||
|
++current)
|
||||||
{
|
{
|
||||||
forward_weight_offset += forward_weight_vector[i];
|
forward_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
||||||
forward_duration_offset += forward_duration_vector[i];
|
datafacade.GetCoordinateOfNode(*current),
|
||||||
|
datafacade.GetCoordinateOfNode(*std::next(current)));
|
||||||
}
|
}
|
||||||
forward_weight = forward_weight_vector[data.fwd_segment_position];
|
|
||||||
forward_duration = forward_duration_vector[data.fwd_segment_position];
|
|
||||||
|
|
||||||
BOOST_ASSERT(data.fwd_segment_position < reverse_weight_vector.size());
|
BOOST_ASSERT(data.fwd_segment_position <
|
||||||
|
std::distance(forward_durations.begin(), forward_durations.end()));
|
||||||
|
|
||||||
for (std::size_t i = 0; i < reverse_weight_vector.size() - data.fwd_segment_position - 1;
|
EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
|
||||||
i++)
|
EdgeDuration forward_duration = forward_durations[data.fwd_segment_position];
|
||||||
|
EdgeDistance forward_distance = util::coordinate_calculation::fccApproximateDistance(
|
||||||
|
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
|
||||||
|
point_on_segment);
|
||||||
|
|
||||||
|
const auto reverse_weight_offset =
|
||||||
|
std::accumulate(reverse_weights.begin(),
|
||||||
|
reverse_weights.end() - data.fwd_segment_position - 1,
|
||||||
|
EdgeWeight{0});
|
||||||
|
|
||||||
|
const auto reverse_duration_offset =
|
||||||
|
std::accumulate(reverse_durations.begin(),
|
||||||
|
reverse_durations.end() - data.fwd_segment_position - 1,
|
||||||
|
EdgeDuration{0});
|
||||||
|
|
||||||
|
EdgeDistance reverse_distance_offset = 0;
|
||||||
|
for (auto current = forward_geometry.begin();
|
||||||
|
current < forward_geometry.end() - data.fwd_segment_position - 2;
|
||||||
|
++current)
|
||||||
{
|
{
|
||||||
reverse_weight_offset += reverse_weight_vector[i];
|
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
||||||
reverse_duration_offset += reverse_duration_vector[i];
|
datafacade.GetCoordinateOfNode(*current),
|
||||||
|
datafacade.GetCoordinateOfNode(*std::next(current)));
|
||||||
}
|
}
|
||||||
reverse_weight =
|
|
||||||
reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1];
|
EdgeWeight reverse_weight =
|
||||||
reverse_duration =
|
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
|
||||||
reverse_duration_vector[reverse_duration_vector.size() - data.fwd_segment_position - 1];
|
EdgeDuration reverse_duration =
|
||||||
|
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1];
|
||||||
|
EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance(
|
||||||
|
point_on_segment,
|
||||||
|
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
|
||||||
|
|
||||||
ratio = std::min(1.0, std::max(0.0, ratio));
|
ratio = std::min(1.0, std::max(0.0, ratio));
|
||||||
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
||||||
@@ -493,14 +524,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
|
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
|
||||||
};
|
};
|
||||||
bool is_forward_valid_source =
|
bool is_forward_valid_source =
|
||||||
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
|
areSegmentsValid(forward_weights.begin(), forward_weights.end());
|
||||||
bool is_forward_valid_target =
|
bool is_forward_valid_target = areSegmentsValid(
|
||||||
areSegmentsValid(forward_weight_vector.begin(),
|
forward_weights.begin(), forward_weights.begin() + data.fwd_segment_position + 1);
|
||||||
forward_weight_vector.begin() + data.fwd_segment_position + 1);
|
|
||||||
bool is_reverse_valid_source =
|
bool is_reverse_valid_source =
|
||||||
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
|
areSegmentsValid(reverse_weights.begin(), reverse_weights.end());
|
||||||
bool is_reverse_valid_target = areSegmentsValid(
|
bool is_reverse_valid_target = areSegmentsValid(
|
||||||
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
|
reverse_weights.begin(), reverse_weights.end() - data.fwd_segment_position);
|
||||||
|
|
||||||
auto transformed = PhantomNodeWithDistance{
|
auto transformed = PhantomNodeWithDistance{
|
||||||
PhantomNode{data,
|
PhantomNode{data,
|
||||||
@@ -509,6 +539,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_weight,
|
reverse_weight,
|
||||||
forward_weight_offset,
|
forward_weight_offset,
|
||||||
reverse_weight_offset,
|
reverse_weight_offset,
|
||||||
|
forward_distance,
|
||||||
|
reverse_distance,
|
||||||
|
forward_distance_offset,
|
||||||
|
reverse_distance_offset,
|
||||||
forward_duration,
|
forward_duration,
|
||||||
reverse_duration,
|
reverse_duration,
|
||||||
forward_duration_offset,
|
forward_duration_offset,
|
||||||
@@ -605,17 +639,14 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
|
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
|
||||||
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
|
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
|
||||||
|
|
||||||
const std::vector<EdgeWeight> forward_weight_vector =
|
const auto forward_weights = datafacade.GetUncompressedForwardWeights(geometry_id);
|
||||||
datafacade.GetUncompressedForwardWeights(geometry_id);
|
if (forward_weights[data.fwd_segment_position] != INVALID_SEGMENT_WEIGHT)
|
||||||
|
|
||||||
if (forward_weight_vector[data.fwd_segment_position] != INVALID_SEGMENT_WEIGHT)
|
|
||||||
{
|
{
|
||||||
forward_edge_valid = data.forward_segment_id.enabled;
|
forward_edge_valid = data.forward_segment_id.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<EdgeWeight> reverse_weight_vector =
|
const auto reverse_weights = datafacade.GetUncompressedReverseWeights(geometry_id);
|
||||||
datafacade.GetUncompressedReverseWeights(geometry_id);
|
if (reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1] !=
|
||||||
if (reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1] !=
|
|
||||||
INVALID_SEGMENT_WEIGHT)
|
INVALID_SEGMENT_WEIGHT)
|
||||||
{
|
{
|
||||||
reverse_edge_valid = data.reverse_segment_id.enabled;
|
reverse_edge_valid = data.reverse_segment_id.enabled;
|
||||||
|
|||||||
@@ -55,10 +55,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
const auto source_node_id =
|
const auto source_node_id =
|
||||||
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
|
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
|
||||||
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
|
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
|
||||||
std::vector<NodeID> source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
|
const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
|
||||||
|
|
||||||
geometry.osm_node_ids.push_back(
|
geometry.osm_node_ids.push_back(
|
||||||
facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate]));
|
facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate)));
|
||||||
|
|
||||||
auto cumulative_distance = 0.;
|
auto cumulative_distance = 0.;
|
||||||
auto current_distance = 0.;
|
auto current_distance = 0.;
|
||||||
@@ -111,8 +111,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
const auto target_node_id =
|
const auto target_node_id =
|
||||||
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
|
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
|
||||||
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
|
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
|
||||||
const std::vector<DatasourceID> forward_datasources =
|
const auto forward_datasources = facade.GetUncompressedForwardDatasources(target_geometry_id);
|
||||||
facade.GetUncompressedForwardDatasources(target_geometry_id);
|
|
||||||
|
|
||||||
// This happens when the source/target are on the same edge-based-node
|
// This happens when the source/target are on the same edge-based-node
|
||||||
// There will be no entries in the unpacked path, thus no annotations.
|
// There will be no entries in the unpacked path, thus no annotations.
|
||||||
@@ -136,7 +135,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
LegGeometry::Annotation{current_distance,
|
LegGeometry::Annotation{current_distance,
|
||||||
duration,
|
duration,
|
||||||
weight,
|
weight,
|
||||||
forward_datasources[target_node.fwd_segment_position]});
|
forward_datasources(target_node.fwd_segment_position)});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -145,7 +144,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
|
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
|
||||||
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
|
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
|
||||||
facade.GetWeightMultiplier(),
|
facade.GetWeightMultiplier(),
|
||||||
forward_datasources[target_node.fwd_segment_position]});
|
forward_datasources(target_node.fwd_segment_position)});
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry.segment_offsets.push_back(geometry.locations.size());
|
geometry.segment_offsets.push_back(geometry.locations.size());
|
||||||
@@ -158,10 +157,9 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
// target node rev: 1 1 <- 2 <- 3
|
// target node rev: 1 1 <- 2 <- 3
|
||||||
const auto target_segment_end_coordinate =
|
const auto target_segment_end_coordinate =
|
||||||
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
|
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
|
||||||
const std::vector<NodeID> target_geometry =
|
const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id);
|
||||||
facade.GetUncompressedForwardGeometry(target_geometry_id);
|
|
||||||
geometry.osm_node_ids.push_back(
|
geometry.osm_node_ids.push_back(
|
||||||
facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate]));
|
facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate)));
|
||||||
|
|
||||||
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
||||||
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
||||||
|
|||||||
@@ -13,13 +13,19 @@ namespace engine
|
|||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Multiple possible reasons can result in unnecessary/confusing instructions
|
||||||
|
// Collapsing such turns into a single turn instruction, we give a clearer
|
||||||
|
// set of instructions that is not cluttered by unnecessary turns/name changes.
|
||||||
|
OSRM_ATTR_WARN_UNUSED
|
||||||
|
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
|
||||||
|
|
||||||
// Multiple possible reasons can result in unnecessary/confusing instructions
|
// Multiple possible reasons can result in unnecessary/confusing instructions
|
||||||
// A prime example would be a segregated intersection. Turning around at this
|
// A prime example would be a segregated intersection. Turning around at this
|
||||||
// intersection would result in two instructions to turn left.
|
// intersection would result in two instructions to turn left.
|
||||||
// Collapsing such turns into a single turn instruction, we give a clearer
|
// Collapsing such turns into a single turn instruction, we give a clearer
|
||||||
// set of instructionst that is not cluttered by unnecessary turns/name changes.
|
// set of instructions that is not cluttered by unnecessary turns/name changes.
|
||||||
OSRM_ATTR_WARN_UNUSED
|
OSRM_ATTR_WARN_UNUSED
|
||||||
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
|
std::vector<RouteStep> collapseSegregatedTurnInstructions(std::vector<RouteStep> steps);
|
||||||
|
|
||||||
// A combined turn is a set of two instructions that actually form a single turn, as far as we
|
// A combined turn is a set of two instructions that actually form a single turn, as far as we
|
||||||
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots
|
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots
|
||||||
@@ -93,6 +99,22 @@ struct StaggeredTurnStrategy : CombineStrategy
|
|||||||
const RouteStep &step_prior_to_intersection;
|
const RouteStep &step_prior_to_intersection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handling of consecutive segregated steps
|
||||||
|
struct CombineSegregatedStepsStrategy : CombineStrategy
|
||||||
|
{
|
||||||
|
void operator()(RouteStep &step_at_turn_location, const RouteStep &transfer_from_step) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handling of segregated intersections
|
||||||
|
struct SegregatedTurnStrategy : CombineStrategy
|
||||||
|
{
|
||||||
|
SegregatedTurnStrategy(const RouteStep &step_prior_to_intersection);
|
||||||
|
|
||||||
|
void operator()(RouteStep &step_at_turn_location, const RouteStep &transfer_from_step) const;
|
||||||
|
|
||||||
|
const RouteStep &step_prior_to_intersection;
|
||||||
|
};
|
||||||
|
|
||||||
// Signage Strategies
|
// Signage Strategies
|
||||||
|
|
||||||
// Transfer the signage from the next step onto this step
|
// Transfer the signage from the next step onto this step
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const constexpr std::size_t MIN_END_OF_ROAD_INTERSECTIONS = std::size_t{2};
|
|||||||
const constexpr double MAX_COLLAPSE_DISTANCE = 30.0;
|
const constexpr double MAX_COLLAPSE_DISTANCE = 30.0;
|
||||||
// a bit larger than 100 to avoid oscillation in tests
|
// a bit larger than 100 to avoid oscillation in tests
|
||||||
const constexpr double NAME_SEGMENT_CUTOFF_LENGTH = 105.0;
|
const constexpr double NAME_SEGMENT_CUTOFF_LENGTH = 105.0;
|
||||||
|
const double constexpr STRAIGHT_ANGLE = 180.;
|
||||||
|
|
||||||
// check if a step is completely without turn type
|
// check if a step is completely without turn type
|
||||||
inline bool hasTurnType(const RouteStep &step)
|
inline bool hasTurnType(const RouteStep &step)
|
||||||
@@ -104,6 +105,12 @@ inline void setInstructionType(RouteStep &step, const osrm::guidance::TurnType::
|
|||||||
step.maneuver.instruction.type = type;
|
step.maneuver.instruction.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// alias for readability
|
||||||
|
inline void setModifier(RouteStep &step, const osrm::guidance::DirectionModifier::Enum modifier)
|
||||||
|
{
|
||||||
|
step.maneuver.instruction.direction_modifier = modifier;
|
||||||
|
}
|
||||||
|
|
||||||
// alias for readability
|
// alias for readability
|
||||||
inline bool haveSameMode(const RouteStep &lhs, const RouteStep &rhs)
|
inline bool haveSameMode(const RouteStep &lhs, const RouteStep &rhs)
|
||||||
{
|
{
|
||||||
@@ -215,6 +222,86 @@ inline double totalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_
|
|||||||
return total_angle;
|
return total_angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check bearings for u-turns.
|
||||||
|
// since bearings are wrapped around at 0 (we only support 0,360), we need to do some minor math to
|
||||||
|
// check if bearings `a` and `b` go in opposite directions. In general we accept some minor
|
||||||
|
// deviations for u-turns.
|
||||||
|
inline bool bearingsAreReversed(const double bearing_in, const double bearing_out)
|
||||||
|
{
|
||||||
|
// Nearly perfectly reversed angles have a difference close to 180 degrees (straight)
|
||||||
|
const double left_turn_angle = [&]() {
|
||||||
|
if (0 <= bearing_out && bearing_out <= bearing_in)
|
||||||
|
return bearing_in - bearing_out;
|
||||||
|
return bearing_in + 360 - bearing_out;
|
||||||
|
}();
|
||||||
|
return util::angularDeviation(left_turn_angle, 180) <= 35;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the specified step has only one intersection
|
||||||
|
inline bool hasSingleIntersection(const RouteStep &step)
|
||||||
|
{
|
||||||
|
return (step.intersections.size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the specified angle is a wider straight turn
|
||||||
|
inline bool isWiderStraight(const double angle) { return (angle >= 125 && angle <= 235); }
|
||||||
|
|
||||||
|
// Returns the straightest intersecting edge turn for the specified step
|
||||||
|
inline double getStraightestIntersectingEdgeTurn(const RouteStep &step)
|
||||||
|
{
|
||||||
|
const auto &intersection = step.intersections.front();
|
||||||
|
const double bearing_in = util::bearing::reverse(intersection.bearings[intersection.in]);
|
||||||
|
double staightest_turn = 360.;
|
||||||
|
double staightest_delta = 360.;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < intersection.bearings.size(); ++i)
|
||||||
|
{
|
||||||
|
// Skip the in, out, and non-traversable edges
|
||||||
|
if ((i == intersection.in) || (i == intersection.out) || !intersection.entry.at(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double intersecting_turn =
|
||||||
|
util::bearing::angleBetween(bearing_in, intersection.bearings.at(i));
|
||||||
|
double straight_delta = util::angularDeviation(intersecting_turn, STRAIGHT_ANGLE);
|
||||||
|
|
||||||
|
if (straight_delta < staightest_delta)
|
||||||
|
{
|
||||||
|
staightest_delta = straight_delta;
|
||||||
|
staightest_turn = intersecting_turn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return staightest_turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the specified step has the straightest turn as compared to
|
||||||
|
// the intersecting edges
|
||||||
|
inline bool hasStraightestTurn(const RouteStep &step)
|
||||||
|
{
|
||||||
|
const auto &intersection = step.intersections.front();
|
||||||
|
const double path_turn =
|
||||||
|
util::bearing::angleBetween(util::bearing::reverse(intersection.bearings[intersection.in]),
|
||||||
|
intersection.bearings[intersection.out]);
|
||||||
|
|
||||||
|
// Path turn must be a wider straight
|
||||||
|
if (isWiderStraight(path_turn))
|
||||||
|
{
|
||||||
|
const double straightest_intersecting_turn = getStraightestIntersectingEdgeTurn(step);
|
||||||
|
const double path_straight_delta = util::angularDeviation(path_turn, STRAIGHT_ANGLE);
|
||||||
|
const double intersecting_straight_delta =
|
||||||
|
util::angularDeviation(straightest_intersecting_turn, STRAIGHT_ANGLE);
|
||||||
|
const double path_intersecting_delta =
|
||||||
|
util::angularDeviation(path_turn, straightest_intersecting_turn);
|
||||||
|
|
||||||
|
// Add some fuzz - the delta between the path and intersecting turn must be greater
|
||||||
|
// than 10 in order to consider using the intersecting turn as the straightest
|
||||||
|
return ((path_intersecting_delta > 10.)
|
||||||
|
? (path_straight_delta <= intersecting_straight_delta)
|
||||||
|
: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace guidance */
|
} /* namespace guidance */
|
||||||
} /* namespace engine */
|
} /* namespace engine */
|
||||||
} /* namespace osrm */
|
} /* namespace osrm */
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ struct Hint
|
|||||||
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
|
static_assert(sizeof(Hint) == 80 + 4, "Hint is bigger than expected");
|
||||||
constexpr std::size_t ENCODED_HINT_SIZE = 92;
|
constexpr std::size_t ENCODED_HINT_SIZE = 112;
|
||||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,13 @@ struct PhantomNode
|
|||||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
|
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
|
||||||
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
|
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
|
||||||
|
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
|
||||||
|
forward_distance_offset(0), reverse_distance_offset(0),
|
||||||
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
||||||
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
||||||
is_valid_forward_source{false}, is_valid_forward_target{false},
|
is_valid_forward_source{false}, is_valid_forward_target{false},
|
||||||
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +81,30 @@ struct PhantomNode
|
|||||||
return reverse_duration + reverse_duration_offset;
|
return reverse_duration + reverse_duration_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DO THIS FOR DISTANCE
|
||||||
|
|
||||||
|
EdgeDistance GetForwardDistance() const
|
||||||
|
{
|
||||||
|
// ..... <-- forward_distance
|
||||||
|
// .... <-- offset
|
||||||
|
// ......... <-- desired distance
|
||||||
|
// x <-- this is PhantomNode.location
|
||||||
|
// 0----1----2----3----4 <-- EdgeBasedGraph Node segments
|
||||||
|
BOOST_ASSERT(forward_segment_id.enabled);
|
||||||
|
return forward_distance + forward_distance_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeDistance GetReverseDistance() const
|
||||||
|
{
|
||||||
|
// .......... <-- reverse_distance
|
||||||
|
// ... <-- offset
|
||||||
|
// ............. <-- desired distance
|
||||||
|
// x <-- this is PhantomNode.location
|
||||||
|
// 0----1----2----3----4 <-- EdgeBasedGraph Node segments
|
||||||
|
BOOST_ASSERT(reverse_segment_id.enabled);
|
||||||
|
return reverse_distance + reverse_distance_offset;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsBidirected() const { return forward_segment_id.enabled && reverse_segment_id.enabled; }
|
bool IsBidirected() const { return forward_segment_id.enabled && reverse_segment_id.enabled; }
|
||||||
|
|
||||||
bool IsValid(const unsigned number_of_nodes) const
|
bool IsValid(const unsigned number_of_nodes) const
|
||||||
@@ -88,6 +115,8 @@ struct PhantomNode
|
|||||||
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||||
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
||||||
(reverse_duration != MAXIMAL_EDGE_DURATION)) &&
|
(reverse_duration != MAXIMAL_EDGE_DURATION)) &&
|
||||||
|
((forward_distance != INVALID_EDGE_DISTANCE) ||
|
||||||
|
(reverse_distance != INVALID_EDGE_DISTANCE)) &&
|
||||||
(component.id != INVALID_COMPONENTID);
|
(component.id != INVALID_COMPONENTID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +159,10 @@ struct PhantomNode
|
|||||||
EdgeWeight reverse_weight,
|
EdgeWeight reverse_weight,
|
||||||
EdgeWeight forward_weight_offset,
|
EdgeWeight forward_weight_offset,
|
||||||
EdgeWeight reverse_weight_offset,
|
EdgeWeight reverse_weight_offset,
|
||||||
|
EdgeDistance forward_distance,
|
||||||
|
EdgeDistance reverse_distance,
|
||||||
|
EdgeDistance forward_distance_offset,
|
||||||
|
EdgeDistance reverse_distance_offset,
|
||||||
EdgeWeight forward_duration,
|
EdgeWeight forward_duration,
|
||||||
EdgeWeight reverse_duration,
|
EdgeWeight reverse_duration,
|
||||||
EdgeWeight forward_duration_offset,
|
EdgeWeight forward_duration_offset,
|
||||||
@@ -144,7 +177,9 @@ struct PhantomNode
|
|||||||
: forward_segment_id{other.forward_segment_id},
|
: forward_segment_id{other.forward_segment_id},
|
||||||
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
|
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
|
||||||
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
|
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
|
||||||
reverse_weight_offset{reverse_weight_offset}, forward_duration{forward_duration},
|
reverse_weight_offset{reverse_weight_offset}, forward_distance{forward_distance},
|
||||||
|
reverse_distance{reverse_distance}, forward_distance_offset{forward_distance_offset},
|
||||||
|
reverse_distance_offset{reverse_distance_offset}, forward_duration{forward_duration},
|
||||||
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
|
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
|
||||||
reverse_duration_offset{reverse_duration_offset},
|
reverse_duration_offset{reverse_duration_offset},
|
||||||
component{component.id, component.is_tiny}, location{location},
|
component{component.id, component.is_tiny}, location{location},
|
||||||
@@ -162,13 +197,17 @@ struct PhantomNode
|
|||||||
EdgeWeight reverse_weight;
|
EdgeWeight reverse_weight;
|
||||||
EdgeWeight forward_weight_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeWeight forward_weight_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
EdgeWeight reverse_weight_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeWeight reverse_weight_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
|
EdgeDistance forward_distance;
|
||||||
|
EdgeDistance reverse_distance;
|
||||||
|
EdgeDistance forward_distance_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
|
EdgeDistance reverse_distance_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
EdgeWeight forward_duration;
|
EdgeWeight forward_duration;
|
||||||
EdgeWeight reverse_duration;
|
EdgeWeight reverse_duration;
|
||||||
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
ComponentID component;
|
ComponentID component;
|
||||||
|
|
||||||
util::Coordinate location;
|
util::Coordinate location; // this is the coordinate of x
|
||||||
util::Coordinate input_location;
|
util::Coordinate input_location;
|
||||||
unsigned short fwd_segment_position;
|
unsigned short fwd_segment_position;
|
||||||
// is phantom node valid to be used as source or target
|
// is phantom node valid to be used as source or target
|
||||||
@@ -180,7 +219,7 @@ struct PhantomNode
|
|||||||
unsigned short bearing : 12;
|
unsigned short bearing : 12;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 80, "PhantomNode has more padding then expected");
|
||||||
|
|
||||||
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,12 @@ class RoutingAlgorithmsInterface
|
|||||||
virtual InternalRouteResult
|
virtual InternalRouteResult
|
||||||
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
||||||
|
|
||||||
virtual std::vector<EdgeDuration>
|
virtual std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
||||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const = 0;
|
const std::vector<std::size_t> &target_indices,
|
||||||
|
const bool calculate_distance,
|
||||||
|
const bool calculate_duration) const = 0;
|
||||||
|
|
||||||
virtual routing_algorithms::SubMatchingList
|
virtual routing_algorithms::SubMatchingList
|
||||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||||
@@ -53,6 +55,7 @@ class RoutingAlgorithmsInterface
|
|||||||
virtual bool HasDirectShortestPathSearch() const = 0;
|
virtual bool HasDirectShortestPathSearch() const = 0;
|
||||||
virtual bool HasMapMatching() const = 0;
|
virtual bool HasMapMatching() const = 0;
|
||||||
virtual bool HasManyToManySearch() const = 0;
|
virtual bool HasManyToManySearch() const = 0;
|
||||||
|
virtual bool SupportsDistanceAnnotationType() const = 0;
|
||||||
virtual bool HasGetTileTurns() const = 0;
|
virtual bool HasGetTileTurns() const = 0;
|
||||||
virtual bool HasExcludeFlags() const = 0;
|
virtual bool HasExcludeFlags() const = 0;
|
||||||
virtual bool IsValid() const = 0;
|
virtual bool IsValid() const = 0;
|
||||||
@@ -81,10 +84,12 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
InternalRouteResult
|
InternalRouteResult
|
||||||
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
|
||||||
|
|
||||||
std::vector<EdgeDuration>
|
virtual std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
||||||
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<std::size_t> &source_indices,
|
||||||
const std::vector<std::size_t> &target_indices) const final override;
|
const std::vector<std::size_t> &target_indices,
|
||||||
|
const bool calculate_distance,
|
||||||
|
const bool calculate_duration) const final override;
|
||||||
|
|
||||||
routing_algorithms::SubMatchingList
|
routing_algorithms::SubMatchingList
|
||||||
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
|
||||||
@@ -124,6 +129,11 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
|
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SupportsDistanceAnnotationType() const final override
|
||||||
|
{
|
||||||
|
return routing_algorithms::SupportsDistanceAnnotationType<Algorithm>::value;
|
||||||
|
}
|
||||||
|
|
||||||
bool HasGetTileTurns() const final override
|
bool HasGetTileTurns() const final override
|
||||||
{
|
{
|
||||||
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
|
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
|
||||||
@@ -184,10 +194,12 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatc
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
std::vector<EdgeDuration> RoutingAlgorithms<Algorithm>::ManyToManySearch(
|
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &_source_indices,
|
const std::vector<std::size_t> &_source_indices,
|
||||||
const std::vector<std::size_t> &_target_indices) const
|
const std::vector<std::size_t> &_target_indices,
|
||||||
|
const bool calculate_distance,
|
||||||
|
const bool calculate_duration) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!phantom_nodes.empty());
|
BOOST_ASSERT(!phantom_nodes.empty());
|
||||||
|
|
||||||
@@ -205,8 +217,13 @@ std::vector<EdgeDuration> RoutingAlgorithms<Algorithm>::ManyToManySearch(
|
|||||||
std::iota(target_indices.begin(), target_indices.end(), 0);
|
std::iota(target_indices.begin(), target_indices.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return routing_algorithms::manyToManySearch(
|
return routing_algorithms::manyToManySearch(heaps,
|
||||||
heaps, *facade, phantom_nodes, std::move(source_indices), std::move(target_indices));
|
*facade,
|
||||||
|
phantom_nodes,
|
||||||
|
std::move(source_indices),
|
||||||
|
std::move(target_indices),
|
||||||
|
calculate_distance,
|
||||||
|
calculate_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
|
|||||||
@@ -15,23 +15,43 @@ namespace engine
|
|||||||
{
|
{
|
||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct NodeBucket
|
struct NodeBucket
|
||||||
{
|
{
|
||||||
NodeID middle_node;
|
NodeID middle_node;
|
||||||
unsigned column_index; // a column in the weight/duration matrix
|
NodeID parent_node;
|
||||||
|
unsigned column_index : 31; // a column in the weight/duration matrix
|
||||||
|
unsigned from_clique_arc : 1;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeDuration duration;
|
EdgeDuration duration;
|
||||||
|
|
||||||
NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
|
NodeBucket(NodeID middle_node,
|
||||||
: middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
|
NodeID parent_node,
|
||||||
|
bool from_clique_arc,
|
||||||
|
unsigned column_index,
|
||||||
|
EdgeWeight weight,
|
||||||
|
EdgeDuration duration)
|
||||||
|
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
||||||
|
from_clique_arc(from_clique_arc), weight(weight), duration(duration)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBucket(NodeID middle_node,
|
||||||
|
NodeID parent_node,
|
||||||
|
unsigned column_index,
|
||||||
|
EdgeWeight weight,
|
||||||
|
EdgeDuration duration)
|
||||||
|
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
||||||
|
from_clique_arc(false), weight(weight), duration(duration)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// partial order comparison
|
// partial order comparison
|
||||||
bool operator<(const NodeBucket &rhs) const { return middle_node < rhs.middle_node; }
|
bool operator<(const NodeBucket &rhs) const
|
||||||
|
{
|
||||||
|
return std::tie(middle_node, column_index) < std::tie(rhs.middle_node, rhs.column_index);
|
||||||
|
}
|
||||||
|
|
||||||
// functor for equal_range
|
// functor for equal_range
|
||||||
struct Compare
|
struct Compare
|
||||||
@@ -46,15 +66,36 @@ struct NodeBucket
|
|||||||
return lhs < rhs.middle_node;
|
return lhs < rhs.middle_node;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// functor for equal_range
|
||||||
|
struct ColumnCompare
|
||||||
|
{
|
||||||
|
unsigned column_idx;
|
||||||
|
|
||||||
|
ColumnCompare(unsigned column_idx) : column_idx(column_idx){};
|
||||||
|
|
||||||
|
bool operator()(const NodeBucket &lhs, const NodeID &rhs) const // lowerbound
|
||||||
|
{
|
||||||
|
return std::tie(lhs.middle_node, lhs.column_index) < std::tie(rhs, column_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const NodeID &lhs, const NodeBucket &rhs) const // upperbound
|
||||||
|
{
|
||||||
|
return std::tie(lhs, column_idx) < std::tie(rhs.middle_node, rhs.column_index);
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
|
||||||
const DataFacade<Algorithm> &facade,
|
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const DataFacade<Algorithm> &facade,
|
||||||
const std::vector<std::size_t> &source_indices,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
const std::vector<std::size_t> &target_indices);
|
const std::vector<std::size_t> &source_indices,
|
||||||
|
const std::vector<std::size_t> &target_indices,
|
||||||
|
const bool calculate_distance,
|
||||||
|
const bool calculate_duration);
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|||||||
@@ -136,24 +136,29 @@ void annotatePath(const FacadeT &facade,
|
|||||||
|
|
||||||
// datastructures to hold extracted data from geometry
|
// datastructures to hold extracted data from geometry
|
||||||
std::vector<NodeID> id_vector;
|
std::vector<NodeID> id_vector;
|
||||||
std::vector<EdgeWeight> weight_vector;
|
std::vector<SegmentWeight> weight_vector;
|
||||||
std::vector<EdgeWeight> duration_vector;
|
std::vector<SegmentDuration> duration_vector;
|
||||||
std::vector<DatasourceID> datasource_vector;
|
std::vector<DatasourceID> datasource_vector;
|
||||||
|
|
||||||
const auto get_segment_geometry = [&](const auto geometry_index) {
|
const auto get_segment_geometry = [&](const auto geometry_index) {
|
||||||
|
const auto copy = [](auto &vector, const auto range) {
|
||||||
|
vector.resize(range.size());
|
||||||
|
std::copy(range.begin(), range.end(), vector.begin());
|
||||||
|
};
|
||||||
|
|
||||||
if (geometry_index.forward)
|
if (geometry_index.forward)
|
||||||
{
|
{
|
||||||
id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id);
|
copy(id_vector, facade.GetUncompressedForwardGeometry(geometry_index.id));
|
||||||
weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id);
|
copy(weight_vector, facade.GetUncompressedForwardWeights(geometry_index.id));
|
||||||
duration_vector = facade.GetUncompressedForwardDurations(geometry_index.id);
|
copy(duration_vector, facade.GetUncompressedForwardDurations(geometry_index.id));
|
||||||
datasource_vector = facade.GetUncompressedForwardDatasources(geometry_index.id);
|
copy(datasource_vector, facade.GetUncompressedForwardDatasources(geometry_index.id));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
id_vector = facade.GetUncompressedReverseGeometry(geometry_index.id);
|
copy(id_vector, facade.GetUncompressedReverseGeometry(geometry_index.id));
|
||||||
weight_vector = facade.GetUncompressedReverseWeights(geometry_index.id);
|
copy(weight_vector, facade.GetUncompressedReverseWeights(geometry_index.id));
|
||||||
duration_vector = facade.GetUncompressedReverseDurations(geometry_index.id);
|
copy(duration_vector, facade.GetUncompressedReverseDurations(geometry_index.id));
|
||||||
datasource_vector = facade.GetUncompressedReverseDatasources(geometry_index.id);
|
copy(datasource_vector, facade.GetUncompressedReverseDatasources(geometry_index.id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,8 +179,9 @@ void annotatePath(const FacadeT &facade,
|
|||||||
|
|
||||||
BOOST_ASSERT(id_vector.size() > 0);
|
BOOST_ASSERT(id_vector.size() > 0);
|
||||||
BOOST_ASSERT(datasource_vector.size() > 0);
|
BOOST_ASSERT(datasource_vector.size() > 0);
|
||||||
BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1);
|
BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size());
|
||||||
BOOST_ASSERT(duration_vector.size() == id_vector.size() - 1);
|
BOOST_ASSERT(duration_vector.size() + 1 == id_vector.size());
|
||||||
|
|
||||||
const bool is_first_segment = unpacked_path.empty();
|
const bool is_first_segment = unpacked_path.empty();
|
||||||
|
|
||||||
const std::size_t start_index =
|
const std::size_t start_index =
|
||||||
@@ -192,23 +198,24 @@ void annotatePath(const FacadeT &facade,
|
|||||||
BOOST_ASSERT(start_index < end_index);
|
BOOST_ASSERT(start_index < end_index);
|
||||||
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
||||||
{
|
{
|
||||||
unpacked_path.push_back(PathData{*node_from,
|
unpacked_path.push_back(
|
||||||
id_vector[segment_idx + 1],
|
PathData{*node_from,
|
||||||
name_index,
|
id_vector[segment_idx + 1],
|
||||||
is_segregated,
|
name_index,
|
||||||
weight_vector[segment_idx],
|
is_segregated,
|
||||||
0,
|
static_cast<EdgeWeight>(weight_vector[segment_idx]),
|
||||||
duration_vector[segment_idx],
|
0,
|
||||||
0,
|
static_cast<EdgeDuration>(duration_vector[segment_idx]),
|
||||||
guidance::TurnInstruction::NO_TURN(),
|
0,
|
||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
guidance::TurnInstruction::NO_TURN(),
|
||||||
travel_mode,
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
classes,
|
travel_mode,
|
||||||
EMPTY_ENTRY_CLASS,
|
classes,
|
||||||
datasource_vector[segment_idx],
|
EMPTY_ENTRY_CLASS,
|
||||||
osrm::guidance::TurnBearing(0),
|
datasource_vector[segment_idx],
|
||||||
osrm::guidance::TurnBearing(0),
|
osrm::guidance::TurnBearing(0),
|
||||||
is_left_hand_driving});
|
osrm::guidance::TurnBearing(0),
|
||||||
|
is_left_hand_driving});
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||||
if (facade.HasLaneData(turn_id))
|
if (facade.HasLaneData(turn_id))
|
||||||
@@ -264,16 +271,16 @@ void annotatePath(const FacadeT &facade,
|
|||||||
for (std::size_t segment_idx = start_index; segment_idx != end_index;
|
for (std::size_t segment_idx = start_index; segment_idx != end_index;
|
||||||
(start_index < end_index ? ++segment_idx : --segment_idx))
|
(start_index < end_index ? ++segment_idx : --segment_idx))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(segment_idx < id_vector.size() - 1);
|
BOOST_ASSERT(segment_idx < static_cast<std::size_t>(id_vector.size() - 1));
|
||||||
BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0);
|
BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0);
|
||||||
unpacked_path.push_back(
|
unpacked_path.push_back(
|
||||||
PathData{target_node_id,
|
PathData{target_node_id,
|
||||||
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
||||||
facade.GetNameIndex(target_node_id),
|
facade.GetNameIndex(target_node_id),
|
||||||
facade.IsSegregated(target_node_id),
|
facade.IsSegregated(target_node_id),
|
||||||
weight_vector[segment_idx],
|
static_cast<EdgeWeight>(weight_vector[segment_idx]),
|
||||||
0,
|
0,
|
||||||
duration_vector[segment_idx],
|
static_cast<EdgeDuration>(duration_vector[segment_idx]),
|
||||||
0,
|
0,
|
||||||
guidance::TurnInstruction::NO_TURN(),
|
guidance::TurnInstruction::NO_TURN(),
|
||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
@@ -399,6 +406,22 @@ InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
|
|||||||
return raw_route_data;
|
return raw_route_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename FacadeT> EdgeDistance computeEdgeDistance(const FacadeT &facade, NodeID node_id)
|
||||||
|
{
|
||||||
|
const auto geometry_index = facade.GetGeometryIndex(node_id);
|
||||||
|
|
||||||
|
EdgeDistance total_distance = 0.0;
|
||||||
|
|
||||||
|
auto geometry_range = facade.GetUncompressedForwardGeometry(geometry_index.id);
|
||||||
|
for (auto current = geometry_range.begin(); current < geometry_range.end() - 1; ++current)
|
||||||
|
{
|
||||||
|
total_distance += util::coordinate_calculation::fccApproximateDistance(
|
||||||
|
facade.GetCoordinateOfNode(*current), facade.GetCoordinateOfNode(*std::next(current)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_distance;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -288,6 +288,106 @@ void unpackPath(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BidirectionalIterator>
|
||||||
|
EdgeDistance calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
|
||||||
|
BidirectionalIterator packed_path_begin,
|
||||||
|
BidirectionalIterator packed_path_end)
|
||||||
|
{
|
||||||
|
// Make sure we have at least something to unpack
|
||||||
|
if (packed_path_begin == packed_path_end ||
|
||||||
|
std::distance(packed_path_begin, packed_path_end) <= 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::stack<std::tuple<NodeID, NodeID, bool>> recursion_stack;
|
||||||
|
std::stack<EdgeDistance> distance_stack;
|
||||||
|
// We have to push the path in reverse order onto the stack because it's LIFO.
|
||||||
|
for (auto current = std::prev(packed_path_end); current > packed_path_begin;
|
||||||
|
current = std::prev(current))
|
||||||
|
{
|
||||||
|
recursion_stack.emplace(*std::prev(current), *current, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<NodeID, NodeID, bool> edge;
|
||||||
|
while (!recursion_stack.empty())
|
||||||
|
{
|
||||||
|
edge = recursion_stack.top();
|
||||||
|
recursion_stack.pop();
|
||||||
|
|
||||||
|
// Have we processed the edge before? tells us if we have values in the durations stack that
|
||||||
|
// we can add up
|
||||||
|
if (!std::get<2>(edge))
|
||||||
|
{ // haven't processed edge before, so process it in the body!
|
||||||
|
|
||||||
|
std::get<2>(edge) = true; // mark that this edge will now be processed
|
||||||
|
|
||||||
|
// Look for an edge on the forward CH graph (.forward)
|
||||||
|
EdgeID smaller_edge_id =
|
||||||
|
facade.FindSmallestEdge(std::get<0>(edge), std::get<1>(edge), [](const auto &data) {
|
||||||
|
return data.forward;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If we didn't find one there, the we might be looking at a part of the path that
|
||||||
|
// was found using the backward search. Here, we flip the node order (.second,
|
||||||
|
// .first) and only consider edges with the `.backward` flag.
|
||||||
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||||
|
{
|
||||||
|
smaller_edge_id =
|
||||||
|
facade.FindSmallestEdge(std::get<1>(edge),
|
||||||
|
std::get<0>(edge),
|
||||||
|
[](const auto &data) { return data.backward; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find anything *still*, then something is broken and someone has
|
||||||
|
// called this function with bad values.
|
||||||
|
BOOST_ASSERT_MSG(smaller_edge_id != SPECIAL_EDGEID, "Invalid smaller edge ID");
|
||||||
|
|
||||||
|
const auto &data = facade.GetEdgeData(smaller_edge_id);
|
||||||
|
BOOST_ASSERT_MSG(data.weight != std::numeric_limits<EdgeWeight>::max(),
|
||||||
|
"edge weight invalid");
|
||||||
|
|
||||||
|
// If the edge is a shortcut, we need to add the two halfs to the stack.
|
||||||
|
if (data.shortcut)
|
||||||
|
{ // unpack
|
||||||
|
const NodeID middle_node_id = data.turn_id;
|
||||||
|
// Note the order here - we're adding these to a stack, so we
|
||||||
|
// want the first->middle to get visited before middle->second
|
||||||
|
recursion_stack.emplace(edge);
|
||||||
|
recursion_stack.emplace(middle_node_id, std::get<1>(edge), false);
|
||||||
|
recursion_stack.emplace(std::get<0>(edge), middle_node_id, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// compute the duration here and put it onto the duration stack using method
|
||||||
|
// similar to annotatePath but smaller
|
||||||
|
EdgeDistance distance = computeEdgeDistance(facade, std::get<0>(edge));
|
||||||
|
distance_stack.emplace(distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // the edge has already been processed. this means that there are enough values in the
|
||||||
|
// distances stack
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(distance_stack.size() >= 2,
|
||||||
|
"There are not enough (at least 2) values on the distance stack");
|
||||||
|
EdgeDistance distance1 = distance_stack.top();
|
||||||
|
distance_stack.pop();
|
||||||
|
EdgeDistance distance2 = distance_stack.top();
|
||||||
|
distance_stack.pop();
|
||||||
|
EdgeDistance distance = distance1 + distance2;
|
||||||
|
distance_stack.emplace(distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeDistance total_distance = 0;
|
||||||
|
while (!distance_stack.empty())
|
||||||
|
{
|
||||||
|
total_distance += distance_stack.top();
|
||||||
|
distance_stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_distance;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename RandomIter, typename FacadeT>
|
template <typename RandomIter, typename FacadeT>
|
||||||
void unpackPath(const FacadeT &facade,
|
void unpackPath(const FacadeT &facade,
|
||||||
RandomIter packed_path_begin,
|
RandomIter packed_path_begin,
|
||||||
@@ -340,6 +440,11 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHe
|
|||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> &packed_path);
|
std::vector<NodeID> &packed_path);
|
||||||
|
|
||||||
|
void retrievePackedPathFromSingleManyToManyHeap(
|
||||||
|
const SearchEngineData<Algorithm>::ManyToManyQueryHeap &search_heap,
|
||||||
|
const NodeID middle_node_id,
|
||||||
|
std::vector<NodeID> &packed_path);
|
||||||
|
|
||||||
// assumes that heaps are already setup correctly.
|
// assumes that heaps are already setup correctly.
|
||||||
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
|
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
|
||||||
// Offsets.
|
// Offsets.
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return tr
|
|||||||
|
|
||||||
// Restricted search (Args is LevelID, CellID):
|
// Restricted search (Args is LevelID, CellID):
|
||||||
// * use the fixed level for queries
|
// * use the fixed level for queries
|
||||||
// * check if the node cell is the same as the specified parent onr
|
// * check if the node cell is the same as the specified parent
|
||||||
template <typename MultiLevelPartition>
|
template <typename MultiLevelPartition>
|
||||||
inline LevelID getNodeQueryLevel(const MultiLevelPartition &, NodeID, LevelID level, CellID)
|
inline LevelID getNodeQueryLevel(const MultiLevelPartition &, NodeID, LevelID level, CellID)
|
||||||
{
|
{
|
||||||
@@ -65,6 +65,61 @@ inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
|
|||||||
{
|
{
|
||||||
return cell == parent;
|
return cell == parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unrestricted search with a single phantom node (Args is const PhantomNode &):
|
||||||
|
// * use partition.GetQueryLevel to find the node query level
|
||||||
|
// * allow to traverse all cells
|
||||||
|
template <typename MultiLevelPartition>
|
||||||
|
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
||||||
|
const NodeID node,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
auto highest_diffrent_level = [&partition, node](const SegmentID &phantom_node) {
|
||||||
|
if (phantom_node.enabled)
|
||||||
|
return partition.GetHighestDifferentLevel(phantom_node.id, node);
|
||||||
|
return INVALID_LEVEL_ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto node_level = std::min(highest_diffrent_level(phantom_node.forward_segment_id),
|
||||||
|
highest_diffrent_level(phantom_node.reverse_segment_id));
|
||||||
|
|
||||||
|
return node_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unrestricted search with a single phantom node and a vector of phantom nodes:
|
||||||
|
// * use partition.GetQueryLevel to find the node query level
|
||||||
|
// * allow to traverse all cells
|
||||||
|
template <typename MultiLevelPartition>
|
||||||
|
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
||||||
|
NodeID node,
|
||||||
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
|
const std::size_t phantom_index,
|
||||||
|
const std::vector<std::size_t> &phantom_indices)
|
||||||
|
{
|
||||||
|
auto min_level = [&partition, node](const PhantomNode &phantom_node) {
|
||||||
|
|
||||||
|
const auto &forward_segment = phantom_node.forward_segment_id;
|
||||||
|
const auto forward_level =
|
||||||
|
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
|
||||||
|
: INVALID_LEVEL_ID;
|
||||||
|
|
||||||
|
const auto &reverse_segment = phantom_node.reverse_segment_id;
|
||||||
|
const auto reverse_level =
|
||||||
|
reverse_segment.enabled ? partition.GetHighestDifferentLevel(node, reverse_segment.id)
|
||||||
|
: INVALID_LEVEL_ID;
|
||||||
|
|
||||||
|
return std::min(forward_level, reverse_level);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get minimum level over all phantoms of the highest different level with respect to node
|
||||||
|
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
|
||||||
|
auto result = min_level(phantom_nodes[phantom_index]);
|
||||||
|
for (const auto &index : phantom_indices)
|
||||||
|
{
|
||||||
|
result = std::min(result, min_level(phantom_nodes[index]));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Heaps only record for each node its predecessor ("parent") on the shortest path.
|
// Heaps only record for each node its predecessor ("parent") on the shortest path.
|
||||||
@@ -74,6 +129,46 @@ inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
|
|||||||
using PackedEdge = std::tuple</*from*/ NodeID, /*to*/ NodeID, /*from_clique_arc*/ bool>;
|
using PackedEdge = std::tuple</*from*/ NodeID, /*to*/ NodeID, /*from_clique_arc*/ bool>;
|
||||||
using PackedPath = std::vector<PackedEdge>;
|
using PackedPath = std::vector<PackedEdge>;
|
||||||
|
|
||||||
|
template <bool DIRECTION, typename OutIter>
|
||||||
|
inline void retrievePackedPathFromSingleManyToManyHeap(
|
||||||
|
const SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap, const NodeID middle, OutIter out)
|
||||||
|
{
|
||||||
|
|
||||||
|
NodeID current = middle;
|
||||||
|
NodeID parent = heap.GetData(current).parent;
|
||||||
|
|
||||||
|
while (current != parent)
|
||||||
|
{
|
||||||
|
const auto &data = heap.GetData(current);
|
||||||
|
|
||||||
|
if (DIRECTION == FORWARD_DIRECTION)
|
||||||
|
{
|
||||||
|
*out = std::make_tuple(parent, current, data.from_clique_arc);
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
else if (DIRECTION == REVERSE_DIRECTION)
|
||||||
|
{
|
||||||
|
*out = std::make_tuple(current, parent, data.from_clique_arc);
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = parent;
|
||||||
|
parent = heap.GetData(parent).parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool DIRECTION>
|
||||||
|
inline PackedPath retrievePackedPathFromSingleManyToManyHeap(
|
||||||
|
const SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap, const NodeID middle)
|
||||||
|
{
|
||||||
|
|
||||||
|
PackedPath packed_path;
|
||||||
|
retrievePackedPathFromSingleManyToManyHeap<DIRECTION>(
|
||||||
|
heap, middle, std::back_inserter(packed_path));
|
||||||
|
|
||||||
|
return packed_path;
|
||||||
|
}
|
||||||
|
|
||||||
template <bool DIRECTION, typename OutIter>
|
template <bool DIRECTION, typename OutIter>
|
||||||
inline void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &heap,
|
inline void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &heap,
|
||||||
const NodeID middle,
|
const NodeID middle,
|
||||||
@@ -206,15 +301,22 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
for (const auto edge : facade.GetBorderEdgeRange(level, node))
|
for (const auto edge : facade.GetBorderEdgeRange(level, node))
|
||||||
{
|
{
|
||||||
const auto &edge_data = facade.GetEdgeData(edge);
|
const auto &edge_data = facade.GetEdgeData(edge);
|
||||||
if (DIRECTION == FORWARD_DIRECTION ? edge_data.forward : edge_data.backward)
|
|
||||||
|
if ((DIRECTION == FORWARD_DIRECTION) ? facade.IsForwardEdge(edge)
|
||||||
|
: facade.IsBackwardEdge(edge))
|
||||||
{
|
{
|
||||||
const NodeID to = facade.GetTarget(edge);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
|
||||||
if (!facade.ExcludeNode(to) &&
|
if (!facade.ExcludeNode(to) &&
|
||||||
checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
|
checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(edge_data.weight > 0, "edge_weight invalid");
|
const auto node_weight =
|
||||||
const EdgeWeight to_weight = weight + edge_data.weight;
|
facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? node : to);
|
||||||
|
const auto turn_penalty = facade.GetWeightPenaltyForEdgeID(edge_data.turn_id);
|
||||||
|
|
||||||
|
// TODO: BOOST_ASSERT(edge_data.weight == node_weight + turn_penalty);
|
||||||
|
|
||||||
|
const EdgeWeight to_weight = weight + node_weight + turn_penalty;
|
||||||
|
|
||||||
if (!forward_heap.WasInserted(to))
|
if (!forward_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
@@ -407,6 +509,90 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
|
||||||
|
// This gives us a packed path (node ids) from the base graph around s and t,
|
||||||
|
// and overlay node ids otherwise. We then have to unpack the overlay clique
|
||||||
|
// edges by recursively descending unpacking the path down to the base graph.
|
||||||
|
|
||||||
|
using UnpackedNodes = std::vector<NodeID>;
|
||||||
|
using UnpackedEdges = std::vector<EdgeID>;
|
||||||
|
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
|
||||||
|
|
||||||
|
template <typename Algorithm, typename... Args>
|
||||||
|
UnpackedPath
|
||||||
|
unpackPathAndCalculateDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade,
|
||||||
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
|
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||||
|
const bool force_loop_forward,
|
||||||
|
const bool force_loop_reverse,
|
||||||
|
EdgeWeight weight_upper_bound,
|
||||||
|
PackedPath packed_path,
|
||||||
|
NodeID middle,
|
||||||
|
Args... args)
|
||||||
|
{
|
||||||
|
EdgeWeight weight = weight_upper_bound;
|
||||||
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
|
const NodeID source_node = !packed_path.empty() ? std::get<0>(packed_path.front()) : middle;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
for (auto const &packed_edge : packed_path)
|
||||||
|
{
|
||||||
|
NodeID source, target;
|
||||||
|
bool overlay_edge;
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // an overlay graph edge
|
||||||
|
LevelID level = getNodeQueryLevel(partition, source, args...);
|
||||||
|
CellID parent_cell_id = partition.GetCell(level, source);
|
||||||
|
BOOST_ASSERT(parent_cell_id == partition.GetCell(level, target));
|
||||||
|
|
||||||
|
LevelID sublevel = level - 1;
|
||||||
|
|
||||||
|
// Here heaps can be reused, let's go deeper!
|
||||||
|
forward_heap.Clear();
|
||||||
|
reverse_heap.Clear();
|
||||||
|
forward_heap.Insert(source, 0, {source});
|
||||||
|
reverse_heap.Insert(target, 0, {target});
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
weight_upper_bound,
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
|
||||||
|
}
|
||||||
|
|
||||||
// Alias to be compatible with the CH-based search
|
// Alias to be compatible with the CH-based search
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
|||||||
@@ -207,6 +207,25 @@ void unpackLegs(const DataFacade<Algorithm> &facade,
|
|||||||
phantom_nodes_vector[current_leg].target_phantom.forward_segment_id.id));
|
phantom_nodes_vector[current_leg].target_phantom.forward_segment_id.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Algorithm>
|
||||||
|
inline void initializeHeap(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<Algorithm> &facade)
|
||||||
|
{
|
||||||
|
|
||||||
|
const auto nodes_number = facade.GetNumberOfNodes();
|
||||||
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline void initializeHeap<mld::Algorithm>(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||||
|
const DataFacade<mld::Algorithm> &facade)
|
||||||
|
{
|
||||||
|
|
||||||
|
const auto nodes_number = facade.GetNumberOfNodes();
|
||||||
|
const auto border_nodes_number = facade.GetMaxBorderNodeID() + 1;
|
||||||
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number, border_nodes_number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
@@ -221,7 +240,7 @@ InternalRouteResult shortestPathSearch(SearchEngineData<Algorithm> &engine_worki
|
|||||||
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
|
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
|
||||||
: facade.GetContinueStraightDefault());
|
: facade.GetContinueStraightDefault());
|
||||||
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
initializeHeap(engine_working_data, facade);
|
||||||
|
|
||||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||||
|
|||||||
@@ -91,13 +91,13 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
|||||||
NodeID,
|
NodeID,
|
||||||
EdgeWeight,
|
EdgeWeight,
|
||||||
MultiLayerDijkstraHeapData,
|
MultiLayerDijkstraHeapData,
|
||||||
util::UnorderedMapStorage<NodeID, int>>;
|
util::TwoLevelStorage<NodeID, int>>;
|
||||||
|
|
||||||
using ManyToManyQueryHeap = util::QueryHeap<NodeID,
|
using ManyToManyQueryHeap = util::QueryHeap<NodeID,
|
||||||
NodeID,
|
NodeID,
|
||||||
EdgeWeight,
|
EdgeWeight,
|
||||||
ManyToManyMultiLayerDijkstraHeapData,
|
ManyToManyMultiLayerDijkstraHeapData,
|
||||||
util::UnorderedMapStorage<NodeID, int>>;
|
util::TwoLevelStorage<NodeID, int>>;
|
||||||
|
|
||||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||||
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
|
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
|
||||||
@@ -106,9 +106,11 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
|||||||
static SearchEngineHeapPtr reverse_heap_1;
|
static SearchEngineHeapPtr reverse_heap_1;
|
||||||
static ManyToManyHeapPtr many_to_many_heap;
|
static ManyToManyHeapPtr many_to_many_heap;
|
||||||
|
|
||||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes,
|
||||||
|
unsigned number_of_boundary_nodes);
|
||||||
|
|
||||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes,
|
||||||
|
unsigned number_of_boundary_nodes);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef OSRM_EXTRACTOR_COMPRESSED_NODE_BASED_GRAPH_EDGE_HPP
|
||||||
|
#define OSRM_EXTRACTOR_COMPRESSED_NODE_BASED_GRAPH_EDGE_HPP
|
||||||
|
|
||||||
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
// We encode the cnbg graph only using its topology as edge list
|
||||||
|
struct CompressedNodeBasedGraphEdge
|
||||||
|
{
|
||||||
|
NodeID source;
|
||||||
|
NodeID target;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OSRM_EXTRACTOR_COMPRESSED_NODE_BASED_GRAPH_EDGE_HPP
|
||||||
@@ -9,20 +9,16 @@
|
|||||||
#include "extractor/edge_based_node_segment.hpp"
|
#include "extractor/edge_based_node_segment.hpp"
|
||||||
#include "extractor/extraction_turn.hpp"
|
#include "extractor/extraction_turn.hpp"
|
||||||
#include "extractor/maneuver_override.hpp"
|
#include "extractor/maneuver_override.hpp"
|
||||||
|
#include "extractor/name_table.hpp"
|
||||||
#include "extractor/nbg_to_ebg.hpp"
|
#include "extractor/nbg_to_ebg.hpp"
|
||||||
#include "extractor/node_data_container.hpp"
|
#include "extractor/node_data_container.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
#include "extractor/restriction_index.hpp"
|
#include "extractor/restriction_index.hpp"
|
||||||
#include "extractor/turn_lane_types.hpp"
|
#include "extractor/turn_lane_types.hpp"
|
||||||
#include "extractor/way_restriction_map.hpp"
|
#include "extractor/way_restriction_map.hpp"
|
||||||
#include "guidance/turn_analysis.hpp"
|
|
||||||
#include "guidance/turn_instruction.hpp"
|
|
||||||
|
|
||||||
#include "util/concurrent_id_map.hpp"
|
#include "util/concurrent_id_map.hpp"
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "util/deallocating_vector.hpp"
|
||||||
#include "util/guidance/bearing_class.hpp"
|
|
||||||
#include "util/guidance/entry_class.hpp"
|
|
||||||
#include "util/name_table.hpp"
|
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
@@ -74,7 +70,7 @@ class EdgeBasedGraphFactory
|
|||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const util::NameTable &name_table,
|
const NameTable &name_table,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
const LaneDescriptionMap &lane_description_map);
|
const LaneDescriptionMap &lane_description_map);
|
||||||
|
|
||||||
@@ -95,21 +91,11 @@ class EdgeBasedGraphFactory
|
|||||||
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
|
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
|
||||||
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
||||||
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
||||||
|
void GetEdgeBasedNodeDurations(std::vector<EdgeWeight> &output_node_durations);
|
||||||
std::uint32_t GetConnectivityChecksum() const;
|
std::uint32_t GetConnectivityChecksum() const;
|
||||||
|
|
||||||
std::uint64_t GetNumberOfEdgeBasedNodes() const;
|
std::uint64_t GetNumberOfEdgeBasedNodes() const;
|
||||||
|
|
||||||
// Basic analysis of a turn (u --(e1)-- v --(e2)-- w)
|
|
||||||
// with known angle.
|
|
||||||
// Handles special cases like u-turns and roundabouts
|
|
||||||
// For basic turns, the turn based on the angle-classification is returned
|
|
||||||
guidance::TurnInstruction AnalyzeTurn(const NodeID u,
|
|
||||||
const EdgeID e1,
|
|
||||||
const NodeID v,
|
|
||||||
const EdgeID e2,
|
|
||||||
const NodeID w,
|
|
||||||
const double angle) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
||||||
|
|
||||||
@@ -132,6 +118,7 @@ class EdgeBasedGraphFactory
|
|||||||
//! node weights that indicate the length of the segment (node based) represented by the
|
//! node weights that indicate the length of the segment (node based) represented by the
|
||||||
//! edge-based node
|
//! edge-based node
|
||||||
std::vector<EdgeWeight> m_edge_based_node_weights;
|
std::vector<EdgeWeight> m_edge_based_node_weights;
|
||||||
|
std::vector<EdgeDuration> m_edge_based_node_durations;
|
||||||
|
|
||||||
//! list of edge based nodes (compressed segments)
|
//! list of edge based nodes (compressed segments)
|
||||||
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
|
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
|
||||||
@@ -153,7 +140,7 @@ class EdgeBasedGraphFactory
|
|||||||
const std::unordered_set<NodeID> &m_traffic_lights;
|
const std::unordered_set<NodeID> &m_traffic_lights;
|
||||||
const CompressedEdgeContainer &m_compressed_edge_container;
|
const CompressedEdgeContainer &m_compressed_edge_container;
|
||||||
|
|
||||||
const util::NameTable &name_table;
|
const NameTable &name_table;
|
||||||
const std::unordered_set<EdgeID> &segregated_edges;
|
const std::unordered_set<EdgeID> &segregated_edges;
|
||||||
const LaneDescriptionMap &lane_description_map;
|
const LaneDescriptionMap &lane_description_map;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "extractor/restriction.hpp"
|
#include "extractor/restriction.hpp"
|
||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/tar_fwd.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -27,9 +27,9 @@ class ExtractionContainers
|
|||||||
void PrepareRestrictions();
|
void PrepareRestrictions();
|
||||||
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
||||||
|
|
||||||
void WriteNodes(storage::io::FileWriter &file_out) const;
|
void WriteNodes(storage::tar::FileWriter &file_out) const;
|
||||||
void WriteEdges(storage::io::FileWriter &file_out) const;
|
void WriteEdges(storage::tar::FileWriter &file_out) const;
|
||||||
void WriteMetadata(storage::io::FileWriter &file_out) const;
|
void WriteMetadata(storage::tar::FileWriter &file_out) const;
|
||||||
void WriteCharData(const std::string &file_name);
|
void WriteCharData(const std::string &file_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class Extractor
|
|||||||
const std::vector<TurnRestriction> &turn_restrictions,
|
const std::vector<TurnRestriction> &turn_restrictions,
|
||||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
const util::NameTable &name_table,
|
const NameTable &name_table,
|
||||||
const std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
const std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
const LaneDescriptionMap &turn_lane_map,
|
const LaneDescriptionMap &turn_lane_map,
|
||||||
// for calculating turn penalties
|
// for calculating turn penalties
|
||||||
@@ -87,6 +87,7 @@ class Extractor
|
|||||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
|
std::vector<EdgeDuration> &edge_based_node_durations,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||||
std::uint32_t &connectivity_checksum);
|
std::uint32_t &connectivity_checksum);
|
||||||
|
|
||||||
@@ -99,11 +100,6 @@ class Extractor
|
|||||||
const std::vector<util::Coordinate> &coordinates);
|
const std::vector<util::Coordinate> &coordinates);
|
||||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||||
|
|
||||||
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
|
|
||||||
static void WriteCompressedNodeBasedGraph(const std::string &path,
|
|
||||||
const util::NodeBasedDynamicGraph &graph,
|
|
||||||
const std::vector<util::Coordinate> &coordiantes);
|
|
||||||
|
|
||||||
void WriteConditionalRestrictions(
|
void WriteConditionalRestrictions(
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||||
@@ -116,7 +112,7 @@ class Extractor
|
|||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::vector<TurnRestriction> &turn_restrictions,
|
const std::vector<TurnRestriction> &turn_restrictions,
|
||||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||||
const util::NameTable &name_table,
|
const NameTable &name_table,
|
||||||
LaneDescriptionMap lane_description_map,
|
LaneDescriptionMap lane_description_map,
|
||||||
ScriptingEnvironment &scripting_environment);
|
ScriptingEnvironment &scripting_environment);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ struct ExtractorConfig final : storage::IOConfig
|
|||||||
".osrm.names",
|
".osrm.names",
|
||||||
".osrm.tls",
|
".osrm.tls",
|
||||||
".osrm.tld",
|
".osrm.tld",
|
||||||
".osrm.timestamp",
|
|
||||||
".osrm.geometry",
|
".osrm.geometry",
|
||||||
".osrm.nbg_nodes",
|
".osrm.nbg_nodes",
|
||||||
".osrm.ebg_nodes",
|
".osrm.ebg_nodes",
|
||||||
|
|||||||
+304
-68
@@ -4,12 +4,14 @@
|
|||||||
#include "extractor/edge_based_edge.hpp"
|
#include "extractor/edge_based_edge.hpp"
|
||||||
#include "extractor/node_data_container.hpp"
|
#include "extractor/node_data_container.hpp"
|
||||||
#include "extractor/profile_properties.hpp"
|
#include "extractor/profile_properties.hpp"
|
||||||
|
#include "extractor/query_node.hpp"
|
||||||
#include "extractor/serialization.hpp"
|
#include "extractor/serialization.hpp"
|
||||||
#include "extractor/turn_lane_types.hpp"
|
#include "extractor/turn_lane_types.hpp"
|
||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
#include "util/packed_vector.hpp"
|
#include "util/packed_vector.hpp"
|
||||||
#include "util/range_table.hpp"
|
#include "util/range_table.hpp"
|
||||||
#include "util/serialization.hpp"
|
#include "util/serialization.hpp"
|
||||||
@@ -33,10 +35,10 @@ inline void writeIntersections(const boost::filesystem::path &path,
|
|||||||
std::is_same<IntersectionBearingsView, IntersectionBearingsT>::value,
|
std::is_same<IntersectionBearingsView, IntersectionBearingsT>::value,
|
||||||
"");
|
"");
|
||||||
|
|
||||||
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
storage::tar::FileWriter writer(path, storage::tar::FileWriter::GenerateFingerprint);
|
||||||
|
|
||||||
serialization::write(writer, intersection_bearings);
|
serialization::write(writer, "/common/intersection_bearings", intersection_bearings);
|
||||||
storage::serialization::write(writer, entry_classes);
|
storage::serialization::write(writer, "/common/entry_classes", entry_classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the .osrm.icd file
|
// read the .osrm.icd file
|
||||||
@@ -49,30 +51,30 @@ inline void readIntersections(const boost::filesystem::path &path,
|
|||||||
std::is_same<IntersectionBearingsView, IntersectionBearingsT>::value,
|
std::is_same<IntersectionBearingsView, IntersectionBearingsT>::value,
|
||||||
"");
|
"");
|
||||||
|
|
||||||
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
storage::tar::FileReader reader(path, storage::tar::FileReader::VerifyFingerprint);
|
||||||
|
|
||||||
serialization::read(reader, intersection_bearings);
|
serialization::read(reader, "/common/intersection_bearings", intersection_bearings);
|
||||||
storage::serialization::read(reader, entry_classes);
|
storage::serialization::read(reader, "/common/entry_classes", entry_classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.properties
|
// reads .osrm.properties
|
||||||
inline void readProfileProperties(const boost::filesystem::path &path,
|
inline void readProfileProperties(const boost::filesystem::path &path,
|
||||||
ProfileProperties &properties)
|
ProfileProperties &properties)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
serialization::read(reader, properties);
|
serialization::read(reader, "/common/properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.properties
|
// writes .osrm.properties
|
||||||
inline void writeProfileProperties(const boost::filesystem::path &path,
|
inline void writeProfileProperties(const boost::filesystem::path &path,
|
||||||
const ProfileProperties &properties)
|
const ProfileProperties &properties)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
serialization::write(writer, properties);
|
serialization::write(writer, "/common/properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EdgeBasedEdgeVector>
|
template <typename EdgeBasedEdgeVector>
|
||||||
@@ -83,13 +85,16 @@ void writeEdgeBasedGraph(const boost::filesystem::path &path,
|
|||||||
{
|
{
|
||||||
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
||||||
|
|
||||||
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
storage::tar::FileWriter writer(path, storage::tar::FileWriter::GenerateFingerprint);
|
||||||
|
|
||||||
writer.WriteElementCount64(number_of_edge_based_nodes);
|
writer.WriteElementCount64("/common/number_of_edge_based_nodes", 1);
|
||||||
storage::serialization::write(writer, edge_based_edge_list);
|
writer.WriteFrom("/common/number_of_edge_based_nodes", number_of_edge_based_nodes);
|
||||||
writer.WriteOne(connectivity_checksum);
|
storage::serialization::write(writer, "/common/edge_based_edge_list", edge_based_edge_list);
|
||||||
|
writer.WriteElementCount64("/common/connectivity_checksum", 1);
|
||||||
|
writer.WriteFrom("/common/connectivity_checksum", connectivity_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reads .osrm.ebg file
|
||||||
template <typename EdgeBasedEdgeVector>
|
template <typename EdgeBasedEdgeVector>
|
||||||
void readEdgeBasedGraph(const boost::filesystem::path &path,
|
void readEdgeBasedGraph(const boost::filesystem::path &path,
|
||||||
EdgeID &number_of_edge_based_nodes,
|
EdgeID &number_of_edge_based_nodes,
|
||||||
@@ -98,14 +103,14 @@ void readEdgeBasedGraph(const boost::filesystem::path &path,
|
|||||||
{
|
{
|
||||||
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
||||||
|
|
||||||
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
storage::tar::FileReader reader(path, storage::tar::FileReader::VerifyFingerprint);
|
||||||
|
|
||||||
number_of_edge_based_nodes = reader.ReadElementCount64();
|
reader.ReadInto("/common/number_of_edge_based_nodes", number_of_edge_based_nodes);
|
||||||
storage::serialization::read(reader, edge_based_edge_list);
|
storage::serialization::read(reader, "/common/edge_based_edge_list", edge_based_edge_list);
|
||||||
reader.ReadInto(connectivity_checksum);
|
reader.ReadInto("/common/connectivity_checksum", connectivity_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.nodes
|
// reads .osrm.nbg_nodes
|
||||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||||
inline void readNodes(const boost::filesystem::path &path,
|
inline void readNodes(const boost::filesystem::path &path,
|
||||||
CoordinatesT &coordinates,
|
CoordinatesT &coordinates,
|
||||||
@@ -114,14 +119,26 @@ inline void readNodes(const boost::filesystem::path &path,
|
|||||||
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||||
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
storage::serialization::read(reader, coordinates);
|
storage::serialization::read(reader, "/common/nbn_data/coordinates", coordinates);
|
||||||
util::serialization::read(reader, osm_node_ids);
|
util::serialization::read(reader, "/common/nbn_data/osm_node_ids", osm_node_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.nodes
|
// reads only coordinates from .osrm.nbg_nodes
|
||||||
|
template <typename CoordinatesT>
|
||||||
|
inline void readNodeCoordinates(const boost::filesystem::path &path, CoordinatesT &coordinates)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||||
|
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/common/nbn_data/coordinates", coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.nbg_nodes
|
||||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||||
inline void writeNodes(const boost::filesystem::path &path,
|
inline void writeNodes(const boost::filesystem::path &path,
|
||||||
const CoordinatesT &coordinates,
|
const CoordinatesT &coordinates,
|
||||||
@@ -130,48 +147,48 @@ inline void writeNodes(const boost::filesystem::path &path,
|
|||||||
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||||
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
storage::serialization::write(writer, coordinates);
|
storage::serialization::write(writer, "/common/nbn_data/coordinates", coordinates);
|
||||||
util::serialization::write(writer, osm_node_ids);
|
util::serialization::write(writer, "/common/nbn_data/osm_node_ids", osm_node_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.cnbg_to_ebg
|
// reads .osrm.cnbg_to_ebg
|
||||||
inline void readNBGMapping(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
|
inline void readNBGMapping(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
storage::serialization::read(reader, mapping);
|
storage::serialization::read(reader, "/common/cnbg_to_ebg", mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.cnbg_to_ebg
|
// writes .osrm.cnbg_to_ebg
|
||||||
inline void writeNBGMapping(const boost::filesystem::path &path,
|
inline void writeNBGMapping(const boost::filesystem::path &path,
|
||||||
const std::vector<NBGToEBG> &mapping)
|
const std::vector<NBGToEBG> &mapping)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
storage::serialization::write(writer, mapping);
|
storage::serialization::write(writer, "/common/cnbg_to_ebg", mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.datasource_names
|
// reads .osrm.datasource_names
|
||||||
inline void readDatasources(const boost::filesystem::path &path, Datasources &sources)
|
inline void readDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
serialization::read(reader, sources);
|
serialization::read(reader, "/common/data_sources_names", sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.datasource_names
|
// writes .osrm.datasource_names
|
||||||
inline void writeDatasources(const boost::filesystem::path &path, Datasources &sources)
|
inline void writeDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
serialization::write(writer, sources);
|
serialization::write(writer, "/common/data_sources_names", sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.geometry
|
// reads .osrm.geometry
|
||||||
@@ -181,10 +198,10 @@ inline void readSegmentData(const boost::filesystem::path &path, SegmentDataT &s
|
|||||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||||
"");
|
"");
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
serialization::read(reader, segment_data);
|
serialization::read(reader, "/common/segment_data", segment_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.geometry
|
// writes .osrm.geometry
|
||||||
@@ -194,10 +211,10 @@ inline void writeSegmentData(const boost::filesystem::path &path, const SegmentD
|
|||||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||||
"");
|
"");
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
serialization::write(writer, segment_data);
|
serialization::write(writer, "/common/segment_data", segment_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.ebg_nodes
|
// reads .osrm.ebg_nodes
|
||||||
@@ -208,10 +225,10 @@ inline void readNodeData(const boost::filesystem::path &path, NodeDataT &node_da
|
|||||||
std::is_same<EdgeBasedNodeDataView, NodeDataT>::value ||
|
std::is_same<EdgeBasedNodeDataView, NodeDataT>::value ||
|
||||||
std::is_same<EdgeBasedNodeDataExternalContainer, NodeDataT>::value,
|
std::is_same<EdgeBasedNodeDataExternalContainer, NodeDataT>::value,
|
||||||
"");
|
"");
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
serialization::read(reader, node_data);
|
serialization::read(reader, "/common/ebg_node_data", node_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.ebg_nodes
|
// writes .osrm.ebg_nodes
|
||||||
@@ -222,10 +239,10 @@ inline void writeNodeData(const boost::filesystem::path &path, const NodeDataT &
|
|||||||
std::is_same<EdgeBasedNodeDataView, NodeDataT>::value ||
|
std::is_same<EdgeBasedNodeDataView, NodeDataT>::value ||
|
||||||
std::is_same<EdgeBasedNodeDataExternalContainer, NodeDataT>::value,
|
std::is_same<EdgeBasedNodeDataExternalContainer, NodeDataT>::value,
|
||||||
"");
|
"");
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
serialization::write(writer, node_data);
|
serialization::write(writer, "/common/ebg_node_data", node_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.tls
|
// reads .osrm.tls
|
||||||
@@ -238,11 +255,11 @@ inline void readTurnLaneDescriptions(const boost::filesystem::path &path,
|
|||||||
"");
|
"");
|
||||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
storage::serialization::read(reader, turn_offsets);
|
storage::serialization::read(reader, "/common/turn_lanes/offsets", turn_offsets);
|
||||||
storage::serialization::read(reader, turn_masks);
|
storage::serialization::read(reader, "/common/turn_lanes/masks", turn_masks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.tls
|
// writes .osrm.tls
|
||||||
@@ -255,11 +272,40 @@ inline void writeTurnLaneDescriptions(const boost::filesystem::path &path,
|
|||||||
"");
|
"");
|
||||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||||
|
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
storage::serialization::write(writer, turn_offsets);
|
storage::serialization::write(writer, "/common/turn_lanes/offsets", turn_offsets);
|
||||||
storage::serialization::write(writer, turn_masks);
|
storage::serialization::write(writer, "/common/turn_lanes/masks", turn_masks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads .osrm.tld
|
||||||
|
template <typename TurnLaneDataT>
|
||||||
|
inline void readTurnLaneData(const boost::filesystem::path &path, TurnLaneDataT &turn_lane_data)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_same<typename TurnLaneDataT::value_type, util::guidance::LaneTupleIdPair>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/common/turn_lanes/data", turn_lane_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.tld
|
||||||
|
template <typename TurnLaneDataT>
|
||||||
|
inline void writeTurnLaneData(const boost::filesystem::path &path,
|
||||||
|
const TurnLaneDataT &turn_lane_data)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_same<typename TurnLaneDataT::value_type, util::guidance::LaneTupleIdPair>::value,
|
||||||
|
"");
|
||||||
|
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::write(writer, "/common/turn_lanes/data", turn_lane_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm.maneuver_overrides
|
// reads .osrm.maneuver_overrides
|
||||||
@@ -268,10 +314,13 @@ inline void readManeuverOverrides(const boost::filesystem::path &path,
|
|||||||
StorageManeuverOverrideT &maneuver_overrides,
|
StorageManeuverOverrideT &maneuver_overrides,
|
||||||
NodeSequencesT &node_sequences)
|
NodeSequencesT &node_sequences)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
storage::io::FileReader reader{path, fingerprint};
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
serialization::read(reader, maneuver_overrides, node_sequences);
|
storage::serialization::read(
|
||||||
|
reader, "/common/maneuver_overrides/overrides", maneuver_overrides);
|
||||||
|
storage::serialization::read(
|
||||||
|
reader, "/common/maneuver_overrides/node_sequences", node_sequences);
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes .osrm.maneuver_overrides
|
// writes .osrm.maneuver_overrides
|
||||||
@@ -279,10 +328,197 @@ inline void writeManeuverOverrides(const boost::filesystem::path &path,
|
|||||||
const std::vector<StorageManeuverOverride> &maneuver_overrides,
|
const std::vector<StorageManeuverOverride> &maneuver_overrides,
|
||||||
const std::vector<NodeID> &node_sequences)
|
const std::vector<NodeID> &node_sequences)
|
||||||
{
|
{
|
||||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
storage::io::FileWriter writer{path, fingerprint};
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
serialization::write(writer, maneuver_overrides, node_sequences);
|
storage::serialization::write(
|
||||||
|
writer, "/common/maneuver_overrides/overrides", maneuver_overrides);
|
||||||
|
storage::serialization::write(
|
||||||
|
writer, "/common/maneuver_overrides/node_sequences", node_sequences);
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.turn_weight_penalties
|
||||||
|
template <typename TurnPenaltyT>
|
||||||
|
inline void writeTurnWeightPenalty(const boost::filesystem::path &path,
|
||||||
|
const TurnPenaltyT &turn_penalty)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::write(writer, "/common/turn_penalty/weight", turn_penalty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read .osrm.turn_weight_penalties
|
||||||
|
template <typename TurnPenaltyT>
|
||||||
|
inline void readTurnWeightPenalty(const boost::filesystem::path &path, TurnPenaltyT &turn_penalty)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/common/turn_penalty/weight", turn_penalty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.turn_duration_penalties
|
||||||
|
template <typename TurnPenaltyT>
|
||||||
|
inline void writeTurnDurationPenalty(const boost::filesystem::path &path,
|
||||||
|
const TurnPenaltyT &turn_penalty)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::write(writer, "/common/turn_penalty/duration", turn_penalty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read .osrm.turn_weight_penalties
|
||||||
|
template <typename TurnPenaltyT>
|
||||||
|
inline void readTurnDurationPenalty(const boost::filesystem::path &path, TurnPenaltyT &turn_penalty)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/common/turn_penalty/duration", turn_penalty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes .osrm.restrictions
|
||||||
|
template <typename ConditionalRestrictionsT>
|
||||||
|
inline void writeConditionalRestrictions(const boost::filesystem::path &path,
|
||||||
|
const ConditionalRestrictionsT &conditional_restrictions)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
serialization::write(writer, "/common/conditional_restrictions", conditional_restrictions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read .osrm.restrictions
|
||||||
|
template <typename ConditionalRestrictionsT>
|
||||||
|
inline void readConditionalRestrictions(const boost::filesystem::path &path,
|
||||||
|
ConditionalRestrictionsT &conditional_restrictions)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
serialization::read(reader, "/common/conditional_restrictions", conditional_restrictions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads .osrm file which is a temporary file of osrm-extract
|
||||||
|
template <typename BarrierOutIter, typename TrafficSignalsOutIter, typename PackedOSMIDsT>
|
||||||
|
void readRawNBGraph(const boost::filesystem::path &path,
|
||||||
|
BarrierOutIter barriers,
|
||||||
|
TrafficSignalsOutIter traffic_signals,
|
||||||
|
std::vector<util::Coordinate> &coordinates,
|
||||||
|
PackedOSMIDsT &osm_node_ids,
|
||||||
|
std::vector<extractor::NodeBasedEdge> &edge_list,
|
||||||
|
std::vector<extractor::NodeBasedEdgeAnnotation> &annotations)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
auto number_of_nodes = reader.ReadElementCount64("/extractor/nodes");
|
||||||
|
coordinates.resize(number_of_nodes);
|
||||||
|
osm_node_ids.reserve(number_of_nodes);
|
||||||
|
auto index = 0;
|
||||||
|
auto decode = [&](const auto ¤t_node) {
|
||||||
|
coordinates[index].lon = current_node.lon;
|
||||||
|
coordinates[index].lat = current_node.lat;
|
||||||
|
osm_node_ids.push_back(current_node.node_id);
|
||||||
|
index++;
|
||||||
|
};
|
||||||
|
reader.ReadStreaming<extractor::QueryNode>("/extractor/nodes",
|
||||||
|
boost::make_function_output_iterator(decode));
|
||||||
|
|
||||||
|
reader.ReadStreaming<NodeID>("/extractor/barriers", barriers);
|
||||||
|
|
||||||
|
reader.ReadStreaming<NodeID>("/extractor/traffic_lights", traffic_signals);
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/extractor/edges", edge_list);
|
||||||
|
storage::serialization::read(reader, "/extractor/annotations", annotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NameTableT>
|
||||||
|
void readNames(const boost::filesystem::path &path, NameTableT &table)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
serialization::read(reader, "/common/names", table);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NameTableT>
|
||||||
|
void writeNames(const boost::filesystem::path &path, const NameTableT &table)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
serialization::write(writer, "/common/names", table);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NodeWeigtsVectorT>
|
||||||
|
void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVectorT &weights)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NodeWeigtsVectorT, typename NodeDurationsVectorT>
|
||||||
|
void readEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
||||||
|
NodeWeigtsVectorT &weights,
|
||||||
|
NodeDurationsVectorT &durations)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
|
||||||
|
storage::serialization::read(reader, "/extractor/edge_based_node_durations", durations);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename NodeWeigtsVectorT, typename NodeDurationsVectorT>
|
||||||
|
void writeEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
|
||||||
|
const NodeWeigtsVectorT &weights,
|
||||||
|
const NodeDurationsVectorT &durations)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights);
|
||||||
|
storage::serialization::write(writer, "/extractor/edge_based_node_durations", durations);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RTreeT>
|
||||||
|
void writeRamIndex(const boost::filesystem::path &path, const RTreeT &rtree)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
util::serialization::write(writer, "/common/rtree", rtree);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RTreeT> void readRamIndex(const boost::filesystem::path &path, RTreeT &rtree)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
util::serialization::read(reader, "/common/rtree", rtree);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EdgeListT>
|
||||||
|
void writeCompressedNodeBasedGraph(const boost::filesystem::path &path, const EdgeListT &edge_list)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
|
||||||
|
storage::tar::FileWriter writer{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::write(writer, "/extractor/cnbg", edge_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EdgeListT>
|
||||||
|
void readCompressedNodeBasedGraph(const boost::filesystem::path &path, EdgeListT &edge_list)
|
||||||
|
{
|
||||||
|
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
|
||||||
|
storage::tar::FileReader reader{path, fingerprint};
|
||||||
|
|
||||||
|
storage::serialization::read(reader, "/extractor/cnbg", edge_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user