Compare commits

..

19 Commits

Author SHA1 Message Date
karenzshea 020c0d1c11 5.17.0 2018-04-19 12:03:55 +02:00
Patrick Niklaus 1bc18d6275 Bump OSRM verison to 5.17 RC5 2018-04-17 15:56:42 +00:00
Huyen Chau Nguyen 4334810c71 add changelog entry 2018-04-16 09:40:49 +00:00
Huyen Chau Nguyen a307371c27 adjust tests to changes 2018-04-16 09:40:49 +00:00
Huyen Chau Nguyen 5351a258a9 refactor bike profile 2018-04-16 09:40:49 +00:00
Huyen Chau Nguyen adadb45f02 make primaries and secondaries more dangerous
only apply oneway safety considerations on primaries

re-adjust primary and secondary safeties
2018-04-16 09:40:49 +00:00
Patrick Niklaus adee18468c Bump RC to 4 2018-04-13 13:23:35 +00:00
Patrick Niklaus 9a9abf4c11 Remove double log printing 2018-04-13 10:14:23 +00:00
karenzshea 331eeca4c1 empty list of shmem regions if none found 2018-04-13 10:12:20 +00:00
karenzshea f8d6e4750a log err instead of throwing when no shmem regions found 2018-04-13 10:12:05 +00:00
Michael Krasnyk cf505386f9 Bump version to 5.17.0-rc.3 2018-04-12 10:12:28 +02:00
Michael Krasnyk e346e9ae07 Avoid using signed integers for edge IDs 2018-04-12 10:11:52 +02:00
Michael Krasnyk ad37fcce2d Bump version to 5.17.0-rc.2 2018-04-10 21:17:33 +02:00
Patrick Niklaus 0e19f07c3c Use byte based tar size encoding above 8GB 2018-04-10 21:14:29 +02:00
Patrick Niklaus 59c0795c7f Add test case for writing and reading huge tar file
This test case is disabled by default because it needs too much storage,
but serves as documentation for the future.
2018-04-10 21:14:27 +02:00
Michael Krasnyk 3653e51f67 Use base-256 encoding for files larger 68G
Reference:
http://lists.busybox.net/pipermail/busybox/2011-May/075596.html
2018-04-10 21:14:25 +02:00
Michael Krasnyk 8c24507f8f Use 12 octal digits in mtar_raw_header_t::size 2018-04-10 21:14:23 +02:00
Michael Krasnyk 3e444777e0 Fix mtar file size truncation to 4G 2018-04-10 21:14:20 +02:00
Patrick Niklaus 670cd8813c Bump OSRM version 2018-04-09 13:13:44 +00:00
927 changed files with 7898 additions and 72997 deletions
+2 -58
View File
@@ -13,9 +13,9 @@ notifications:
branches: branches:
only: only:
- master - master
- "5.20"
# enable building tags # enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/ - /^v\d+\.\d+(\.\d+)?(-\S*)?$/
- "5.17"
cache: cache:
yarn: true yarn: true
@@ -155,14 +155,6 @@ matrix:
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libboost-all-dev', 'ccache'] packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
- os: osx
osx_image: xcode9.2
compiler: "mason-osx-release-node-10"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="10"
after_success:
- ./scripts/travis/publish.sh
- os: osx - os: osx
osx_image: xcode9.2 osx_image: xcode9.2
compiler: "mason-osx-release-node-8" compiler: "mason-osx-release-node-8"
@@ -285,54 +277,6 @@ matrix:
after_success: after_success:
- ./scripts/travis/publish.sh - ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-10-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-10-mason-linux-debug"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
before_install: before_install:
- source $NVM_DIR/nvm.sh - source $NVM_DIR/nvm.sh
- nvm install $NODE - nvm install $NODE
@@ -353,7 +297,7 @@ before_install:
fi fi
- | - |
if [[ ! -f $(which yarn) ]]; then if [[ ! -f $(which yarn) ]]; then
npm install -g yarn@1.11.1 npm install -g yarn
fi fi
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)") - export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off") - export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
-47
View File
@@ -1,50 +1,3 @@
# 5.20.0
- Changes from 5.19.0:
- Table:
- CHANGED: switch to pre-calculated distances for table responses for large speedup and 10% memory increase. [#5251](https://github.com/Project-OSRM/osrm-backend/pull/5251)
- ADDED: new parameter `fallback_speed` which will fill `null` cells with estimated value [#5257](https://github.com/Project-OSRM/osrm-backend/pull/5257)
- CHANGED: Remove API check for matrix sources/destination length to be less than or equal to coordinates length. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5289)
- FIXED: Fix crashing bug when using fallback_speed parameter with more sources than destinations. [#5291](https://github.com/Project-OSRM/osrm-backend/pull/5291)
- Features:
- ADDED: direct mmapping of datafiles is now supported via the `--mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- ADDED: Now publishing Node 10.x LTS binary modules [#5246](https://github.com/Project-OSRM/osrm-backend/pull/5246)
- Windows:
- FIXED: Windows builds again. [#5249](https://github.com/Project-OSRM/osrm-backend/pull/5249)
# 5.19.0
- Changes from 5.18.0:
- Optimizations:
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
- ADDED: Node bindings can return pre-rendered JSON buffer. [#5189](https://github.com/Project-OSRM/osrm-backend/pull/5189)
- Profiles:
- CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [#5076
](https://github.com/Project-OSRM/osrm-backend/pull/5076/)
- CHANGED: Foot profile now blacklists barriers instead of whitelisting them [#5077
](https://github.com/Project-OSRM/osrm-backend/pull/5077/)
- CHANGED: Support maxlength and maxweight in car profile [#5101](https://github.com/Project-OSRM/osrm-backend/pull/5101]
- Bugfixes:
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
- Misc:
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)
# 5.18.0
- 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 # 5.17.0
- Changes from 5.16.0: - Changes from 5.16.0:
- Bugfixes: - Bugfixes:
+13 -24
View File
@@ -167,7 +167,7 @@ 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:MICROTAR> $<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:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>) 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:MICROTAR> $<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>)
@@ -416,30 +416,11 @@ 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
@@ -573,6 +554,14 @@ else()
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR}) include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
endif() endif()
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})
add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c")
set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON)
# 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
if(ENABLE_CCACHE AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")) if(ENABLE_CCACHE AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
find_program(CCACHE_FOUND ccache) find_program(CCACHE_FOUND ccache)
@@ -873,4 +862,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()
+1 -1
View File
@@ -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 or distances of the fastest route between all pairs of supplied coordinates - Table - Computes the duration 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
+1 -1
View File
@@ -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 --tags ~@ch --require features/support --require features/step_definitions -f progress' mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
}; };
+8 -118
View File
@@ -222,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. 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. Computes the duration of the fastest route between all pairs of supplied coordinates.
```endpoint ```endpoint
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&{destinations}=[{elem}...]&annotations={duration|distance|duration,distance} GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]
``` ```
**Options** **Coordinates**
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:
@@ -236,9 +236,6 @@ 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. |
|fallback_speed|`double > 0`|If no route found between a source/destination pair, calculate the as-the-crow-flies distance, then use this speed to estimate duration.|
|fallback_coordinate|`input` (default), or `snapped`| When using a `fallback_speed`, use the user-supplied coordinate (`input`), or the snapped location (`snapped`) for calculating distances.|
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;
@@ -256,23 +253,14 @@ sources=0;5;7&destinations=5;1;4;2;3;6
#### Example Request #### Example Request
```curl ```curl
# Returns a 3x3 duration matrix: # Returns a 3x3 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 duration matrix # Returns a 1x3 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 duration matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`: # Returns a asymmetric 3x2 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**
@@ -280,115 +268,17 @@ curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397
- `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.
+21 -46
View File
@@ -25,9 +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)?** *DEPRECATED* - `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.
Old behaviour: Path to a file on disk to store the memory using mmap. Current behaviour: setting this value is the same as setting `mmap_memory: true`.
- `options.mmap_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Map on-disk files to virtual memory addresses (mmap), rather than loading into RAM.
- `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).
@@ -58,7 +56,7 @@ Returns the fastest route between two or more coordinates while visiting the way
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. - `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`. - `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
`null`/`true`/`false` `null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -90,7 +88,7 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned. - `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`) Must be an integer greater than or equal to `1`. (optional, default `1`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`. - `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -112,8 +110,8 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
### table ### table
Computes duration table for the given locations. Allows for both symmetric and asymmetric Computes duration tables for the given locations. Allows for both symmetric and asymmetric
tables. Optionally returns distance table. tables.
**Parameters** **Parameters**
@@ -129,9 +127,7 @@ tables. Optionally returns distance table.
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < - `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
#coordinates`) to use location with given index as destination. Default is to use all. #coordinates`) to use location with given index as destination. Default is to use all.
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`. - `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `options.fallback_speed` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Replace `null` responses in result with as-the-crow-flies estimates based on `fallback_speed`. Value is in metres/second. - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `options.fallback_coordinate` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Either `input` (default) or `snapped`. If using a `fallback_speed`, use either the user-supplied coordinate (`input`), or the snapped coordinate (`snapped`) for calculating the as-the-crow-flies diestance between two points.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -171,7 +167,7 @@ and what weights they have applied.
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like - `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) [wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/). and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -208,7 +204,7 @@ if they can not be matched successfully.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`. - `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
- `options.gaps` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore` (optional, default `split`). - `options.gaps` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore` (optional, default `split`).
- `options.tidy` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Allows the input track modification to obtain better matching quality for noisy tracks (optional, default `false`). - `options.tidy` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Allows the input track modification to obtain better matching quality for noisy tracks (optional, default `false`).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -272,7 +268,7 @@ Right now, the following combinations are possible:
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`) - `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`) - `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`. - `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -301,39 +297,18 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
2) `waypoint_index`: index of the point in the trip. 2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace. **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
## Plugin behaviour
All plugins support a second additional object that is available to configure some NodeJS specific behaviours.
- `plugin_config` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `plugin_config.format` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The format of the result object to various API calls. Valid options are `object` (default), which returns a standard Javascript object, as described above, and `json_buffer`, which will return a NodeJS **[Buffer](https://nodejs.org/api/buffer.html)** object, containing a JSON string. The latter has the advantage that it can be immediately serialized to disk/sent over the network, and the generation of the string is performed outside the main NodeJS event loop. This option is ignored by the `tile` plugin.
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
};
osrm.route(options, { format: "json_buffer" }, function(err, response) {
if (err) throw err;
console.log(response.toString("utf-8"));
});
```
## Responses ## Responses
Responses
### Route ### Route
Represents a route through (potentially multiple) waypoints. Represents a route through (potentially multiple) waypoints.
**Parameters** **Parameters**
- **documentation** in - `exteral` **documentation** in
[`osrm-backend`](../http.md#route-object) [`osrm-backend`](../http.md#route)
### RouteLeg ### RouteLeg
@@ -341,8 +316,8 @@ Represents a route between two waypoints.
**Parameters** **Parameters**
- **documentation** in - `exteral` **documentation** in
[`osrm-backend`](../http.md#routeleg-object) [`osrm-backend`](../http.md#routeleg)
### RouteStep ### RouteStep
@@ -351,15 +326,15 @@ single way to the subsequent step.
**Parameters** **Parameters**
- **documentation** in - `exteral` **documentation** in
[`osrm-backend`](../http.md#routestep-object) [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
### StepManeuver ### StepManeuver
**Parameters** **Parameters**
- **documentation** in - `exteral` **documentation** in
[`osrm-backend`](../http.md#stepmaneuver-object) [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
### Waypoint ### Waypoint
@@ -367,5 +342,5 @@ Object used to describe waypoint on a route.
**Parameters** **Parameters**
- **documentation** in - `exteral` **documentation** in
[`osrm-backend`](../http.md#waypoint-object) [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
+5 -5
View File
@@ -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 4. A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 2.
### Library files ### 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.
@@ -138,7 +138,7 @@ Given an OpenStreetMap way, the `process_way` function will either return nothin
Argument | Description Argument | Description
---------|------------------------------------------------------- ---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`. profile | The configuration table you returned in `setup`.
way | The input way to process (read-only). node | The input way to process (read-only).
result | The output that you will modify. result | The output that you will modify.
relations| Storage of relations to access relations, where `way` is a member. relations| Storage of relations to access relations, where `way` is a member.
@@ -199,7 +199,7 @@ source.lon | Read | Float | Co-ordinates of segment start
source.lat | Read | Float | "" source.lat | Read | Float | ""
target.lon | Read | Float | Co-ordinates of segment end target.lon | Read | Float | Co-ordinates of segment end
target.lat | Read | Float | "" target.lat | Read | Float | ""
distance | Read | Float | Length of segment target.distance | Read | Float | Length of segment
weight | Read/write | Float | Routing weight for this segment weight | Read/write | Float | Routing weight for this segment
duration | Read/write | Float | Duration for this segment duration | Read/write | Float | Duration for this segment
@@ -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 the target a restricted access road? (See definition in `process_way`) target_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
target_mode | Read | Enum | Travel mode after the turn. Defined in `include/extractor/travel_mode.hpp` target_mode | Read | Enum | Travel mode before 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)
+3 -3
View File
@@ -43,9 +43,9 @@ 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 `package.json` on branch `x.y` has been committed. 3. 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:) 4. 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. 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.
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 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. Push tags and commits: `git push; git push --tags` 7. Push tags and commits: `git push; git push --tags`
8. On https://github.com/Project-OSRM/osrm-backend/releases press `Draft a new release`, 8. On https://github.com/Project-OSRM/osrm-backend/releases press `Draft a new release`,
+1 -1
View File
@@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x | | entrance | x |
| wall | | | wall | |
| fence | | | fence | |
| some_tag | x | | some_tag | |
| block | x | | block | x |
Scenario: Bike - Access tag trumphs barriers Scenario: Bike - Access tag trumphs barriers
-92
View File
@@ -1,92 +0,0 @@
@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)],[()],[()] |
-55
View File
@@ -1,55 +0,0 @@
@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 |
-19
View File
@@ -48,22 +48,3 @@ Feature: Car - Handle physical limitation
| primary | | none | x | | primary | | none | x |
| primary | | no-sign | x | | primary | | no-sign | x |
| primary | | unsigned | x | | primary | | unsigned | x |
Scenario: Car - Limited by length
Then routability should be
| highway | maxlength | bothw |
| primary | | x |
| primary | 1 | |
| primary | 5 | x |
| primary | unsigned | x |
Scenario: Car - Limited by weight
Then routability should be
| highway | maxweight | bothw |
| primary | | x |
| primary | 1 | |
| primary | 3.5 | x |
| primary | 35000 kg | x |
| primary | 8.9t | x |
| primary | 0.1 lbs | |
| primary | unsigned | x |
+1 -1
View File
@@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x | | entrance | x |
| wall | | | wall | |
| fence | | | fence | |
| some_tag | x | | some_tag | |
| block | x | | block | x |
Scenario: Foot - Access tag trumphs barriers Scenario: Foot - Access tag trumphs barriers
@@ -1209,33 +1209,3 @@ Feature: Simple Turns
| a | c | knob,knob | depart,arrive | | a | c | knob,knob | depart,arrive |
| d | e | soph,soph | depart,arrive | | d | e | soph,soph | depart,arrive |
| d | a | soph,knob,knob | depart,turn left,arrive | | d | a | soph,knob,knob | depart,turn left,arrive |
# https://www.openstreetmap.org/node/30797565
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 | turns |
| d | c | ,, | depart,turn right,arrive |
+3 -53
View File
@@ -84,47 +84,7 @@ class OSRMDirectLoader extends OSRMBaseLoader {
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd)); throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
} }
}); });
callback();
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
}
};
class OSRMmmapLoader extends OSRMBaseLoader {
constructor (scope) {
super(scope);
}
load (inputFile, callback) {
this.inputFile = inputFile;
this.shutdown(() => {
this.launch(callback);
});
}
osrmUp (callback) {
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
const command_arguments = util.format('%s -p %d -i %s -a %s --mmap', 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) => {
if (err && err.signal !== 'SIGINT') {
this.child = null;
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
}
});
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
} }
}; };
@@ -175,32 +135,22 @@ class OSRMLoader {
this.scope = scope; this.scope = scope;
this.sharedLoader = new OSRMDatastoreLoader(this.scope); this.sharedLoader = new OSRMDatastoreLoader(this.scope);
this.directLoader = new OSRMDirectLoader(this.scope); this.directLoader = new OSRMDirectLoader(this.scope);
this.mmapLoader = new OSRMmmapLoader(this.scope);
this.method = scope.DEFAULT_LOAD_METHOD; this.method = scope.DEFAULT_LOAD_METHOD;
} }
load (inputFile, callback) { load (inputFile, callback) {
if (!this.loader) {
this.loader = {shutdown: (cb) => cb() };
}
if (this.method === 'datastore') { if (this.method === 'datastore') {
this.loader.shutdown((err) => { this.directLoader.shutdown((err) => {
if (err) return callback(err); if (err) return callback(err);
this.loader = this.sharedLoader; this.loader = this.sharedLoader;
this.sharedLoader.load(inputFile, callback); this.sharedLoader.load(inputFile, callback);
}); });
} else if (this.method === 'directly') { } else if (this.method === 'directly') {
this.loader.shutdown((err) => { this.sharedLoader.shutdown((err) => {
if (err) return callback(err); if (err) return callback(err);
this.loader = this.directLoader; this.loader = this.directLoader;
this.directLoader.load(inputFile, callback); this.directLoader.load(inputFile, callback);
}); });
} else if (this.method === 'mmap') {
this.loader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.mmapLoader;
this.mmapLoader.load(inputFile, callback);
});
} else { } else {
callback(new Error('*** Unknown load method ' + method)); callback(new Error('*** Unknown load method ' + method));
} }
+60 -74
View File
@@ -1,88 +1,74 @@
var util = require('util'); var util = require('util');
module.exports = function () { module.exports = function () {
const durationsRegex = new RegExp(/^I request a travel time matrix I should get$/); this.When(/^I request a travel time matrix I should get$/, (table, callback) => {
const distancesRegex = new RegExp(/^I request a travel distance matrix I should get$/); var NO_ROUTE = 2147483647; // MAX_INT
const DURATIONS_NO_ROUTE = 2147483647; // MAX_INT var tableRows = table.raw();
const DISTANCES_NO_ROUTE = 3.40282e+38; // MAX_FLOAT
this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', callback);}.bind(this)); if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', callback);}.bind(this));
};
const durationsParse = function(v) { return isNaN(parseInt(v)); }; var waypoints = [],
const distancesParse = function(v) { return isNaN(parseFloat(v)); }; 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]);
function tableParse(table, noRoute, annotation, callback) { if (symmetric) {
columnHeaders.forEach((nodeName) => {
const parse = annotation == 'distances' ? distancesParse : durationsParse; var node = this.findNodeByName(nodeName);
const params = this.queryParams; if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
params.annotations = annotation == 'distances' ? 'distance' : 'duration'; waypoints.push({ coord: node, type: 'loc' });
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 testRow = (row, ri, cb) => { var actual = [];
for (var k in result[ri]) { actual.push(table.headers);
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
result[ri][k] = row[k]; this.reprocessAndLoadData((e) => {
} else if (row[k] === '' && result[ri][k] === noRoute) { if (e) return callback(e);
result[ri][k] = ''; // compute matrix
} else { var params = this.queryParams;
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);
});
}); });
}); });
} };
+1 -7
View File
@@ -21,8 +21,7 @@ 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,
@@ -106,11 +105,6 @@ 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;
} }
+2 -2
View File
@@ -32,7 +32,7 @@ module.exports = function () {
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';
this.DEFAULT_INPUT_FORMAT = 'osm'; this.DEFAULT_INPUT_FORMAT = 'osm';
this.DEFAULT_LOAD_METHOD = process.argv[process.argv.indexOf('-m') +1].match('mmap') ? 'mmap' : 'datastore'; this.DEFAULT_LOAD_METHOD = 'datastore';
this.DEFAULT_ORIGIN = [1,1]; this.DEFAULT_ORIGIN = [1,1];
this.OSM_USER = 'osrm'; this.OSM_USER = 'osrm';
this.OSM_UID = 1; this.OSM_UID = 1;
@@ -80,7 +80,7 @@ module.exports = function () {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.info(util.format('Node Version', process.version)); console.info(util.format('Node Version', process.version));
if (parseInt(process.version.match(/v(\d+)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests'); if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
fs.exists(this.TEST_PATH, (exists) => { fs.exists(this.TEST_PATH, (exists) => {
if (exists) if (exists)
+1 -1
View File
@@ -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) => {
-19
View File
@@ -226,22 +226,3 @@ 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 |
+180 -483
View File
@@ -1,142 +1,29 @@
@matrix @testbot @matrix @testbot
Feature: Basic Distance Matrix Feature: Basic Distance Matrix
# note that results of travel distance are in metres # note that results are travel time, specified in 1/10th of seconds
# 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 distance matrix of small grid
Scenario: Testbot - Travel time matrix of minimal network
Given the node map Given the node map
""" """
a b c a b
d e f
""" """
And the ways And the ways
| nodes | | nodes |
| abc | | ab |
| def |
| ad |
| be |
| cf |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | e | f | | | a | b |
| a | 0 | 100.1 | 199.5 | 299.5 | | a | 0 | 10 |
| b | 100.1 | 0 | 99.4 | 199.5 | | b | 10 | 0 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
Scenario: Testbot - Travel distance matrix of minimal network exact distances Scenario: Testbot - Travel time matrix with different way speeds
Given the node map
"""
a z
b
c
d
"""
And the ways
| nodes |
| az |
| zbcd |
When I request a travel distance matrix I should get
| | a | z | b | c | d |
| a | 0 | 100.1 | 199.5 | 298.9 | 398.3 |
| z | 100.1 | 0 | 99.4 | 198.8 | 298.2 |
| b | 199.5 | 99.4 | 0 | 99.4 | 198.8 |
| c | 298.9 | 198.8 | 99.4 | 0 | 99.4 |
| d | 398.3 | 298.2 | 198.8 | 99.4 | 0 |
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 | 298.9 | 99.4 | 199.5 |
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
@@ -148,25 +35,40 @@ Feature: Basic Distance Matrix
| bc | secondary | | bc | secondary |
| cd | tertiary | | cd | tertiary |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | c | d | | | a | b | c | d |
| a | 0 | 100.1 | 200.1 | 300.2 | | a | 0 | 10 | 30 | 60 |
| b | 100.1 | 0 | 100.1 | 200.1 | | b | 10 | 0 | 20 | 50 |
| c | 200.1 | 100.1 | 0 | 100.1 | | c | 30 | 20 | 0 | 30 |
| d | 300.2 | 200.1 | 100.1 | 0 | | d | 60 | 50 | 30 | 0 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | c | d | | | a | b | c | d |
| a | 0 | 100.1 | 200.1 | 300.2 | | a | 0 | 10 | 30 | 60 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | | | a |
| a | 0 | | a | 0 |
| b | 100.1 | | b | 10 |
| c | 200.1 | | c | 30 |
| d | 300.2 | | d | 60 |
Scenario: Testbot - Travel distance matrix of small grid Scenario: Testbot - Travel time matrix with fuzzy match
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
@@ -181,14 +83,14 @@ Feature: Basic Distance Matrix
| be | | be |
| cf | | cf |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | e | f | | | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 | | a | 0 | 10 | 20 | 30 |
| b | 100.1 | 0 | 99.4 | 199.5 | | b | 10 | 0 | 10 | 20 |
| e | 199.5 | 99.4 | 0 | 100.1 | | e | 20 | 10 | 0 | 10 |
| f | 299.5 | 199.5 | 100.1 | 0 | | f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel distance matrix of network with unroutable parts Scenario: Testbot - Travel time matrix of network with unroutable parts
Given the node map Given the node map
""" """
a b a b
@@ -198,12 +100,12 @@ Feature: Basic Distance Matrix
| nodes | oneway | | nodes | oneway |
| ab | yes | | ab | yes |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | | | a | b |
| a | 0 | 100.1 | | a | 0 | 10 |
| b | | 0 | | b | | 0 |
Scenario: Testbot - Travel distance matrix of network with oneways Scenario: Testbot - Travel time matrix of network with oneways
Given the node map Given the node map
""" """
x a b y x a b y
@@ -216,14 +118,14 @@ Feature: Basic Distance Matrix
| xa | | | xa | |
| by | | | by | |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | x | y | d | e | | | x | y | d | e |
| x | 0 | 300.2 | 399.6 | 299.5 | | x | 0 | 30 | 40 | 30 |
| y | 499 | 0 | 299.5 | 199.5 | | y | 50 | 0 | 30 | 20 |
| d | 199.5 | 299.5 | 0 | 298.9 | | d | 20 | 30 | 0 | 30 |
| e | 299.5 | 399.6 | 100.1 | 0 | | e | 30 | 40 | 10 | 0 |
Scenario: Testbot - Rectangular travel distance matrix Scenario: Testbot - Rectangular travel time matrix
Given the node map Given the node map
""" """
a b c a b c
@@ -238,57 +140,51 @@ Feature: Basic Distance Matrix
| be | | be |
| cf | | cf |
When I route I should get When I request a travel time matrix I should get
| from | to | distance | | | a | b | e | f |
| e | a | 200m | | a | 0 | 10 | 20 | 30 |
| e | b | 100m |
| f | a | 299.9m |
| f | b | 200m |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | e | f | | | a |
| a | 0 | 100.1 | 199.5 | 299.5 | | a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | | | a | b | e | f |
| a | 0 | | a | 0 | 10 | 20 | 30 |
| b | 100.1 | | b | 10 | 0 | 10 | 20 |
| e | 199.5 |
| f | 299.5 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | e | f | | | a | b |
| a | 0 | 100.1 | 199.5 | 299.5 | | a | 0 | 10 |
| b | 100.1 | 0 | 99.4 | 199.5 | | b | 10 | 0 |
| e | 20 | 10 |
| f | 30 | 20 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | | | a | b | e | f |
| a | 0 | 100.1 | | a | 0 | 10 | 20 | 30 |
| b | 100.1 | 0 | | b | 10 | 0 | 10 | 20 |
| e | 199.5 | 99.4 | | e | 20 | 10 | 0 | 10 |
| f | 299.5 | 199.5 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | e | f | | | a | b | e |
| a | 0 | 100.1 | 199.5 | 299.5 | | a | 0 | 10 | 20 |
| b | 100.1 | 0 | 99.4 | 199.5 | | b | 10 | 0 | 10 |
| e | 199.5 | 99.4 | 0 | 100.1 | | e | 20 | 10 | 0 |
| f | 30 | 20 | 10 |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | e | | | a | b | e | f |
| a | 0 | 100.1 | 199.5 | | a | 0 | 10 | 20 | 30 |
| b | 100.1 | 0 | 99.4 | | b | 10 | 0 | 10 | 20 |
| e | 199.5 | 99.4 | 0 | | e | 20 | 10 | 0 | 10 |
| f | 299.5 | 199.5 | 100.1 | | f | 30 | 20 | 10 | 0 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
Scenario: Testbot - Travel distance 3x2 matrix Scenario: Testbot - Travel time 3x2 matrix
Given the node map Given the node map
""" """
a b c a b c
@@ -303,11 +199,10 @@ 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 | | b | e | f |
| | b | e | f | | a | 10 | 20 | 30 |
| a | 100.1 | 199.5 | 299.5 | | b | 0 | 10 | 20 |
| b | 0 | 99.4 | 199.5 |
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
@@ -326,10 +221,10 @@ Feature: Basic Distance Matrix
| da | | da |
| fg | | fg |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | f | g | | | f | g |
| f | 0 | 298.2 | | f | 0 | 30 |
| g | 298.2 | 0 | | g | 30 | 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
@@ -349,25 +244,14 @@ Feature: Basic Distance Matrix
| fg | | fg |
| hi | | hi |
When I route I should get When I request a travel time matrix I should get
| from | to | distance | | | f | g | h | i |
| f | g | 300m | | f | 0 | 30 | 0 | 30 |
| f | i | 300m | | g | 30 | 0 | 30 | 0 |
| g | f | 300m | | h | 0 | 30 | 0 | 30 |
| g | h | 300m | | i | 30 | 0 | 30 | 0 |
| h | g | 300m |
| h | i | 300m |
| i | f | 300m |
| i | h | 300m |
When I request a travel distance matrix I should get Scenario: Testbot - Travel time matrix with loops
| | f | g | h | i |
| f | 0 | 298.2 | 0 | 298.2 |
| g | 298.2 | 0 | 298.2 | 0 |
| h | 0 | 298.2 | 0 | 298.2 |
| i | 298.2 | 0 | 298.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
@@ -381,15 +265,14 @@ Feature: Basic Distance Matrix
| cd | yes | | cd | yes |
| da | yes | | da | yes |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 | | | 1 | 2 | 3 | 4 |
| 1 | 0 | 100.1 | 399.6 | 499.7 | | 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
| 2 | 699.1 | 0 | 299.5 | 399.6 | | 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
| 3 | 399.6 | 499.7 | 0 | 100.1 | | 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
| 4 | 299.5 | 399.6 | 699.1 | 0 | | 4 | 30 +-1 | 40 +-1 | 70 +-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')
@@ -418,19 +301,20 @@ Feature: Basic Distance Matrix
""" """
And the ways And the ways
| nodes | | nodes |
| abcd | | abcd |
| ce | | ce |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | c | d | e | | | a | b | c | d | e |
| a | 0 | 100.1 | 200.1 | 300.2 | 398.9 | | a | 0 | 11 | 22 | 33 | 33 |
| b | 100.1 | 0 | 100.1 | 200.1 | 298.9 | | b | 11 | 0 | 11 | 22 | 22 |
| c | 200.1 | 100.1 | 0 | 100.1 | 198.8 | | c | 22 | 11 | 0 | 11 | 11 |
| d | 300.2 | 200.1 | 100.1 | 0 | 298.9 | | d | 33 | 22 | 11 | 0 | 22 |
| e | 398.9 | 298.9 | 198.8 | 298.9 | 0 | | e | 33 | 22 | 11 | 22 | 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')
@@ -466,249 +350,62 @@ Feature: Basic Distance Matrix
| dc | yes | | dc | yes |
| ca | yes | | ca | yes |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 1096.7 | 298.9 | 199.5 | 598.4 | 498.3 | 897.3 | 797.9 | | 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
| 2 | 100.1 | 0 | 398.9 | 299.5 | 698.5 | 598.4 | 997.3 | 897.9 | | 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
| 3 | 897.9 | 797.9 | 0 | 1097.4 | 299.5 | 199.5 | 598.4 | 499 | | 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
| 4 | 997.3 | 897.3 | 99.4 | 0 | 398.9 | 298.9 | 697.8 | 598.4 | | 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
| 5 | 598.4 | 498.3 | 897.3 | 797.9 | 0 | 1096.7 | 298.9 | 199.5 | | 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
| 6 | 698.5 | 598.4 | 997.3 | 897.9 | 100.1 | 0 | 398.9 | 299.5 | | 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 299.5 | 199.5 | 598.4 | 499 | 897.9 | 797.9 | 0 | 1097.4 | | 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 398.9 | 298.9 | 697.8 | 598.4 | 997.3 | 897.3 | 99.4 | 0 | | 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
When I request a travel distance matrix I should get
| | 1 |
| 1 | 0 |
| 2 | 100.1 |
| 3 | 897.9 |
| 4 | 997.3 |
| 5 | 598.4 |
| 6 | 698.5 |
| 7 | 299.5 |
| 8 | 398.9 |
Scenario: Testbot - Travel distance matrix with ties Scenario: Testbot - Travel time matrix with ties
Given the node map 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 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 | 20s | 20 | | a | c | ac,ac | 200m | 5s | 5 |
When I route I should get When I request a travel time matrix I should get
| from | to | route | distance | | | a | b | c | d |
| a | b | ab,ab | 450m | | a | 0 | 1 | 5 | 10 |
| a | c | ac,ac | 200m |
| a | d | ac,dc,dc | 499.9m |
When I request a travel distance matrix I should get When I request a travel time matrix I should get
| | a | b | c | d | | | a |
| a | 0 | 450.3 | 198.8 | 499 | | a | 0 |
| b | 1 |
When I request a travel distance matrix I should get | c | 15 |
| | a | | d | 10 |
| a | 0 |
| b | 450.3 |
| c | 198.8 |
| d | 499 |
When I request a travel distance matrix I should get
| | a | c |
| a | 0 | 198.8 |
| c | 198.8 | 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.7 | 2001.4 | 3002.1 |
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.2 | 650.5 | 1930.6 | 1533 |
| b | 759 | 0 | 200.1 | 550.4 | 1830.5 | 1432.9 |
| c | 558.8 | 658.9 | 0 | 350.3 | 1630.4 | 1232.8 |
| d | 1478.9 | 1579 | 1779.1 | 0 | 1280.1 | 882.5 |
| e | 198.8 | 298.9 | 499 | 710.3 | 0 | 1592.8 |
| f | 596.4 | 696.5 | 896.6 | 1107.9 | 397.6 | 0 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
| b | 300.2 | 0 | 600.5 | 1200.9 |
| f | 900.7 | 600.5 | 0 | 302.2 |
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
Scenario: Testbot - Filling in noroutes with estimates - use input coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | input |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
| b | 300.2 | 0 | 600.5 | 1200.9 |
| f | 900.7 | 600.5 | 0 | 302.2 |
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1200.9 |
| b | 300.2 | 0 | 600.5 | 900.7 |
| f | 900.7 | 600.5 | 0 | 302.2 |
| 1 | 1200.9 | 900.7 | 300.2 | 0 |
Scenario: Testbot - Asymetric fallback_speed - more sources than destinations
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1200.9 |
Scenario: Testbot - Asymetric fallback_speed - more destinations than sources
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1200.9 |
-583
View File
@@ -1,583 +0,0 @@
@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 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
| b | 30 | 0 | 12 | 24 |
| f | 18 | 12 | 0 | 30 |
| 1 | 30 | 24 | 30 | 0 |
Scenario: Testbot - Filling in noroutes with estimates - use input coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | input |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
| b | 30 | 0 | 12 | 24 |
| f | 18 | 12 | 0 | 30 |
| 1 | 30 | 24 | 30 | 0 |
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 24 |
| b | 30 | 0 | 12 | 18 |
| f | 18 | 12 | 0 | 30 |
| 1 | 24 | 18 | 30 | 0 |
+2 -61
View File
@@ -39,64 +39,5 @@ 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 |
+30 -62
View File
@@ -38,15 +38,15 @@ Feature: Multi level routing
Scenario: Testbot - Multi level routing Scenario: Testbot - Multi level routing
Given the node map Given the node map
""" """
ab ef ab ef
\ /
dc hg dc hg
ij mn ij mn
/ \
lkpo lkpo
""" """
And the nodes And the nodes
@@ -67,76 +67,44 @@ Feature: Multi level routing
When I route I should get When I route I should get
| from | to | route | time | | from | to | route | time |
| a | b | abcda,abcda | 25s | | a | b | abcda,abcda | 20s |
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 239.2s | | a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 229.4s |
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 157.1s | | a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 144.7s |
| a | o | abcda,cm,mnopm,mnopm,mnopm | 137.1s | | a | o | abcda,cm,mnopm,mnopm,mnopm | 124.7s |
| f | l | efghe,hj,ijkli,ijkli | 136.7s | | f | l | efghe,hj,ijkli,ijkli,ijkli | 124.7s |
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 162.1s | | f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 144.7s |
| l | o | ijkli,kp,mnopm,mnopm | 80s | | l | o | ijkli,kp,mnopm,mnopm | 60s |
| c | m | cm,cm | 44.7s | | c | m | cm,cm | 44.7s |
| f | a | efghe,hj,ijkli,kp,mnopm,cm,abcda,abcda | 239.2s |
| l | a | ijkli,kp,mnopm,cm,abcda,abcda | 157.1s |
When I request a travel time matrix I should get When I request a travel time matrix I should get
| | a | f | l | o | | | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 | | a | 0 | 229.4 | 144.7 | 124.7 |
| f | 239.2 | 0 | 136.7 | 162.1 | | f | 229.4 | 0 | 124.7 | 144.7 |
| l | 157.1 | 136.7 | 0 | 80 | | l | 144.7 | 124.7 | 0 | 60 |
| o | 137.1 | 162.1 | 80 | 0 | | o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get When I request a travel time matrix I should get
| | a | f | l | o | | | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 | | a | 0 | 229.4 | 144.7 | 124.7 |
When I request a travel time matrix I should get When I request a travel time matrix I should get
| | a | | | a |
| a | 0 | | a | 0 |
| f | 239.2 | | f | 229.4 |
| l | 157.1 | | l | 144.7 |
| o | 137.1 | | o | 124.7 |
When I request a travel time matrix I should get When I request a travel time matrix I should get
| | a | f | l | o | | | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 | | a | 0 | 229.4 | 144.7 | 124.7 |
| o | 137.1 | 162.1 | 80 | 0 | | o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get When I request a travel time matrix I should get
| | a | o | | | a | o |
| a | 0 | 137.1 | | a | 0 | 124.7 |
| f | 239.2 | 162.1 | | f | 229.4 | 144.7 |
| l | 157.1 | 80 | | l | 144.7 | 60 |
| o | 137.1 | 0 | | o | 124.7 | 0 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
| l | 1618.3 | 1293.3 | 0 | 800.5 |
| o | 1418.2 | 1617.3 | 800.5 | 0 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| f | 2339.9 |
| l | 1618.3 |
| o | 1418.2 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
When I request a travel distance matrix I should get
| | a | o |
| a | 0 | 1366.8 |
| f | 2339.9 | 1522.1 |
| l | 1618.3 | 800.5 |
| o | 1418.2 | 0 |
Scenario: Testbot - Multi level routing: horizontal road Scenario: Testbot - Multi level routing: horizontal road
Given the node map Given the node map
+1 -1
View File
@@ -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 | 1295.7,487.5,304.7,0 | 1:0:0 | | a | g | ad,df,fb,fb | 30 km/h | 1275.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
+2 -5
View File
@@ -12,26 +12,23 @@ namespace contractor
struct ContractorEdgeData struct ContractorEdgeData
{ {
ContractorEdgeData() ContractorEdgeData()
: weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0), : weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
backward(0)
{ {
} }
ContractorEdgeData(EdgeWeight weight, ContractorEdgeData(EdgeWeight weight,
EdgeWeight duration, EdgeWeight duration,
EdgeDistance distance,
unsigned original_edges, unsigned original_edges,
unsigned id, unsigned id,
bool shortcut, bool shortcut,
bool forward, bool forward,
bool backward) bool backward)
: weight(weight), duration(duration), distance(distance), id(id), : weight(weight), duration(duration), id(id),
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut), originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
forward(forward), backward(backward) forward(forward), backward(backward)
{ {
} }
EdgeWeight weight; EdgeWeight weight;
EdgeWeight duration; EdgeWeight duration;
EdgeDistance distance;
unsigned id; unsigned id;
unsigned originalEdges : 29; unsigned originalEdges : 29;
bool shortcut : 1; bool shortcut : 1;
@@ -41,7 +41,6 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.target, input_edge.target,
std::max(input_edge.data.weight, 1), std::max(input_edge.data.weight, 1),
input_edge.data.duration, input_edge.data.duration,
input_edge.data.distance,
1, 1,
input_edge.data.turn_id, input_edge.data.turn_id,
false, false,
@@ -52,7 +51,6 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.source, input_edge.source,
std::max(input_edge.data.weight, 1), std::max(input_edge.data.weight, 1),
input_edge.data.duration, input_edge.data.duration,
input_edge.data.distance,
1, 1,
input_edge.data.turn_id, input_edge.data.turn_id,
false, false,
@@ -84,7 +82,6 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT; forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION; forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE;
// remove parallel edges // remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target) while (i < edges.size() && edges[i].source == source && edges[i].target == target)
{ {
@@ -93,16 +90,12 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight); forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
forward_edge.data.duration = forward_edge.data.duration =
std::min(edges[i].data.duration, forward_edge.data.duration); std::min(edges[i].data.duration, forward_edge.data.duration);
forward_edge.data.distance =
std::min(edges[i].data.distance, forward_edge.data.distance);
} }
if (edges[i].data.backward) if (edges[i].data.backward)
{ {
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight); reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
reverse_edge.data.duration = reverse_edge.data.duration =
std::min(edges[i].data.duration, reverse_edge.data.duration); std::min(edges[i].data.duration, reverse_edge.data.duration);
reverse_edge.data.distance =
std::min(edges[i].data.distance, reverse_edge.data.distance);
} }
++i; ++i;
} }
@@ -158,7 +151,6 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid"); BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
new_edge.data.weight = data.weight; new_edge.data.weight = data.weight;
new_edge.data.duration = data.duration; new_edge.data.duration = data.duration;
new_edge.data.distance = data.distance;
new_edge.data.shortcut = data.shortcut; new_edge.data.shortcut = data.shortcut;
new_edge.data.turn_id = data.id; new_edge.data.turn_id = data.id;
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31 BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
+3 -8
View File
@@ -17,8 +17,7 @@ struct QueryEdge
struct EdgeData struct EdgeData
{ {
explicit EdgeData() explicit EdgeData()
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false), : turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false)
distance(0)
{ {
} }
@@ -26,11 +25,10 @@ struct QueryEdge
const bool shortcut, const bool shortcut,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeWeight duration, const EdgeWeight duration,
const EdgeDistance distance,
const bool forward, const bool forward,
const bool backward) const bool backward)
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration), : turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
forward(forward), backward(backward), distance(distance) forward(forward), backward(backward)
{ {
} }
@@ -42,7 +40,6 @@ struct QueryEdge
turn_id = other.id; turn_id = other.id;
forward = other.forward; forward = other.forward;
backward = other.backward; backward = other.backward;
distance = other.distance;
} }
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node // this ID is either the middle node of the shortcut, or the ID of the edge based node (node
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle // based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
@@ -53,7 +50,6 @@ struct QueryEdge
EdgeWeight duration : 30; EdgeWeight duration : 30;
std::uint32_t forward : 1; std::uint32_t forward : 1;
std::uint32_t backward : 1; std::uint32_t backward : 1;
EdgeDistance distance;
} data; } data;
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {} QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
@@ -73,8 +69,7 @@ struct QueryEdge
return (source == right.source && target == right.target && return (source == right.source && target == right.target &&
data.weight == right.data.weight && data.duration == right.data.duration && data.weight == right.data.weight && data.duration == right.data.duration &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
data.backward == right.data.backward && data.turn_id == right.data.turn_id && data.backward == right.data.backward && data.turn_id == right.data.turn_id);
data.distance == right.data.distance);
} }
}; };
} }
+11 -37
View File
@@ -22,7 +22,6 @@ class CellCustomizer
{ {
bool from_clique; bool from_clique;
EdgeDuration duration; EdgeDuration duration;
EdgeDistance distance;
}; };
public: public:
@@ -61,7 +60,7 @@ class CellCustomizer
} }
} }
heap.Clear(); heap.Clear();
heap.Insert(source, 0, {false, 0, 0}); heap.Insert(source, 0, {false, 0});
// explore search space // explore search space
while (!heap.Empty() && !destinations_set.empty()) while (!heap.Empty() && !destinations_set.empty())
@@ -69,18 +68,8 @@ class CellCustomizer
const NodeID node = heap.DeleteMin(); const NodeID node = heap.DeleteMin();
const EdgeWeight weight = heap.GetKey(node); const EdgeWeight weight = heap.GetKey(node);
const EdgeDuration duration = heap.GetData(node).duration; const EdgeDuration duration = heap.GetData(node).duration;
const EdgeDistance distance = heap.GetData(node).distance;
RelaxNode(graph, RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration);
cells,
allowed_nodes,
metric,
heap,
level,
node,
weight,
duration,
distance);
destinations_set.erase(node); destinations_set.erase(node);
} }
@@ -88,27 +77,21 @@ class CellCustomizer
// fill a map of destination nodes to placeholder pointers // fill a map of destination nodes to placeholder pointers
auto weights = cell.GetOutWeight(source); auto weights = cell.GetOutWeight(source);
auto durations = cell.GetOutDuration(source); auto durations = cell.GetOutDuration(source);
auto distances = cell.GetOutDistance(source);
for (auto &destination : destinations) for (auto &destination : destinations)
{ {
BOOST_ASSERT(!weights.empty()); BOOST_ASSERT(!weights.empty());
BOOST_ASSERT(!durations.empty()); BOOST_ASSERT(!durations.empty());
BOOST_ASSERT(!distances.empty());
const bool inserted = heap.WasInserted(destination); const bool inserted = heap.WasInserted(destination);
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT; weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
durations.front() = durations.front() =
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION; inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
distances.front() =
inserted ? heap.GetData(destination).distance : INVALID_EDGE_DISTANCE;
weights.advance_begin(1); weights.advance_begin(1);
durations.advance_begin(1); durations.advance_begin(1);
distances.advance_begin(1);
} }
BOOST_ASSERT(weights.empty()); BOOST_ASSERT(weights.empty());
BOOST_ASSERT(durations.empty()); BOOST_ASSERT(durations.empty());
BOOST_ASSERT(distances.empty());
} }
} }
@@ -145,8 +128,7 @@ class CellCustomizer
LevelID level, LevelID level,
NodeID node, NodeID node,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration) const
EdgeDistance distance) const
{ {
auto first_level = level == 1; auto first_level = level == 1;
BOOST_ASSERT(heap.WasInserted(node)); BOOST_ASSERT(heap.WasInserted(node));
@@ -167,7 +149,6 @@ class CellCustomizer
auto subcell = cells.GetCell(metric, level - 1, subcell_id); auto subcell = cells.GetCell(metric, level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin(); auto subcell_destination = subcell.GetDestinationNodes().begin();
auto subcell_duration = subcell.GetOutDuration(node).begin(); auto subcell_duration = subcell.GetOutDuration(node).begin();
auto subcell_distance = subcell.GetOutDistance(node).begin();
for (auto subcell_weight : subcell.GetOutWeight(node)) for (auto subcell_weight : subcell.GetOutWeight(node))
{ {
if (subcell_weight != INVALID_EDGE_WEIGHT) if (subcell_weight != INVALID_EDGE_WEIGHT)
@@ -180,24 +161,20 @@ class CellCustomizer
const EdgeWeight to_weight = weight + subcell_weight; const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration; const EdgeDuration to_duration = duration + *subcell_duration;
const EdgeDistance to_distance = distance + *subcell_distance;
if (!heap.WasInserted(to)) if (!heap.WasInserted(to))
{ {
heap.Insert(to, to_weight, {true, to_duration, to_distance}); heap.Insert(to, to_weight, {true, to_duration});
} }
else if (std::tie(to_weight, to_duration, to_distance) < else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), std::tie(heap.GetKey(to), heap.GetData(to).duration))
heap.GetData(to).duration,
heap.GetData(to).distance))
{ {
heap.DecreaseKey(to, to_weight); heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {true, to_duration, to_distance}; heap.GetData(to) = {true, to_duration};
} }
} }
++subcell_destination; ++subcell_destination;
++subcell_duration; ++subcell_duration;
++subcell_distance;
} }
} }
} }
@@ -218,18 +195,15 @@ class CellCustomizer
{ {
const EdgeWeight to_weight = weight + data.weight; const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration; const EdgeDuration to_duration = duration + data.duration;
const EdgeDistance to_distance = distance + data.distance;
if (!heap.WasInserted(to)) if (!heap.WasInserted(to))
{ {
heap.Insert( heap.Insert(to, to_weight, {false, duration + data.duration});
to, to_weight, {false, duration + data.duration, distance + data.distance});
} }
else if (std::tie(to_weight, to_duration, to_distance) < else if (std::tie(to_weight, to_duration) <
std::tie( std::tie(heap.GetKey(to), heap.GetData(to).duration))
heap.GetKey(to), heap.GetData(to).duration, heap.GetData(to).distance))
{ {
heap.DecreaseKey(to, to_weight); heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {false, to_duration, to_distance}; heap.GetData(to) = {false, to_duration};
} }
} }
} }
-1
View File
@@ -20,7 +20,6 @@ template <storage::Ownership Ownership> struct CellMetricImpl
Vector<EdgeWeight> weights; Vector<EdgeWeight> weights;
Vector<EdgeDuration> durations; Vector<EdgeDuration> durations;
Vector<EdgeDistance> distances;
}; };
} }
+1 -2
View File
@@ -21,8 +21,7 @@ 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 -104
View File
@@ -16,116 +16,28 @@ namespace osrm
namespace customizer namespace customizer
{ {
struct EdgeBasedGraphEdgeData using EdgeBasedGraphEdgeData = partitioner::EdgeBasedGraphEdgeData;
struct MultiLevelEdgeBasedGraph
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
{ {
NodeID turn_id; // ID of the edge based node (node based edge) using Base =
partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
using Base::Base;
}; };
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph; struct MultiLevelEdgeBasedGraphView
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
namespace serialization
{ {
template <typename EdgeDataT, storage::Ownership Ownership> using Base = partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
void read(storage::tar::FileReader &reader, using Base::Base;
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_,
Vector<EdgeDistance> node_distances_)
: node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
node_distances(std::move(node_distances_))
{
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<EdgeDistance> node_distances_,
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_)),
node_distances(std::move(node_distances_)), 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]; }
EdgeDistance GetNodeDistance(NodeID node) const { return node_distances[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<EdgeDistance> node_distances;
Vector<bool> is_forward_edge;
Vector<bool> is_backward_edge;
}; };
using MultiLevelEdgeBasedGraph = struct StaticEdgeBasedGraphEdge : MultiLevelEdgeBasedGraph::InputEdge
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>; {
using MultiLevelEdgeBasedGraphView = using Base = MultiLevelEdgeBasedGraph::InputEdge;
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>; using Base::Base;
};
} }
} }
-33
View File
@@ -73,39 +73,6 @@ writeCellMetrics(const boost::filesystem::path &path,
} }
} }
} }
// 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);
}
} }
} }
} }
-34
View File
@@ -1,8 +1,6 @@
#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/serialization.hpp" #include "storage/serialization.hpp"
@@ -23,7 +21,6 @@ inline void read(storage::tar::FileReader &reader,
{ {
storage::serialization::read(reader, name + "/weights", metric.weights); storage::serialization::read(reader, name + "/weights", metric.weights);
storage::serialization::read(reader, name + "/durations", metric.durations); storage::serialization::read(reader, name + "/durations", metric.durations);
storage::serialization::read(reader, name + "/distances", metric.distances);
} }
template <storage::Ownership Ownership> template <storage::Ownership Ownership>
@@ -33,37 +30,6 @@ inline void write(storage::tar::FileWriter &writer,
{ {
storage::serialization::write(writer, name + "/weights", metric.weights); storage::serialization::write(writer, name + "/weights", metric.weights);
storage::serialization::write(writer, name + "/durations", metric.durations); storage::serialization::write(writer, name + "/durations", metric.durations);
storage::serialization::write(writer, name + "/distances", metric.distances);
}
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 + "/node_distances", graph.node_distances);
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 + "/node_distances", graph.node_distances);
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);
} }
} }
} }
-9
View File
@@ -50,9 +50,6 @@ 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
{ {
}; };
@@ -76,9 +73,6 @@ 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
{ {
}; };
@@ -102,9 +96,6 @@ 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
{ {
}; };
+8 -48
View File
@@ -36,10 +36,9 @@ class TableAPI final : public BaseAPI
{ {
} }
virtual void virtual void MakeResponse(const std::vector<EdgeWeight> &durations,
MakeResponse(const std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> &tables, const std::vector<PhantomNode> &phantoms,
const std::vector<PhantomNode> &phantoms, util::json::Object &response) const
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();
@@ -65,18 +64,8 @@ class TableAPI final : public BaseAPI
response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations); response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations);
} }
if (parameters.annotations & TableParameters::AnnotationsType::Duration) response.values["durations"] =
{ 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";
} }
@@ -108,9 +97,9 @@ class TableAPI final : public BaseAPI
return json_waypoints; return json_waypoints;
} }
virtual util::json::Array MakeDurationTable(const std::vector<EdgeWeight> &values, virtual util::json::Array MakeTable(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))
@@ -127,7 +116,6 @@ 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));
@@ -135,34 +123,6 @@ 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 &parameters; const TableParameters &parameters;
}; };
+9 -67
View File
@@ -59,25 +59,6 @@ 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;
double fallback_speed = 0;
enum class FallbackCoordinateType
{
Input = 0,
Snapped = 1
};
FallbackCoordinateType fallback_coordinate_type = FallbackCoordinateType::Input;
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>
@@ -89,29 +70,6 @@ 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_}
{
}
template <typename... Args>
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
const AnnotationsType annotations_,
double fallback_speed_,
FallbackCoordinateType fallback_coordinate_type_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_}
{
}
bool IsValid() const bool IsValid() const
{ {
if (!BaseParameters::IsValid()) if (!BaseParameters::IsValid())
@@ -121,9 +79,16 @@ 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 their fault // 1/ The user is able to specify duplicates in srcs and dsts, in that case it's her fault
// 2/ 0 <= index < len(locations) // 2/ len(srcs) and len(dsts) smaller or equal to len(locations)
if (sources.size() > coordinates.size())
return false;
if (destinations.size() > coordinates.size())
return false;
// 3/ 0 <= index < len(locations)
const auto not_in_range = [this](const std::size_t x) { return x >= coordinates.size(); }; const auto not_in_range = [this](const std::size_t x) { return x >= coordinates.size(); };
if (std::any_of(begin(sources), end(sources), not_in_range)) if (std::any_of(begin(sources), end(sources), not_in_range))
@@ -132,32 +97,9 @@ struct TableParameters : public BaseParameters
if (std::any_of(begin(destinations), end(destinations), not_in_range)) if (std::any_of(begin(destinations), end(destinations), not_in_range))
return false; return false;
if (fallback_speed < 0)
return false;
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;
}
} }
} }
} }
@@ -2,7 +2,6 @@
#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"
@@ -60,7 +59,7 @@ template <> class AlgorithmDataFacade<CH>
template <> class AlgorithmDataFacade<MLD> template <> class AlgorithmDataFacade<MLD>
{ {
public: public:
using EdgeData = customizer::EdgeBasedGraphEdgeData; using EdgeData = extractor::EdgeBasedEdge::EdgeData;
using EdgeRange = util::range<EdgeID>; using EdgeRange = util::range<EdgeID>;
// search graph access // search graph access
@@ -72,22 +71,12 @@ template <> class AlgorithmDataFacade<MLD>
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 EdgeDistance GetNodeDistance(const NodeID node) const = 0;
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;
@@ -133,6 +133,7 @@ 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;
@@ -282,13 +283,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return segment_data.GetReverseDatasources(id); return segment_data.GetReverseDatasources(id);
} }
TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const override final TurnPenalty GetWeightPenaltyForEdgeID(const unsigned 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];
} }
TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const override final TurnPenalty GetDurationPenaltyForEdgeID(const unsigned 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];
@@ -621,6 +622,7 @@ class ContiguousInternalMemoryDataFacade<CH>
const std::size_t exclude_index) const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index), : ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, metric_name, exclude_index) ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, metric_name, exclude_index)
{ {
} }
}; };
@@ -682,36 +684,6 @@ 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);
}
EdgeDistance GetNodeDistance(const NodeID node) const override final
{
return query_graph.GetNodeDistance(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
@@ -719,6 +691,11 @@ 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);
@@ -743,6 +720,7 @@ class ContiguousInternalMemoryDataFacade<MLD> final
const std::size_t exclude_index) const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index), : ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, metric_name, exclude_index) ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, metric_name, exclude_index)
{ {
} }
}; };
@@ -33,6 +33,7 @@
#include <boost/range/adaptor/reversed.hpp> #include <boost/range/adaptor/reversed.hpp>
#include <boost/range/any_range.hpp> #include <boost/range/any_range.hpp>
#include <cstddef> #include <cstddef>
#include <string> #include <string>
@@ -86,9 +87,9 @@ class BaseDataFacade
virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0; virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0;
virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0; virtual NodeReverseRange 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
@@ -10,7 +10,6 @@
#include <boost/iostreams/device/mapped_file.hpp> #include <boost/iostreams/device/mapped_file.hpp>
#include <memory> #include <memory>
#include <string>
namespace osrm namespace osrm
{ {
@@ -25,7 +24,8 @@ namespace datafacade
class MMapMemoryAllocator : public ContiguousBlockAllocator class MMapMemoryAllocator : public ContiguousBlockAllocator
{ {
public: public:
explicit MMapMemoryAllocator(const storage::StorageConfig &config); explicit MMapMemoryAllocator(const storage::StorageConfig &config,
const boost::filesystem::path &memory_file);
~MMapMemoryAllocator() override final; ~MMapMemoryAllocator() override final;
// interface to give access to the datafacades // interface to give access to the datafacades
@@ -33,8 +33,8 @@ class MMapMemoryAllocator : public ContiguousBlockAllocator
private: private:
storage::SharedDataIndex index; storage::SharedDataIndex index;
std::vector<boost::iostreams::mapped_file> mapped_memory_files; util::vector_view<char> mapped_memory;
std::string rtree_filename; boost::iostreams::mapped_file mapped_memory_file;
}; };
} // namespace datafacade } // namespace datafacade
+3 -2
View File
@@ -32,8 +32,9 @@ class ExternalProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
public: public:
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade; using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
ExternalProvider(const storage::StorageConfig &config) ExternalProvider(const storage::StorageConfig &config,
: facade_factory(std::make_shared<datafacade::MMapMemoryAllocator>(config)) const boost::filesystem::path &memory_file)
: facade_factory(std::make_shared<datafacade::MMapMemoryAllocator>(config, memory_file))
{ {
} }
+5 -9
View File
@@ -63,16 +63,12 @@ template <typename Algorithm> class Engine final : public EngineInterface
<< "\" with algorithm " << routing_algorithms::name<Algorithm>(); << "\" with algorithm " << routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name); facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name);
} }
else if (!config.memory_file.empty() || config.use_mmap) else if (!config.memory_file.empty())
{ {
if (!config.memory_file.empty()) util::Log(logDEBUG) << "Using memory mapped filed at " << config.memory_file
{ << " with algorithm " << routing_algorithms::name<Algorithm>();
util::Log(logWARNING) facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config,
<< "The 'memory_file' option is DEPRECATED - using direct mmaping instead"; config.memory_file);
}
util::Log(logDEBUG) << "Using direct memory mapping with algorithm "
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config);
} }
else else
{ {
-1
View File
@@ -89,7 +89,6 @@ struct EngineConfig final
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; boost::filesystem::path memory_file;
bool use_mmap = true;
Algorithm algorithm = Algorithm::CH; Algorithm algorithm = Algorithm::CH;
std::string verbosity; std::string verbosity;
std::string dataset_name; std::string dataset_name;
+2 -35
View File
@@ -13,7 +13,6 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <iterator>
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -448,8 +447,6 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const auto forward_durations = datafacade.GetUncompressedForwardDurations(geometry_id); const auto forward_durations = datafacade.GetUncompressedForwardDurations(geometry_id);
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id); const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
const auto forward_weight_offset = const auto forward_weight_offset =
std::accumulate(forward_weights.begin(), std::accumulate(forward_weights.begin(),
forward_weights.begin() + data.fwd_segment_position, forward_weights.begin() + data.fwd_segment_position,
@@ -460,25 +457,12 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
forward_durations.begin() + data.fwd_segment_position, forward_durations.begin() + data.fwd_segment_position,
EdgeDuration{0}); EdgeDuration{0});
EdgeDistance forward_distance_offset = 0; EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
for (auto current = forward_geometry.begin(); EdgeDuration forward_duration = forward_durations[data.fwd_segment_position];
current < forward_geometry.begin() + data.fwd_segment_position;
++current)
{
forward_distance_offset += util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
}
BOOST_ASSERT(data.fwd_segment_position < BOOST_ASSERT(data.fwd_segment_position <
std::distance(forward_durations.begin(), forward_durations.end())); std::distance(forward_durations.begin(), forward_durations.end()));
EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
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 = const auto reverse_weight_offset =
std::accumulate(reverse_weights.begin(), std::accumulate(reverse_weights.begin(),
reverse_weights.end() - data.fwd_segment_position - 1, reverse_weights.end() - data.fwd_segment_position - 1,
@@ -489,23 +473,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_durations.end() - data.fwd_segment_position - 1, reverse_durations.end() - data.fwd_segment_position - 1,
EdgeDuration{0}); EdgeDuration{0});
EdgeDistance reverse_distance_offset = 0;
for (auto current = forward_geometry.begin();
current < forward_geometry.end() - data.fwd_segment_position - 2;
++current)
{
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
}
EdgeWeight reverse_weight = EdgeWeight reverse_weight =
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1]; reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
EdgeDuration reverse_duration = EdgeDuration reverse_duration =
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1]; 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)
@@ -539,10 +510,6 @@ 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,
+2 -2
View File
@@ -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) == 80 + 4, "Hint is bigger than expected"); static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 112; constexpr std::size_t ENCODED_HINT_SIZE = 92;
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");
} }
+3 -42
View File
@@ -47,13 +47,10 @@ 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)
{ {
} }
@@ -81,30 +78,6 @@ 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
@@ -115,8 +88,6 @@ 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);
} }
@@ -159,10 +130,6 @@ 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,
@@ -177,9 +144,7 @@ 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_distance{forward_distance}, reverse_weight_offset{reverse_weight_offset}, forward_duration{forward_duration},
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},
@@ -197,17 +162,13 @@ 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; // this is the coordinate of x util::Coordinate location;
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
@@ -219,7 +180,7 @@ struct PhantomNode
unsigned short bearing : 12; unsigned short bearing : 12;
}; };
static_assert(sizeof(PhantomNode) == 80, "PhantomNode has more padding then expected"); static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>; using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
+10 -23
View File
@@ -30,11 +30,10 @@ class RoutingAlgorithmsInterface
virtual InternalRouteResult virtual InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0; DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> virtual std::vector<EdgeDuration>
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 std::vector<std::size_t> &target_indices) const = 0;
const bool calculate_distance) const = 0;
virtual routing_algorithms::SubMatchingList virtual routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list, MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@@ -54,7 +53,6 @@ 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;
@@ -83,11 +81,10 @@ 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;
virtual std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> std::vector<EdgeDuration>
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 std::vector<std::size_t> &target_indices) const final override;
const bool calculate_distance) const final override;
routing_algorithms::SubMatchingList routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list, MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@@ -127,11 +124,6 @@ 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;
@@ -192,11 +184,10 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatc
} }
template <typename Algorithm> template <typename Algorithm>
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> std::vector<EdgeDuration> RoutingAlgorithms<Algorithm>::ManyToManySearch(
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes, 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 std::vector<std::size_t> &_target_indices) const
const bool calculate_distance) const
{ {
BOOST_ASSERT(!phantom_nodes.empty()); BOOST_ASSERT(!phantom_nodes.empty());
@@ -214,12 +205,8 @@ RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &p
std::iota(target_indices.begin(), target_indices.end(), 0); std::iota(target_indices.begin(), target_indices.end(), 0);
} }
return routing_algorithms::manyToManySearch(heaps, return routing_algorithms::manyToManySearch(
*facade, heaps, *facade, phantom_nodes, std::move(source_indices), std::move(target_indices));
phantom_nodes,
std::move(source_indices),
std::move(target_indices),
calculate_distance);
} }
template <typename Algorithm> template <typename Algorithm>
@@ -15,46 +15,23 @@ namespace engine
{ {
namespace routing_algorithms namespace routing_algorithms
{ {
namespace namespace
{ {
struct NodeBucket struct NodeBucket
{ {
NodeID middle_node; NodeID middle_node;
NodeID parent_node; unsigned column_index; // a column in the weight/duration matrix
unsigned column_index : 31; // a column in the weight/duration matrix
unsigned from_clique_arc : 1;
EdgeWeight weight; EdgeWeight weight;
EdgeDuration duration; EdgeDuration duration;
EdgeDistance distance;
NodeBucket(NodeID middle_node, NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
NodeID parent_node, : middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
bool from_clique_arc,
unsigned column_index,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance)
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
from_clique_arc(from_clique_arc), weight(weight), duration(duration), distance(distance)
{
}
NodeBucket(NodeID middle_node,
NodeID parent_node,
unsigned column_index,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance)
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
from_clique_arc(false), weight(weight), duration(duration), distance(distance)
{ {
} }
// partial order comparison // partial order comparison
bool operator<(const NodeBucket &rhs) const bool operator<(const NodeBucket &rhs) const { return middle_node < rhs.middle_node; }
{
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
@@ -69,35 +46,15 @@ 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::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data, const DataFacade<Algorithm> &facade,
const DataFacade<Algorithm> &facade, const std::vector<PhantomNode> &phantom_nodes,
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 std::vector<std::size_t> &target_indices,
const bool calculate_distance);
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine
@@ -85,17 +85,13 @@ void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
{ {
heap.Insert(phantom_node.forward_segment_id.id, heap.Insert(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(), -phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, {phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
-phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance()});
} }
if (phantom_node.IsValidReverseSource()) if (phantom_node.IsValidReverseSource())
{ {
heap.Insert(phantom_node.reverse_segment_id.id, heap.Insert(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(), -phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, {phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
-phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance()});
} }
} }
@@ -106,17 +102,13 @@ void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
{ {
heap.Insert(phantom_node.forward_segment_id.id, heap.Insert(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(), phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, {phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
phantom_node.GetForwardDuration(),
phantom_node.GetForwardDistance()});
} }
if (phantom_node.IsValidReverseTarget()) if (phantom_node.IsValidReverseTarget())
{ {
heap.Insert(phantom_node.reverse_segment_id.id, heap.Insert(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(), phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, {phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
phantom_node.GetReverseDuration(),
phantom_node.GetReverseDistance()});
} }
} }
@@ -189,7 +181,6 @@ void annotatePath(const FacadeT &facade,
BOOST_ASSERT(datasource_vector.size() > 0); BOOST_ASSERT(datasource_vector.size() > 0);
BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size()); BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size());
BOOST_ASSERT(duration_vector.size() + 1 == id_vector.size()); 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 =
@@ -414,22 +405,6 @@ 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
@@ -186,10 +186,9 @@ void routingStep(const DataFacade<Algorithm> &facade,
} }
template <bool UseDuration> template <bool UseDuration>
std::tuple<EdgeWeight, EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node) EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
{ {
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT; EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
for (auto edge : facade.GetAdjacentEdgeRange(node)) for (auto edge : facade.GetAdjacentEdgeRange(node))
{ {
const auto &data = facade.GetEdgeData(edge); const auto &data = facade.GetEdgeData(edge);
@@ -199,15 +198,11 @@ std::tuple<EdgeWeight, EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &
if (to == node) if (to == node)
{ {
const auto value = UseDuration ? data.duration : data.weight; const auto value = UseDuration ? data.duration : data.weight;
if (value < loop_weight) loop_weight = std::min(loop_weight, value);
{
loop_weight = value;
loop_distance = data.distance;
}
} }
} }
} }
return std::make_tuple(loop_weight, loop_distance); return loop_weight;
} }
/** /**
@@ -293,106 +288,6 @@ 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,
@@ -445,11 +340,6 @@ 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 // * check if the node cell is the same as the specified parent onr
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,61 +65,6 @@ 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.
@@ -129,46 +74,6 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
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,
@@ -301,22 +206,15 @@ 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...))
{ {
const auto node_weight = BOOST_ASSERT_MSG(edge_data.weight > 0, "edge_weight invalid");
facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? node : to); const EdgeWeight to_weight = weight + edge_data.weight;
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))
{ {
+5 -13
View File
@@ -30,11 +30,7 @@ struct HeapData
struct ManyToManyHeapData : HeapData struct ManyToManyHeapData : HeapData
{ {
EdgeWeight duration; EdgeWeight duration;
EdgeDistance distance; ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
ManyToManyHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
: HeapData(p), duration(duration), distance(distance)
{
}
}; };
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm> template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
@@ -79,16 +75,12 @@ struct MultiLayerDijkstraHeapData
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
{ {
EdgeWeight duration; EdgeWeight duration;
EdgeDistance distance; ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration)
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance) : MultiLayerDijkstraHeapData(p), duration(duration)
: MultiLayerDijkstraHeapData(p), duration(duration), distance(distance)
{ {
} }
ManyToManyMultiLayerDijkstraHeapData(NodeID p, ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeWeight duration)
bool from, : MultiLayerDijkstraHeapData(p, from), duration(duration)
EdgeWeight duration,
EdgeDistance distance)
: MultiLayerDijkstraHeapData(p, from), duration(duration), distance(distance)
{ {
} }
}; };
+5 -12
View File
@@ -15,25 +15,20 @@ struct EdgeBasedEdge
public: public:
struct EdgeData struct EdgeData
{ {
EdgeData() EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {}
: turn_id(0), weight(0), distance(0), duration(0), forward(false), backward(false)
{
}
EdgeData(const NodeID turn_id, EdgeData(const NodeID turn_id,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeDistance distance,
const EdgeWeight duration, const EdgeWeight duration,
const bool forward, const bool forward,
const bool backward) const bool backward)
: turn_id(turn_id), weight(weight), distance(distance), duration(duration), : turn_id(turn_id), weight(weight), duration(duration), forward(forward),
forward(forward), backward(backward) backward(backward)
{ {
} }
NodeID turn_id; // ID of the edge based node (node based edge) NodeID turn_id; // ID of the edge based node (node based edge)
EdgeWeight weight; EdgeWeight weight;
EdgeDistance distance;
EdgeWeight duration : 30; EdgeWeight duration : 30;
std::uint32_t forward : 1; std::uint32_t forward : 1;
std::uint32_t backward : 1; std::uint32_t backward : 1;
@@ -48,7 +43,6 @@ struct EdgeBasedEdge
const NodeID edge_id, const NodeID edge_id,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeWeight duration, const EdgeWeight duration,
const EdgeDistance distance,
const bool forward, const bool forward,
const bool backward); const bool backward);
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data); EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
@@ -59,7 +53,7 @@ struct EdgeBasedEdge
NodeID target; NodeID target;
EdgeData data; EdgeData data;
}; };
static_assert(sizeof(extractor::EdgeBasedEdge) == 24, static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
"Size of extractor::EdgeBasedEdge type is " "Size of extractor::EdgeBasedEdge type is "
"bigger than expected. This will influence " "bigger than expected. This will influence "
"memory consumption."); "memory consumption.");
@@ -73,10 +67,9 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID turn_id, const NodeID turn_id,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeWeight duration, const EdgeWeight duration,
const EdgeDistance distance,
const bool forward, const bool forward,
const bool backward) const bool backward)
: source(source), target(target), data{turn_id, weight, distance, duration, forward, backward} : source(source), target(target), data{turn_id, weight, duration, forward, backward}
{ {
} }
@@ -91,8 +91,6 @@ 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);
void GetEdgeBasedNodeDistances(std::vector<EdgeDistance> &output_node_distances);
std::uint32_t GetConnectivityChecksum() const; std::uint32_t GetConnectivityChecksum() const;
std::uint64_t GetNumberOfEdgeBasedNodes() const; std::uint64_t GetNumberOfEdgeBasedNodes() const;
@@ -119,8 +117,6 @@ 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;
std::vector<EdgeDistance> m_edge_based_node_distances;
//! 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;
-2
View File
@@ -87,8 +87,6 @@ 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,
std::vector<EdgeDistance> &edge_based_node_distances,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list, util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
std::uint32_t &connectivity_checksum); std::uint32_t &connectivity_checksum);
+5 -43
View File
@@ -453,8 +453,8 @@ void writeNames(const boost::filesystem::path &path, const NameTableT &table)
serialization::write(writer, "/common/names", table); serialization::write(writer, "/common/names", table);
} }
template <typename NodeWeightsVectorT> template <typename NodeWeigtsVectorT>
void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeightsVectorT &weights) void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVectorT &weights)
{ {
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint; const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint}; storage::tar::FileReader reader{path, fingerprint};
@@ -462,52 +462,14 @@ void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeightsVe
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights); storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
} }
template <typename NodeDistancesVectorT> template <typename NodeWeigtsVectorT>
void readEdgeBasedNodeDistances(const boost::filesystem::path &path, void writeEdgeBasedNodeWeights(const boost::filesystem::path &path,
NodeDistancesVectorT &distances) const NodeWeigtsVectorT &weights)
{
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint};
storage::serialization::read(reader, "/extractor/edge_based_node_distances", distances);
}
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT, typename NodeDistancesVectorT>
void writeEdgeBasedNodeWeightsDurationsDistances(const boost::filesystem::path &path,
const NodeWeightsVectorT &weights,
const NodeDurationsVectorT &durations,
const NodeDistancesVectorT &distances)
{ {
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint; const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
storage::tar::FileWriter writer{path, fingerprint}; storage::tar::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights); storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights);
storage::serialization::write(writer, "/extractor/edge_based_node_durations", durations);
storage::serialization::write(writer, "/extractor/edge_based_node_distances", distances);
}
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT>
void readEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
NodeWeightsVectorT &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 NodeWeightsVectorT, typename NodeDurationsVectorT>
void writeEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
const NodeWeightsVectorT &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> template <typename RTreeT>
@@ -63,7 +63,7 @@ struct InternalExtractorEdge
WeightData weight_data, WeightData weight_data,
DurationData duration_data, DurationData duration_data,
util::Coordinate source_coordinate) util::Coordinate source_coordinate)
: result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)), : result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate)) duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
{ {
} }
+6 -18
View File
@@ -97,7 +97,6 @@ struct NodeBasedEdge
NodeID target, NodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags); NodeBasedEdgeClassification flags);
@@ -108,7 +107,6 @@ struct NodeBasedEdge
NodeID target; // 32 4 NodeID target; // 32 4
EdgeWeight weight; // 32 4 EdgeWeight weight; // 32 4
EdgeDuration duration; // 32 4 EdgeDuration duration; // 32 4
EdgeDistance distance; // 32 4
GeometryID geometry_id; // 32 4 GeometryID geometry_id; // 32 4
AnnotationID annotation_data; // 32 4 AnnotationID annotation_data; // 32 4
NodeBasedEdgeClassification flags; // 32 4 NodeBasedEdgeClassification flags; // 32 4
@@ -122,7 +120,6 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
OSMNodeID target, OSMNodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags); NodeBasedEdgeClassification flags);
@@ -140,8 +137,7 @@ inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
} }
inline NodeBasedEdge::NodeBasedEdge() inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), distance(0), : source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
annotation_data(-1)
{ {
} }
@@ -149,12 +145,11 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target, NodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags) NodeBasedEdgeClassification flags)
: source(source), target(target), weight(weight), duration(duration), distance(distance), : source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
geometry_id(geometry_id), annotation_data(annotation_data), flags(flags) annotation_data(annotation_data), flags(flags)
{ {
} }
@@ -180,18 +175,11 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target, OSMNodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags) NodeBasedEdgeClassification flags)
: NodeBasedEdge(SPECIAL_NODEID, : NodeBasedEdge(
SPECIAL_NODEID, SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
weight,
duration,
distance,
geometry_id,
annotation_data,
flags),
osm_source_id(std::move(source)), osm_target_id(std::move(target)) osm_source_id(std::move(source)), osm_target_id(std::move(target))
{ {
} }
@@ -201,7 +189,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
{ {
} }
static_assert(sizeof(extractor::NodeBasedEdge) == 32, static_assert(sizeof(extractor::NodeBasedEdge) == 28,
"Size of extractor::NodeBasedEdge type is " "Size of extractor::NodeBasedEdge type is "
"bigger than expected. This will influence " "bigger than expected. This will influence "
"memory consumption."); "memory consumption.");
+5 -170
View File
@@ -2,7 +2,6 @@
#define OSRM_BINDINGS_NODE_SUPPORT_HPP #define OSRM_BINDINGS_NODE_SUPPORT_HPP
#include "nodejs/json_v8_renderer.hpp" #include "nodejs/json_v8_renderer.hpp"
#include "util/json_renderer.hpp"
#include "osrm/approach.hpp" #include "osrm/approach.hpp"
#include "osrm/bearing.hpp" #include "osrm/bearing.hpp"
@@ -25,7 +24,6 @@
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
#include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -44,13 +42,6 @@ using match_parameters_ptr = std::unique_ptr<osrm::MatchParameters>;
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>; using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>; using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;
struct PluginParameters
{
bool renderJSONToBuffer = false;
};
using ObjectOrString = typename mapbox::util::variant<osrm::json::Object, std::string>;
template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result); template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);
template <> v8::Local<v8::Value> inline render(const std::string &result) template <> v8::Local<v8::Value> inline render(const std::string &result)
@@ -58,21 +49,11 @@ template <> v8::Local<v8::Value> inline render(const std::string &result)
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked(); return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
} }
template <> v8::Local<v8::Value> inline render(const ObjectOrString &result) template <> v8::Local<v8::Value> inline render(const osrm::json::Object &result)
{ {
if (result.is<osrm::json::Object>()) v8::Local<v8::Value> value;
{ renderToV8(value, result);
// Convert osrm::json object tree into matching v8 object tree return value;
v8::Local<v8::Value> value;
renderToV8(value, result.get<osrm::json::Object>());
return value;
}
else
{
// Return the string object as a node Buffer
return Nan::CopyBuffer(result.get<std::string>().data(), result.get<std::string>().size())
.ToLocalChecked();
}
} }
inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result) inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
@@ -142,10 +123,6 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
if (shared_memory.IsEmpty()) if (shared_memory.IsEmpty())
return engine_config_ptr(); return engine_config_ptr();
auto mmap_memory = params->Get(Nan::New("mmap_memory").ToLocalChecked());
if (mmap_memory.IsEmpty())
return engine_config_ptr();
if (!memory_file->IsUndefined()) if (!memory_file->IsUndefined())
{ {
if (path->IsUndefined()) if (path->IsUndefined())
@@ -194,18 +171,6 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
return engine_config_ptr(); return engine_config_ptr();
} }
} }
if (!mmap_memory->IsUndefined())
{
if (mmap_memory->IsBoolean())
{
engine_config->use_mmap = Nan::To<bool>(mmap_memory).FromJust();
}
else
{
Nan::ThrowError("mmap_memory option must be a boolean");
return engine_config_ptr();
}
}
if (path->IsUndefined() && !engine_config->use_shared_memory) if (path->IsUndefined() && !engine_config->use_shared_memory)
{ {
@@ -849,50 +814,6 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
return true; return true;
} }
inline PluginParameters
argumentsToPluginParameters(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
if (args.Length() < 3 || !args[1]->IsObject())
{
return {};
}
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[1]).ToLocalChecked();
if (obj->Has(Nan::New("format").ToLocalChecked()))
{
v8::Local<v8::Value> format = obj->Get(Nan::New("format").ToLocalChecked());
if (format.IsEmpty())
{
return {};
}
if (!format->IsString())
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
const Nan::Utf8String format_utf8str(format);
std::string format_str{*format_utf8str, *format_utf8str + format_utf8str.length()};
if (format_str == "object")
{
return {false};
}
else if (format_str == "json_buffer")
{
return {true};
}
else
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
}
return {};
}
inline route_parameters_ptr inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args, argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates) bool requires_multiple_coordinates)
@@ -1143,92 +1064,6 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
} }
} }
if (obj->Has(Nan::New("annotations").ToLocalChecked()))
{
v8::Local<v8::Value> annotations = obj->Get(Nan::New("annotations").ToLocalChecked());
if (annotations.IsEmpty())
return table_parameters_ptr();
if (!annotations->IsArray())
{
Nan::ThrowError(
"Annotations must an array containing 'duration' or 'distance', or both");
return table_parameters_ptr();
}
params->annotations = osrm::TableParameters::AnnotationsType::None;
v8::Local<v8::Array> annotations_array = v8::Local<v8::Array>::Cast(annotations);
for (std::size_t i = 0; i < annotations_array->Length(); ++i)
{
const Nan::Utf8String annotations_utf8str(annotations_array->Get(i));
std::string annotations_str{*annotations_utf8str,
*annotations_utf8str + annotations_utf8str.length()};
if (annotations_str == "duration")
{
params->annotations =
params->annotations | osrm::TableParameters::AnnotationsType::Duration;
}
else if (annotations_str == "distance")
{
params->annotations =
params->annotations | osrm::TableParameters::AnnotationsType::Distance;
}
else
{
Nan::ThrowError("this 'annotations' param is not supported");
return table_parameters_ptr();
}
}
}
if (obj->Has(Nan::New("fallback_speed").ToLocalChecked()))
{
auto fallback_speed = obj->Get(Nan::New("fallback_speed").ToLocalChecked());
if (!fallback_speed->IsNumber())
{
Nan::ThrowError("fallback_speed must be a number");
return table_parameters_ptr();
}
else if (fallback_speed->NumberValue() < 0)
{
Nan::ThrowError("fallback_speed must be > 0");
return table_parameters_ptr();
}
params->fallback_speed = static_cast<double>(fallback_speed->NumberValue());
}
if (obj->Has(Nan::New("fallback_coordinate").ToLocalChecked()))
{
auto fallback_coordinate = obj->Get(Nan::New("fallback_coordinate").ToLocalChecked());
if (!fallback_coordinate->IsString())
{
Nan::ThrowError("fallback_coordinate must be a string: [input, snapped]");
return table_parameters_ptr();
}
std::string fallback_coordinate_str = *v8::String::Utf8Value(fallback_coordinate);
if (fallback_coordinate_str == "snapped")
{
params->fallback_coordinate_type =
osrm::TableParameters::FallbackCoordinateType::Snapped;
}
else if (fallback_coordinate_str == "input")
{
params->fallback_coordinate_type = osrm::TableParameters::FallbackCoordinateType::Input;
}
else
{
Nan::ThrowError("'fallback_coordinate' param must be one of [input, snapped]");
return table_parameters_ptr();
}
}
return params; return params;
} }
@@ -1482,6 +1317,6 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
return params; return params;
} }
} // namespace node_osrm } // ns node_osrm
#endif #endif
+14 -33
View File
@@ -75,35 +75,28 @@ template <storage::Ownership Ownership> class CellStorageImpl
// Implementation of the cell view. We need a template parameter here // Implementation of the cell view. We need a template parameter here
// because we need to derive a read-only and read-write view from this. // because we need to derive a read-only and read-write view from this.
template <typename WeightValueT, typename DurationValueT, typename DistanceValueT> template <typename WeightValueT, typename DurationValueT> class CellImpl
class CellImpl
{ {
private: private:
using WeightPtrT = WeightValueT *; using WeightPtrT = WeightValueT *;
using DurationPtrT = DurationValueT *; using DurationPtrT = DurationValueT *;
using DistancePtrT = DistanceValueT *;
BoundarySize num_source_nodes; BoundarySize num_source_nodes;
BoundarySize num_destination_nodes; BoundarySize num_destination_nodes;
WeightPtrT const weights; WeightPtrT const weights;
DurationPtrT const durations; DurationPtrT const durations;
DistancePtrT const distances;
const NodeID *const source_boundary; const NodeID *const source_boundary;
const NodeID *const destination_boundary; const NodeID *const destination_boundary;
using RowIterator = WeightPtrT; using RowIterator = WeightPtrT;
// Possibly replace with // Possibly replace with
// http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/strided.html // http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/strided.html
class ColumnIterator : public boost::iterator_facade<ColumnIterator,
template <typename ValuePtrT> WeightValueT,
class ColumnIterator : public boost::iterator_facade<ColumnIterator<ValuePtrT>,
decltype(*std::declval<ValuePtrT>()),
boost::random_access_traversal_tag> boost::random_access_traversal_tag>
{ {
typedef boost::iterator_facade<ColumnIterator,
using ValueT = decltype(*std::declval<ValuePtrT>()); WeightValueT,
typedef boost::iterator_facade<ColumnIterator<ValueT>,
ValueT,
boost::random_access_traversal_tag> boost::random_access_traversal_tag>
base_t; base_t;
@@ -115,7 +108,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
explicit ColumnIterator() : current(nullptr), stride(1) {} explicit ColumnIterator() : current(nullptr), stride(1) {}
explicit ColumnIterator(ValuePtrT begin, std::size_t row_length) explicit ColumnIterator(WeightPtrT begin, std::size_t row_length)
: current(begin), stride(row_length) : current(begin), stride(row_length)
{ {
BOOST_ASSERT(begin != nullptr); BOOST_ASSERT(begin != nullptr);
@@ -133,7 +126,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
} }
friend class ::boost::iterator_core_access; friend class ::boost::iterator_core_access;
ValuePtrT current; WeightPtrT current;
const std::size_t stride; const std::size_t stride;
}; };
@@ -154,13 +147,12 @@ template <storage::Ownership Ownership> class CellStorageImpl
auto iter = auto iter =
std::find(destination_boundary, destination_boundary + num_destination_nodes, node); std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
if (iter == destination_boundary + num_destination_nodes) if (iter == destination_boundary + num_destination_nodes)
return boost::make_iterator_range(ColumnIterator<ValuePtr>{}, return boost::make_iterator_range(ColumnIterator{}, ColumnIterator{});
ColumnIterator<ValuePtr>{});
auto column = std::distance(destination_boundary, iter); auto column = std::distance(destination_boundary, iter);
auto begin = ColumnIterator<ValuePtr>{ptr + column, num_destination_nodes}; auto begin = ColumnIterator{ptr + column, num_destination_nodes};
auto end = ColumnIterator<ValuePtr>{ auto end = ColumnIterator{ptr + column + num_source_nodes * num_destination_nodes,
ptr + column + num_source_nodes * num_destination_nodes, num_destination_nodes}; num_destination_nodes};
return boost::make_iterator_range(begin, end); return boost::make_iterator_range(begin, end);
} }
@@ -173,10 +165,6 @@ template <storage::Ownership Ownership> class CellStorageImpl
auto GetInDuration(NodeID node) const { return GetInRange(durations, node); } auto GetInDuration(NodeID node) const { return GetInRange(durations, node); }
auto GetInDistance(NodeID node) const { return GetInRange(distances, node); }
auto GetOutDistance(NodeID node) const { return GetOutRange(distances, node); }
auto GetSourceNodes() const auto GetSourceNodes() const
{ {
return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes); return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes);
@@ -191,20 +179,17 @@ template <storage::Ownership Ownership> class CellStorageImpl
CellImpl(const CellData &data, CellImpl(const CellData &data,
WeightPtrT const all_weights, WeightPtrT const all_weights,
DurationPtrT const all_durations, DurationPtrT const all_durations,
DistancePtrT const all_distances,
const NodeID *const all_sources, const NodeID *const all_sources,
const NodeID *const all_destinations) const NodeID *const all_destinations)
: num_source_nodes{data.num_source_nodes}, : num_source_nodes{data.num_source_nodes},
num_destination_nodes{data.num_destination_nodes}, num_destination_nodes{data.num_destination_nodes},
weights{all_weights + data.value_offset}, weights{all_weights + data.value_offset},
durations{all_durations + data.value_offset}, durations{all_durations + data.value_offset},
distances{all_distances + data.value_offset},
source_boundary{all_sources + data.source_boundary_offset}, source_boundary{all_sources + data.source_boundary_offset},
destination_boundary{all_destinations + data.destination_boundary_offset} destination_boundary{all_destinations + data.destination_boundary_offset}
{ {
BOOST_ASSERT(all_weights != nullptr); BOOST_ASSERT(all_weights != nullptr);
BOOST_ASSERT(all_durations != nullptr); BOOST_ASSERT(all_durations != nullptr);
BOOST_ASSERT(all_distances != nullptr);
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr); BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr); BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr);
} }
@@ -216,8 +201,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
const NodeID *const all_destinations) const NodeID *const all_destinations)
: num_source_nodes{data.num_source_nodes}, : num_source_nodes{data.num_source_nodes},
num_destination_nodes{data.num_destination_nodes}, weights{nullptr}, num_destination_nodes{data.num_destination_nodes}, weights{nullptr},
durations{nullptr}, distances{nullptr}, durations{nullptr}, source_boundary{all_sources + data.source_boundary_offset},
source_boundary{all_sources + data.source_boundary_offset},
destination_boundary{all_destinations + data.destination_boundary_offset} destination_boundary{all_destinations + data.destination_boundary_offset}
{ {
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr); BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
@@ -228,8 +212,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
std::size_t LevelIDToIndex(LevelID level) const { return level - 1; } std::size_t LevelIDToIndex(LevelID level) const { return level - 1; }
public: public:
using Cell = CellImpl<EdgeWeight, EdgeDuration, EdgeDistance>; using Cell = CellImpl<EdgeWeight, EdgeDuration>;
using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration, const EdgeDistance>; using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration>;
CellStorageImpl() {} CellStorageImpl() {}
@@ -377,7 +361,6 @@ template <storage::Ownership Ownership> class CellStorageImpl
metric.weights.resize(total_size + 1, INVALID_EDGE_WEIGHT); metric.weights.resize(total_size + 1, INVALID_EDGE_WEIGHT);
metric.durations.resize(total_size + 1, MAXIMAL_EDGE_DURATION); metric.durations.resize(total_size + 1, MAXIMAL_EDGE_DURATION);
metric.distances.resize(total_size + 1, INVALID_EDGE_DISTANCE);
return metric; return metric;
} }
@@ -405,7 +388,6 @@ template <storage::Ownership Ownership> class CellStorageImpl
return ConstCell{cells[cell_index], return ConstCell{cells[cell_index],
metric.weights.data(), metric.weights.data(),
metric.durations.data(), metric.durations.data(),
metric.distances.data(),
source_boundary.empty() ? nullptr : source_boundary.data(), source_boundary.empty() ? nullptr : source_boundary.data(),
destination_boundary.empty() ? nullptr : destination_boundary.data()}; destination_boundary.empty() ? nullptr : destination_boundary.data()};
} }
@@ -433,7 +415,6 @@ template <storage::Ownership Ownership> class CellStorageImpl
return Cell{cells[cell_index], return Cell{cells[cell_index],
metric.weights.data(), metric.weights.data(),
metric.durations.data(), metric.durations.data(),
metric.distances.data(),
source_boundary.data(), source_boundary.data(),
destination_boundary.data()}; destination_boundary.data()};
} }
@@ -43,7 +43,6 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
edge.data.turn_id, edge.data.turn_id,
std::max(edge.data.weight, 1), std::max(edge.data.weight, 1),
edge.data.duration, edge.data.duration,
edge.data.distance,
edge.data.forward, edge.data.forward,
edge.data.backward); edge.data.backward);
@@ -52,7 +51,6 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
edge.data.turn_id, edge.data.turn_id,
std::max(edge.data.weight, 1), std::max(edge.data.weight, 1),
edge.data.duration, edge.data.duration,
edge.data.distance,
edge.data.backward, edge.data.backward,
edge.data.forward); edge.data.forward);
} }
+35 -29
View File
@@ -1,6 +1,8 @@
#ifndef OSRM_PARTITIONER_SERILIZATION_HPP #ifndef OSRM_PARTITIONER_SERILIZATION_HPP
#define OSRM_PARTITIONER_SERILIZATION_HPP #define OSRM_PARTITIONER_SERILIZATION_HPP
#include "customizer/edge_based_graph.hpp"
#include "partitioner/serialization.hpp" #include "partitioner/serialization.hpp"
#include "storage/io.hpp" #include "storage/io.hpp"
@@ -12,6 +14,39 @@ namespace partitioner
namespace files namespace files
{ {
// 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);
}
// read .osrm.partition file // read .osrm.partition file
template <typename MultiLevelPartitionT> template <typename MultiLevelPartitionT>
inline void readPartition(const boost::filesystem::path &path, MultiLevelPartitionT &mlp) inline void readPartition(const boost::filesystem::path &path, MultiLevelPartitionT &mlp)
@@ -67,35 +102,6 @@ inline void writeCells(const boost::filesystem::path &path, CellStorageT &storag
serialization::write(writer, "/mld/cellstorage", storage); serialization::write(writer, "/mld/cellstorage", storage);
} }
// 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<partitioner::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<partitioner::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);
}
} }
} }
} }
-15
View File
@@ -1,7 +1,6 @@
#ifndef OSRM_PARTITIONER_MULTI_LEVEL_GRAPH_HPP #ifndef OSRM_PARTITIONER_MULTI_LEVEL_GRAPH_HPP
#define OSRM_PARTITIONER_MULTI_LEVEL_GRAPH_HPP #define OSRM_PARTITIONER_MULTI_LEVEL_GRAPH_HPP
#include "partitioner/edge_based_graph.hpp"
#include "partitioner/multi_level_partition.hpp" #include "partitioner/multi_level_partition.hpp"
#include "storage/shared_memory_ownership.hpp" #include "storage/shared_memory_ownership.hpp"
@@ -43,8 +42,6 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
template <typename T> using Vector = util::ViewOrVector<T, Ownership>; template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public: public:
using SuperT::SuperT;
// We limit each node to have 255 edges // We limit each node to have 255 edges
// this is very generous, we could probably pack this // this is very generous, we could probably pack this
using EdgeOffset = std::uint8_t; using EdgeOffset = std::uint8_t;
@@ -149,14 +146,6 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
return max_border_node_id; return max_border_node_id;
} }
auto data() && // rvalue ref-qualifier is a safety-belt
{
return std::make_tuple(std::move(SuperT::node_array),
std::move(SuperT::edge_array),
std::move(node_to_edge_offset),
connectivity_checksum);
}
private: private:
template <typename ContainerT> template <typename ContainerT>
auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
@@ -229,13 +218,9 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
const std::string &name, const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph); const MultiLevelGraph<EdgeDataT, Ownership> &graph);
protected:
Vector<EdgeOffset> node_to_edge_offset; Vector<EdgeOffset> node_to_edge_offset;
std::uint32_t connectivity_checksum; std::uint32_t connectivity_checksum;
}; };
using MultiLevelEdgeBasedGraph =
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
} }
} }
+1 -1
View File
@@ -16,7 +16,7 @@ namespace partitioner
struct PartitionerConfig final : storage::IOConfig struct PartitionerConfig final : storage::IOConfig
{ {
PartitionerConfig() PartitionerConfig()
: IOConfig({".osrm", ".osrm.fileIndex", ".osrm.ebg_nodes", ".osrm.enw"}, : IOConfig({".osrm", ".osrm.fileIndex", ".osrm.ebg_nodes"},
{".osrm.hsgr", ".osrm.cnbg"}, {".osrm.hsgr", ".osrm.cnbg"},
{".osrm.ebg", {".osrm.ebg",
".osrm.cnbg", ".osrm.cnbg",
+20
View File
@@ -19,6 +19,26 @@ namespace partitioner
namespace serialization namespace serialization
{ {
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 + "/edge_array", graph.edge_array);
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 + "/edge_array", graph.edge_array);
storage::serialization::write(writer, name + "/node_to_edge_offset", graph.node_to_edge_offset);
}
template <storage::Ownership Ownership> template <storage::Ownership Ownership>
inline void read(storage::tar::FileReader &reader, inline void read(storage::tar::FileReader &reader,
const std::string &name, const std::string &name,
@@ -178,8 +178,6 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
qi::rule<Iterator, Signature> base_rule; qi::rule<Iterator, Signature> base_rule;
qi::rule<Iterator, Signature> query_rule; qi::rule<Iterator, Signature> query_rule;
qi::real_parser<double, json_policy> double_;
private: private:
qi::rule<Iterator, Signature> bearings_rule; qi::rule<Iterator, Signature> bearings_rule;
qi::rule<Iterator, Signature> radiuses_rule; qi::rule<Iterator, Signature> radiuses_rule;
@@ -197,6 +195,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
qi::rule<Iterator, unsigned char()> base64_char; qi::rule<Iterator, unsigned char()> base64_char;
qi::rule<Iterator, std::string()> polyline_chars; qi::rule<Iterator, std::string()> polyline_chars;
qi::rule<Iterator, double()> unlimited_rule; qi::rule<Iterator, double()> unlimited_rule;
qi::real_parser<double, json_policy> double_;
qi::symbols<char, engine::Approach> approach_type; qi::symbols<char, engine::Approach> approach_type;
}; };
+4 -44
View File
@@ -22,11 +22,11 @@ namespace qi = boost::spirit::qi;
template <typename Iterator = std::string::iterator, template <typename Iterator = std::string::iterator,
typename Signature = void(engine::api::TableParameters &)> typename Signature = void(engine::api::TableParameters &)>
struct TableParametersGrammar : public BaseParametersGrammar<Iterator, Signature> struct TableParametersGrammar final : public BaseParametersGrammar<Iterator, Signature>
{ {
using BaseGrammar = BaseParametersGrammar<Iterator, Signature>; using BaseGrammar = BaseParametersGrammar<Iterator, Signature>;
TableParametersGrammar() : TableParametersGrammar(root_rule) TableParametersGrammar() : BaseGrammar(root_rule)
{ {
#ifdef BOOST_HAS_LONG_LONG #ifdef BOOST_HAS_LONG_LONG
if (std::is_same<std::size_t, unsigned long long>::value) if (std::is_same<std::size_t, unsigned long long>::value)
@@ -48,58 +48,18 @@ struct TableParametersGrammar : public BaseParametersGrammar<Iterator, Signature
(qi::lit("all") | (qi::lit("all") |
(size_t_ % ';')[ph::bind(&engine::api::TableParameters::sources, qi::_r1) = qi::_1]); (size_t_ % ';')[ph::bind(&engine::api::TableParameters::sources, qi::_r1) = qi::_1]);
fallback_speed_rule =
qi::lit("fallback_speed=") >
(double_)[ph::bind(&engine::api::TableParameters::fallback_speed, qi::_r1) = qi::_1];
fallback_coordinate_type.add("input",
engine::api::TableParameters::FallbackCoordinateType::Input)(
"snapped", engine::api::TableParameters::FallbackCoordinateType::Snapped);
table_rule = destinations_rule(qi::_r1) | sources_rule(qi::_r1); table_rule = destinations_rule(qi::_r1) | sources_rule(qi::_r1);
root_rule = root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") > -('?' > (table_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&');
-('?' > (table_rule(qi::_r1) | base_rule(qi::_r1) | fallback_speed_rule(qi::_r1) |
(qi::lit("fallback_coordinate=") >
fallback_coordinate_type
[ph::bind(&engine::api::TableParameters::fallback_coordinate_type,
qi::_r1) = qi::_1])) %
'&');
} }
TableParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
{
using AnnotationsType = engine::api::TableParameters::AnnotationsType;
annotations.add("duration", AnnotationsType::Duration)("distance",
AnnotationsType::Distance);
annotations_list = annotations[qi::_val |= qi::_1] % ',';
base_rule = BaseGrammar::base_rule(qi::_r1) |
(qi::lit("annotations=") >
annotations_list[ph::bind(&engine::api::TableParameters::annotations,
qi::_r1) = qi::_1]);
}
protected:
qi::rule<Iterator, Signature> base_rule;
private: private:
using json_policy = no_trailing_dot_policy<double, 'j', 's', 'o', 'n'>;
qi::rule<Iterator, Signature> root_rule; qi::rule<Iterator, Signature> root_rule;
qi::rule<Iterator, Signature> table_rule; qi::rule<Iterator, Signature> table_rule;
qi::rule<Iterator, Signature> sources_rule; qi::rule<Iterator, Signature> sources_rule;
qi::rule<Iterator, Signature> destinations_rule; qi::rule<Iterator, Signature> destinations_rule;
qi::rule<Iterator, Signature> fallback_speed_rule;
qi::rule<Iterator, std::size_t()> size_t_; qi::rule<Iterator, std::size_t()> size_t_;
qi::symbols<char, engine::api::TableParameters::AnnotationsType> annotations;
qi::rule<Iterator, engine::api::TableParameters::AnnotationsType()> annotations_list;
qi::symbols<char, engine::api::TableParameters::FallbackCoordinateType>
fallback_coordinate_type;
qi::real_parser<double, json_policy> double_;
}; };
} }
} }
+3 -8
View File
@@ -16,15 +16,10 @@ struct Block
{ {
std::uint64_t num_entries; std::uint64_t num_entries;
std::uint64_t byte_size; std::uint64_t byte_size;
std::uint64_t offset;
Block() : num_entries(0), byte_size(0), offset(0) {} Block() : num_entries(0), byte_size(0) {}
Block(std::uint64_t num_entries, std::uint64_t byte_size, std::uint64_t offset)
: num_entries(num_entries), byte_size(byte_size), offset(offset)
{
}
Block(std::uint64_t num_entries, std::uint64_t byte_size) Block(std::uint64_t num_entries, std::uint64_t byte_size)
: num_entries(num_entries), byte_size(byte_size), offset(0) : num_entries(num_entries), byte_size(byte_size)
{ {
} }
}; };
@@ -34,7 +29,7 @@ using NamedBlock = std::tuple<std::string, Block>;
template <typename T> Block make_block(uint64_t num_entries) template <typename T> Block make_block(uint64_t num_entries)
{ {
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer"); static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
return Block{num_entries, sizeof(T) * num_entries, 0}; return Block{num_entries, sizeof(T) * num_entries};
} }
} }
} }
+22 -40
View File
@@ -9,7 +9,6 @@
#include "storage/shared_datatype.hpp" #include "storage/shared_datatype.hpp"
#include "storage/tar.hpp" #include "storage/tar.hpp"
#include <boost/assert.hpp>
#include <boost/function_output_iterator.hpp> #include <boost/function_output_iterator.hpp>
#include <boost/iterator/function_input_iterator.hpp> #include <boost/iterator/function_input_iterator.hpp>
@@ -31,37 +30,22 @@ namespace serialization
namespace detail namespace detail
{ {
template <typename T, typename BlockT = unsigned char> template <typename T, typename BlockT = unsigned char>
inline BlockT packBits(const T &data, std::size_t base_index, const std::size_t count) inline BlockT packBits(const T &data, std::size_t index, std::size_t count)
{ {
static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool"); static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool");
static_assert(std::is_unsigned<BlockT>::value, "BlockT must be unsigned type");
static_assert(std::is_integral<BlockT>::value, "BlockT must be an integral type");
static_assert(CHAR_BIT == 8, "Non-8-bit bytes not supported, sorry!");
BOOST_ASSERT(sizeof(BlockT) * CHAR_BIT >= count);
// Note: if this packing is changed, be sure to update vector_view<bool>
// as well, so that on-disk and in-memory layouts match.
BlockT value = 0; BlockT value = 0;
for (std::size_t bit = 0; bit < count; ++bit) for (std::size_t bit = 0; bit < count; ++bit, ++index)
{ value = (value << 1) | data[index];
value |= (data[base_index + bit] ? BlockT{1} : BlockT{0}) << bit;
}
return value; return value;
} }
template <typename T, typename BlockT = unsigned char> template <typename T, typename BlockT = unsigned char>
inline void inline void unpackBits(T &data, std::size_t index, std::size_t count, BlockT value)
unpackBits(T &data, const std::size_t base_index, const std::size_t count, const BlockT value)
{ {
static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool"); static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool");
static_assert(std::is_unsigned<BlockT>::value, "BlockT must be unsigned type"); const BlockT mask = BlockT{1} << (count - 1);
static_assert(std::is_integral<BlockT>::value, "BlockT must be an integral type"); for (std::size_t bit = 0; bit < count; value <<= 1, ++bit, ++index)
static_assert(CHAR_BIT == 8, "Non-8-bit bytes not supported, sorry!"); data[index] = value & mask;
BOOST_ASSERT(sizeof(BlockT) * CHAR_BIT >= count);
for (std::size_t bit = 0; bit < count; ++bit)
{
data[base_index + bit] = value & (BlockT{1} << bit);
}
} }
template <typename VectorT> template <typename VectorT>
@@ -71,16 +55,15 @@ void readBoolVector(tar::FileReader &reader, const std::string &name, VectorT &d
data.resize(count); data.resize(count);
std::uint64_t index = 0; std::uint64_t index = 0;
using BlockType = std::uint64_t; constexpr std::uint64_t WORD_BITS = CHAR_BIT * sizeof(std::uint64_t);
constexpr std::uint64_t BLOCK_BITS = CHAR_BIT * sizeof(BlockType);
const auto decode = [&](const BlockType block) { const auto decode = [&](const std::uint64_t block) {
auto read_size = std::min<std::size_t>(count - index, BLOCK_BITS); auto read_size = std::min<std::size_t>(count - index, WORD_BITS);
unpackBits<VectorT, BlockType>(data, index, read_size, block); unpackBits<VectorT, std::uint64_t>(data, index, read_size, block);
index += BLOCK_BITS; index += WORD_BITS;
}; };
reader.ReadStreaming<BlockType>(name, boost::make_function_output_iterator(decode)); reader.ReadStreaming<std::uint64_t>(name, boost::make_function_output_iterator(decode));
} }
template <typename VectorT> template <typename VectorT>
@@ -90,20 +73,19 @@ void writeBoolVector(tar::FileWriter &writer, const std::string &name, const Vec
writer.WriteElementCount64(name, count); writer.WriteElementCount64(name, count);
std::uint64_t index = 0; std::uint64_t index = 0;
using BlockType = std::uint64_t; constexpr std::uint64_t WORD_BITS = CHAR_BIT * sizeof(std::uint64_t);
constexpr std::uint64_t BLOCK_BITS = CHAR_BIT * sizeof(BlockType);
// FIXME on old boost version the function_input_iterator does not work with lambdas // FIXME on old boost version the function_input_iterator does not work with lambdas
// so we need to wrap it in a function here. // so we need to wrap it in a function here.
const std::function<BlockType()> encode_function = [&]() -> BlockType { const std::function<std::uint64_t()> encode_function = [&]() -> std::uint64_t {
auto write_size = std::min<std::size_t>(count - index, BLOCK_BITS); auto write_size = std::min<std::size_t>(count - index, WORD_BITS);
auto packed = packBits<VectorT, BlockType>(data, index, write_size); auto packed = packBits<VectorT, std::uint64_t>(data, index, write_size);
index += BLOCK_BITS; index += WORD_BITS;
return packed; return packed;
}; };
std::uint64_t number_of_blocks = (count + BLOCK_BITS - 1) / BLOCK_BITS; std::uint64_t number_of_blocks = (count + WORD_BITS - 1) / WORD_BITS;
writer.WriteStreaming<BlockType>( writer.WriteStreaming<std::uint64_t>(
name, name,
boost::make_function_input_iterator(encode_function, boost::infinite()), boost::make_function_input_iterator(encode_function, boost::infinite()),
number_of_blocks); number_of_blocks);
@@ -284,9 +266,9 @@ template <typename K, typename V> void write(io::BufferWriter &writer, const std
} }
} }
inline void read(io::BufferReader &reader, BaseDataLayout &layout) { read(reader, layout.blocks); } inline void read(io::BufferReader &reader, DataLayout &layout) { read(reader, layout.blocks); }
inline void write(io::BufferWriter &writer, const BaseDataLayout &layout) inline void write(io::BufferWriter &writer, const DataLayout &layout)
{ {
write(writer, layout.blocks); write(writer, layout.blocks);
} }
+19 -38
View File
@@ -5,7 +5,6 @@
#include <boost/function_output_iterator.hpp> #include <boost/function_output_iterator.hpp>
#include <type_traits>
#include <unordered_map> #include <unordered_map>
namespace osrm namespace osrm
@@ -20,8 +19,8 @@ class SharedDataIndex
public: public:
struct AllocatedRegion struct AllocatedRegion
{ {
void *memory_ptr; char *memory_ptr;
std::unique_ptr<BaseDataLayout> layout; DataLayout layout;
}; };
SharedDataIndex() = default; SharedDataIndex() = default;
@@ -30,10 +29,10 @@ class SharedDataIndex
// Build mapping from block name to region // Build mapping from block name to region
for (auto index : util::irange<std::uint32_t>(0, regions.size())) for (auto index : util::irange<std::uint32_t>(0, regions.size()))
{ {
regions[index].layout->List("", regions[index].layout.List("",
boost::make_function_output_iterator([&](const auto &name) { boost::make_function_output_iterator([&](const auto &name) {
block_to_region[name] = index; block_to_region[name] = index;
})); }));
} }
} }
@@ -41,57 +40,39 @@ class SharedDataIndex
{ {
for (const auto &region : regions) for (const auto &region : regions)
{ {
region.layout->List(name_prefix, out); region.layout.List(name_prefix, out);
} }
} }
template <typename T> auto GetBlockPtr(const std::string &name) const template <typename T> auto GetBlockPtr(const std::string &name) const
{ {
#if !defined(__GNUC__) || (__GNUC__ > 4) const auto index_iter = block_to_region.find(name);
// is_tivially_copyable only exists in GCC >=5 const auto &region = regions[index_iter->second];
static_assert(std::is_trivially_copyable<T>::value, return region.layout.GetBlockPtr<T>(region.memory_ptr, name);
"Block-based data must be a trivially copyable type");
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
#endif
const auto &region = GetBlockRegion(name);
return reinterpret_cast<T *>(region.layout->GetBlockPtr(region.memory_ptr, name));
} }
template <typename T> auto GetBlockPtr(const std::string &name) template <typename T> auto GetBlockPtr(const std::string &name)
{ {
#if !defined(__GNUC__) || (__GNUC__ > 4) const auto index_iter = block_to_region.find(name);
// is_tivially_copyable only exists in GCC >=5 const auto &region = regions[index_iter->second];
static_assert(std::is_trivially_copyable<T>::value, return region.layout.GetBlockPtr<T>(region.memory_ptr, name);
"Block-based data must be a trivially copyable type");
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
#endif
const auto &region = GetBlockRegion(name);
return reinterpret_cast<T *>(region.layout->GetBlockPtr(region.memory_ptr, name));
} }
std::size_t GetBlockEntries(const std::string &name) const std::size_t GetBlockEntries(const std::string &name) const
{ {
const auto &region = GetBlockRegion(name); const auto index_iter = block_to_region.find(name);
return region.layout->GetBlockEntries(name); const auto &region = regions[index_iter->second];
return region.layout.GetBlockEntries(name);
} }
std::size_t GetBlockSize(const std::string &name) const std::size_t GetBlockSize(const std::string &name) const
{ {
const auto &region = GetBlockRegion(name); const auto index_iter = block_to_region.find(name);
return region.layout->GetBlockSize(name); const auto &region = regions[index_iter->second];
return region.layout.GetBlockSize(name);
} }
private: private:
const AllocatedRegion &GetBlockRegion(const std::string &name) const
{
const auto index_iter = block_to_region.find(name);
if (index_iter == block_to_region.end())
{
throw util::exception("data block " + name + " not found " + SOURCE_REF);
}
return regions[index_iter->second];
}
std::vector<AllocatedRegion> regions; std::vector<AllocatedRegion> regions;
std::unordered_map<std::string, std::uint32_t> block_to_region; std::unordered_map<std::string, std::uint32_t> block_to_region;
}; };
+41 -76
View File
@@ -20,13 +20,13 @@ namespace osrm
namespace storage namespace storage
{ {
class BaseDataLayout; class DataLayout;
namespace serialization namespace serialization
{ {
inline void read(io::BufferReader &reader, BaseDataLayout &layout); inline void read(io::BufferReader &reader, DataLayout &layout);
inline void write(io::BufferWriter &writer, const BaseDataLayout &layout); inline void write(io::BufferWriter &writer, const DataLayout &layout);
} // namespace serialization }
namespace detail namespace detail
{ {
@@ -52,30 +52,46 @@ inline std::string trimName(const std::string &name_prefix, const std::string &n
return name; return name;
} }
} }
} // namespace detail }
class BaseDataLayout class DataLayout
{ {
public: public:
virtual ~BaseDataLayout() = default; DataLayout() : blocks{} {}
inline void SetBlock(const std::string &name, Block block) { blocks[name] = std::move(block); } inline void SetBlock(const std::string &name, Block block) { blocks[name] = std::move(block); }
inline std::uint64_t GetBlockEntries(const std::string &name) const inline uint64_t GetBlockEntries(const std::string &name) const
{ {
return GetBlock(name).num_entries; return GetBlock(name).num_entries;
} }
inline std::uint64_t GetBlockSize(const std::string &name) const inline uint64_t GetBlockSize(const std::string &name) const { return GetBlock(name).byte_size; }
{
return GetBlock(name).byte_size;
}
inline bool HasBlock(const std::string &name) const inline bool HasBlock(const std::string &name) const
{ {
return blocks.find(name) != blocks.end(); return blocks.find(name) != blocks.end();
} }
inline uint64_t GetSizeOfLayout() const
{
uint64_t result = 0;
for (const auto &name_and_block : blocks)
{
result += GetBlockSize(name_and_block.first) + BLOCK_ALIGNMENT;
}
return result;
}
template <typename T> inline T *GetBlockPtr(char *shared_memory, const std::string &name) const
{
static_assert(BLOCK_ALIGNMENT % std::alignment_of<T>::value == 0,
"Datatype does not fit alignment constraints.");
char *ptr = (char *)GetAlignedBlockPtr(shared_memory, name);
return (T *)ptr;
}
// Depending on the name prefix this function either lists all blocks with the same prefix // Depending on the name prefix this function either lists all blocks with the same prefix
// or all entries in the sub-directory. // or all entries in the sub-directory.
// '/ch/edge' -> '/ch/edge_filter/0/blocks', '/ch/edge_filter/1/blocks' // '/ch/edge' -> '/ch/edge_filter/0/blocks', '/ch/edge_filter/1/blocks'
@@ -99,10 +115,10 @@ class BaseDataLayout
} }
} }
virtual inline void *GetBlockPtr(void *base_ptr, const std::string &name) const = 0; private:
virtual inline std::uint64_t GetSizeOfLayout() const = 0; friend void serialization::read(io::BufferReader &reader, DataLayout &layout);
friend void serialization::write(io::BufferWriter &writer, const DataLayout &layout);
protected:
const Block &GetBlock(const std::string &name) const const Block &GetBlock(const std::string &name) const
{ {
auto iter = blocks.find(name); auto iter = blocks.find(name);
@@ -114,42 +130,10 @@ class BaseDataLayout
return iter->second; return iter->second;
} }
friend void serialization::read(io::BufferReader &reader, BaseDataLayout &layout);
friend void serialization::write(io::BufferWriter &writer, const BaseDataLayout &layout);
std::map<std::string, Block> blocks;
};
class ContiguousDataLayout final : public BaseDataLayout
{
public:
inline std::uint64_t GetSizeOfLayout() const override final
{
std::uint64_t result = 0;
for (const auto &name_and_block : blocks)
{
result += GetBlockSize(name_and_block.first) + BLOCK_ALIGNMENT;
}
return result;
}
inline void *GetBlockPtr(void *base_ptr, const std::string &name) const override final
{
// TODO: re-enable this alignment checking somehow
// static_assert(BLOCK_ALIGNMENT % std::alignment_of<T>::value == 0,
// "Datatype does not fit alignment constraints.");
return GetAlignedBlockPtr(base_ptr, name);
}
private:
friend void serialization::read(io::BufferReader &reader, BaseDataLayout &layout);
friend void serialization::write(io::BufferWriter &writer, const BaseDataLayout &layout);
// Fit aligned storage in buffer to 64 bytes to conform with AVX 512 types // Fit aligned storage in buffer to 64 bytes to conform with AVX 512 types
inline void *align(void *&ptr) const noexcept inline void *align(void *&ptr) const noexcept
{ {
const auto intptr = reinterpret_cast<std::uintptr_t>(ptr); const auto intptr = reinterpret_cast<uintptr_t>(ptr);
const auto aligned = (intptr - 1u + BLOCK_ALIGNMENT) & -BLOCK_ALIGNMENT; const auto aligned = (intptr - 1u + BLOCK_ALIGNMENT) & -BLOCK_ALIGNMENT;
return ptr = reinterpret_cast<void *>(aligned); return ptr = reinterpret_cast<void *>(aligned);
} }
@@ -173,27 +157,7 @@ class ContiguousDataLayout final : public BaseDataLayout
} }
static constexpr std::size_t BLOCK_ALIGNMENT = 64; static constexpr std::size_t BLOCK_ALIGNMENT = 64;
}; std::map<std::string, Block> blocks;
class TarDataLayout final : public BaseDataLayout
{
public:
inline std::uint64_t GetSizeOfLayout() const override final
{
std::uint64_t result = 0;
for (const auto &name_and_block : blocks)
{
result += GetBlockSize(name_and_block.first);
}
return result;
}
inline void *GetBlockPtr(void *base_ptr, const std::string &name) const override final
{
auto offset = GetBlock(name).offset;
const auto offset_address = reinterpret_cast<std::uintptr_t>(base_ptr) + offset;
return reinterpret_cast<void *>(offset_address);
}
}; };
struct SharedRegion struct SharedRegion
@@ -201,7 +165,7 @@ struct SharedRegion
static constexpr const int MAX_NAME_LENGTH = 254; static constexpr const int MAX_NAME_LENGTH = 254;
SharedRegion() : name{0}, timestamp{0} {} SharedRegion() : name{0}, timestamp{0} {}
SharedRegion(const std::string &name_, std::uint64_t timestamp, std::uint16_t shm_key) SharedRegion(const std::string &name_, std::uint64_t timestamp, std::uint8_t shm_key)
: name{0}, timestamp{timestamp}, shm_key{shm_key} : name{0}, timestamp{timestamp}, shm_key{shm_key}
{ {
std::copy_n(name_.begin(), std::min<std::size_t>(MAX_NAME_LENGTH, name_.size()), name); std::copy_n(name_.begin(), std::min<std::size_t>(MAX_NAME_LENGTH, name_.size()), name);
@@ -211,14 +175,14 @@ struct SharedRegion
char name[MAX_NAME_LENGTH + 1]; char name[MAX_NAME_LENGTH + 1];
std::uint64_t timestamp; std::uint64_t timestamp;
std::uint16_t shm_key; std::uint8_t shm_key;
}; };
// Keeps a list of all shared regions in a fixed-sized struct // Keeps a list of all shared regions in a fixed-sized struct
// for fast access and deserialization. // for fast access and deserialization.
struct SharedRegionRegister struct SharedRegionRegister
{ {
using RegionID = std::uint16_t; using RegionID = std::uint8_t;
static constexpr const RegionID INVALID_REGION_ID = std::numeric_limits<RegionID>::max(); static constexpr const RegionID INVALID_REGION_ID = std::numeric_limits<RegionID>::max();
using ShmKey = decltype(SharedRegion::shm_key); using ShmKey = decltype(SharedRegion::shm_key);
@@ -286,11 +250,12 @@ struct SharedRegionRegister
void ReleaseKey(ShmKey key) { shm_key_in_use[key] = false; } void ReleaseKey(ShmKey key) { shm_key_in_use[key] = false; }
static constexpr const std::size_t MAX_SHARED_REGIONS = 512; static constexpr const std::uint8_t MAX_SHARED_REGIONS =
std::numeric_limits<RegionID>::max() - 1;
static_assert(MAX_SHARED_REGIONS < std::numeric_limits<RegionID>::max(), static_assert(MAX_SHARED_REGIONS < std::numeric_limits<RegionID>::max(),
"Number of shared memory regions needs to be less than the region id size."); "Number of shared memory regions needs to be less than the region id size.");
static constexpr const std::size_t MAX_SHM_KEYS = MAX_SHARED_REGIONS * 2; static constexpr const std::uint8_t MAX_SHM_KEYS = std::numeric_limits<std::uint8_t>::max() - 1;
static constexpr const char *name = "osrm-region"; static constexpr const char *name = "osrm-region";
@@ -298,7 +263,7 @@ struct SharedRegionRegister
std::array<SharedRegion, MAX_SHARED_REGIONS> regions; std::array<SharedRegion, MAX_SHARED_REGIONS> regions;
std::array<bool, MAX_SHM_KEYS> shm_key_in_use; std::array<bool, MAX_SHM_KEYS> shm_key_in_use;
}; };
} // namespace storage }
} // namespace osrm }
#endif /* SHARED_DATA_TYPE_HPP */ #endif /* SHARED_DATA_TYPE_HPP */
+9 -10
View File
@@ -34,10 +34,10 @@ namespace storage
struct OSRMLockFile struct OSRMLockFile
{ {
template <typename IdentifierT> boost::filesystem::path operator()(const IdentifierT &id) boost::filesystem::path operator()()
{ {
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path(); boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
boost::filesystem::path lock_file = temp_dir / ("osrm-" + std::to_string(id) + ".lock"); boost::filesystem::path lock_file = temp_dir / "osrm.lock";
return lock_file; return lock_file;
} }
}; };
@@ -93,7 +93,7 @@ class SharedMemory
try try
{ {
OSRMLockFile lock_file; OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file(id).string().c_str(), id); boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
result = RegionExists(key); result = RegionExists(key);
} }
catch (...) catch (...)
@@ -106,7 +106,7 @@ class SharedMemory
template <typename IdentifierT> static bool Remove(const IdentifierT id) template <typename IdentifierT> static bool Remove(const IdentifierT id)
{ {
OSRMLockFile lock_file; OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file(id).string().c_str(), id); boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
return Remove(key); return Remove(key);
} }
@@ -287,11 +287,10 @@ class SharedMemory
template <typename IdentifierT, typename LockFileT = OSRMLockFile> template <typename IdentifierT, typename LockFileT = OSRMLockFile>
std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint64_t size = 0) std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint64_t size = 0)
{ {
static_assert(sizeof(id) == sizeof(std::uint16_t), "Key type is not 16 bits");
try try
{ {
LockFileT lock_file; LockFileT lock_file;
if (!boost::filesystem::exists(lock_file(id))) if (!boost::filesystem::exists(lock_file()))
{ {
if (0 == size) if (0 == size)
{ {
@@ -299,10 +298,10 @@ std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint
} }
else else
{ {
boost::filesystem::ofstream ofs(lock_file(id)); boost::filesystem::ofstream ofs(lock_file());
} }
} }
return std::make_unique<SharedMemory>(lock_file(id), id, size); return std::make_unique<SharedMemory>(lock_file(), id, size);
} }
catch (const boost::interprocess::interprocess_exception &e) catch (const boost::interprocess::interprocess_exception &e)
{ {
@@ -311,7 +310,7 @@ std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint
throw util::exception(e.what() + SOURCE_REF); throw util::exception(e.what() + SOURCE_REF);
} }
} }
} // namespace storage }
} // namespace osrm }
#endif // SHARED_MEMORY_HPP #endif // SHARED_MEMORY_HPP
+4 -6
View File
@@ -33,7 +33,7 @@ template <class Lock> class InvertedLock
InvertedLock(Lock &lock) : lock(lock) { lock.unlock(); } InvertedLock(Lock &lock) : lock(lock) { lock.unlock(); }
~InvertedLock() { lock.lock(); } ~InvertedLock() { lock.lock(); }
}; };
} // namespace }
// The shared monitor implementation based on a semaphore and mutex // The shared monitor implementation based on a semaphore and mutex
template <typename Data> struct SharedMonitor template <typename Data> struct SharedMonitor
@@ -146,9 +146,7 @@ template <typename Data> struct SharedMonitor
// like two-turnstile reusable barrier or boost/interprocess/sync/spin/condition.hpp // like two-turnstile reusable barrier or boost/interprocess/sync/spin/condition.hpp
// fail if a waiter is killed. // fail if a waiter is killed.
// Buffer size needs to be large enough to hold all the semaphores for every static constexpr int buffer_size = 256;
// listener you want to support.
static constexpr int buffer_size = 4096 * 4;
struct InternalData struct InternalData
{ {
@@ -234,8 +232,8 @@ template <typename Data> struct SharedMonitor
bi::shared_memory_object shmem; bi::shared_memory_object shmem;
bi::mapped_region region; bi::mapped_region region;
}; };
} // namespace storage }
} // namespace osrm }
#undef USE_BOOST_INTERPROCESS_CONDITION #undef USE_BOOST_INTERPROCESS_CONDITION
+3 -9
View File
@@ -35,28 +35,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <string> #include <string>
#include <vector>
namespace osrm namespace osrm
{ {
namespace storage namespace storage
{ {
void populateLayoutFromFile(const boost::filesystem::path &path, storage::BaseDataLayout &layout);
class Storage class Storage
{ {
public: public:
Storage(StorageConfig config); Storage(StorageConfig config);
int Run(int max_wait, const std::string &name, bool only_metric); int Run(int max_wait, const std::string &name, bool only_metric);
void PopulateStaticLayout(DataLayout &layout);
void PopulateUpdatableLayout(DataLayout &layout);
void PopulateStaticData(const SharedDataIndex &index); void PopulateStaticData(const SharedDataIndex &index);
void PopulateUpdatableData(const SharedDataIndex &index); void PopulateUpdatableData(const SharedDataIndex &index);
void PopulateLayout(storage::BaseDataLayout &layout,
const std::vector<std::pair<bool, boost::filesystem::path>> &files);
std::string PopulateLayoutWithRTree(storage::BaseDataLayout &layout);
std::vector<std::pair<bool, boost::filesystem::path>> GetUpdatableFiles();
std::vector<std::pair<bool, boost::filesystem::path>> GetStaticFiles();
private: private:
StorageConfig config; StorageConfig config;
+5 -21
View File
@@ -294,14 +294,11 @@ inline auto make_filtered_cell_metric_view(const SharedDataIndex &index,
auto prefix = name + "/exclude/" + std::to_string(exclude_index); auto prefix = name + "/exclude/" + std::to_string(exclude_index);
auto weights_block_id = prefix + "/weights"; auto weights_block_id = prefix + "/weights";
auto durations_block_id = prefix + "/durations"; auto durations_block_id = prefix + "/durations";
auto distances_block_id = prefix + "/distances";
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id); auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id); auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
return customizer::CellMetricView{ return customizer::CellMetricView{std::move(weights), std::move(durations)};
std::move(weights), std::move(durations), std::move(distances)};
} }
inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name) inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name)
@@ -314,14 +311,12 @@ inline auto make_cell_metric_view(const SharedDataIndex &index, const std::strin
{ {
auto weights_block_id = prefix + "/weights"; auto weights_block_id = prefix + "/weights";
auto durations_block_id = prefix + "/durations"; auto durations_block_id = prefix + "/durations";
auto distances_block_id = prefix + "/distances";
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id); auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id); auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
cell_metric_excludes.push_back(customizer::CellMetricView{ cell_metric_excludes.push_back(
std::move(weights), std::move(durations), std::move(distances)}); customizer::CellMetricView{std::move(weights), std::move(durations)});
} }
return cell_metric_excludes; return cell_metric_excludes;
@@ -335,20 +330,9 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std:
index, name + "/edge_array"); index, name + "/edge_array");
auto node_to_offset = make_vector_view<customizer::MultiLevelEdgeBasedGraphView::EdgeOffset>( auto node_to_offset = make_vector_view<customizer::MultiLevelEdgeBasedGraphView::EdgeOffset>(
index, name + "/node_to_edge_offset"); index, name + "/node_to_edge_offset");
auto node_weights = make_vector_view<EdgeWeight>(index, name + "/node_weights");
auto node_durations = make_vector_view<EdgeDuration>(index, name + "/node_durations");
auto node_distances = make_vector_view<EdgeDistance>(index, name + "/node_distances");
auto is_forward_edge = make_vector_view<bool>(index, name + "/is_forward_edge");
auto is_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge");
return customizer::MultiLevelEdgeBasedGraphView(std::move(node_list), return customizer::MultiLevelEdgeBasedGraphView(
std::move(edge_list), std::move(node_list), std::move(edge_list), std::move(node_to_offset));
std::move(node_to_offset),
std::move(node_weights),
std::move(node_durations),
std::move(node_distances),
std::move(is_forward_edge),
std::move(is_backward_edge));
} }
inline auto make_maneuver_overrides_views(const SharedDataIndex &index, const std::string &name) inline auto make_maneuver_overrides_views(const SharedDataIndex &index, const std::string &name)
+4 -12
View File
@@ -17,23 +17,15 @@ class Updater
public: public:
Updater(UpdaterConfig config_) : config(std::move(config_)) {} Updater(UpdaterConfig config_) : config(std::move(config_)) {}
using NumNodesAndEdges =
std::tuple<EdgeID, std::vector<extractor::EdgeBasedEdge>, std::uint32_t>;
NumNodesAndEdges LoadAndUpdateEdgeExpandedGraph() const;
EdgeID EdgeID
LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list, LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights, std::vector<EdgeWeight> &node_weights,
std::uint32_t &connectivity_checksum) const; std::uint32_t &connectivity_checksum) const;
EdgeID LoadAndUpdateEdgeExpandedGraph(
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights,
std::vector<EdgeDuration> &node_durations, // TODO: remove when optional
std::uint32_t &connectivity_checksum) const;
EdgeID LoadAndUpdateEdgeExpandedGraph(
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights,
std::vector<EdgeDuration> &node_durations, // TODO: remove when optional
std::vector<EdgeDistance> &node_distances, // TODO: remove when optional
std::uint32_t &connectivity_checksum) const;
private: private:
UpdaterConfig config; UpdaterConfig config;
}; };
+1 -2
View File
@@ -53,8 +53,7 @@ struct UpdaterConfig final : storage::IOConfig
".osrm.geometry", ".osrm.geometry",
".osrm.fileIndex", ".osrm.fileIndex",
".osrm.properties", ".osrm.properties",
".osrm.restrictions", ".osrm.restrictions"},
".osrm.enw"},
{}, {},
{".osrm.datasource_names"}), {".osrm.datasource_names"}),
valid_now(0) valid_now(0)
-3
View File
@@ -43,9 +43,6 @@ inline double radToDeg(const double radian)
//! Takes the squared euclidean distance of the input coordinates. Does not return meters! //! Takes the squared euclidean distance of the input coordinates. Does not return meters!
std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs); std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs);
double fccApproximateDistance(const Coordinate first_coordinate,
const Coordinate second_coordinate);
double haversineDistance(const Coordinate first_coordinate, const Coordinate second_coordinate); double haversineDistance(const Coordinate first_coordinate, const Coordinate second_coordinate);
double greatCircleDistance(const Coordinate first_coordinate, const Coordinate second_coordinate); double greatCircleDistance(const Coordinate first_coordinate, const Coordinate second_coordinate);
+1 -20
View File
@@ -1,11 +1,9 @@
#ifndef OSRM_UTIL_DEBUG_HPP_ #ifndef OSRM_UTIL_DEBUG_HPP_
#define OSRM_UTIL_DEBUG_HPP_ #define OSRM_UTIL_DEBUG_HPP_
#include "extractor/edge_based_edge.hpp"
#include "extractor/node_data_container.hpp" #include "extractor/node_data_container.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "guidance/intersection.hpp" #include "guidance/intersection.hpp"
#include "guidance/turn_instruction.hpp"
#include "guidance/turn_lane_data.hpp" #include "guidance/turn_lane_data.hpp"
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
@@ -24,7 +22,7 @@ namespace util
inline std::ostream &operator<<(std::ostream &out, const Coordinate &coordinate) inline std::ostream &operator<<(std::ostream &out, const Coordinate &coordinate)
{ {
out << std::setprecision(12) << "{" << toFloating(coordinate.lon) << ", " out << std::setprecision(12) << "{" << toFloating(coordinate.lon) << ", "
<< toFloating(coordinate.lat) << "}"; << toFloating(coordinate.lon) << "}";
return out; return out;
} }
} }
@@ -188,23 +186,6 @@ inline std::ostream &operator<<(std::ostream &out, const LaneDataVector &turn_la
} }
} }
} }
namespace extractor
{
inline std::ostream &operator<<(std::ostream &out, const EdgeBasedEdge &edge)
{
out << " EdgeBasedEdge {";
out << " source " << edge.source << ", target: " << edge.target;
out << " EdgeBasedEdgeData data {";
out << " turn_id: " << edge.data.turn_id << ", weight: " << edge.data.weight;
out << " distance: " << edge.data.distance << ", duration: " << edge.data.duration;
out << " forward: " << (edge.data.forward == 0 ? "false" : "true")
<< ", backward: " << (edge.data.backward == 0 ? "false" : "true");
out << " }";
out << "}";
return out;
}
}
} }
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/ #endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
+5 -5
View File
@@ -413,11 +413,6 @@ template <typename EdgeDataT> class DynamicGraph
util::inplacePermutation(node_array.begin(), node_array.end(), old_to_new_node); util::inplacePermutation(node_array.begin(), node_array.end(), old_to_new_node);
// Build up edge permutation // Build up edge permutation
if (edge_list.size() >= std::numeric_limits<EdgeID>::max())
{
throw util::exception("There are too many edges, OSRM only supports 2^32" + SOURCE_REF);
}
EdgeID new_edge_index = 0; EdgeID new_edge_index = 0;
std::vector<EdgeID> old_to_new_edge(edge_list.size(), SPECIAL_EDGEID); std::vector<EdgeID> old_to_new_edge(edge_list.size(), SPECIAL_EDGEID);
for (auto node : util::irange<NodeID>(0, number_of_nodes)) for (auto node : util::irange<NodeID>(0, number_of_nodes))
@@ -426,6 +421,11 @@ template <typename EdgeDataT> class DynamicGraph
// move all filled edges // move all filled edges
for (auto edge : GetAdjacentEdgeRange(node)) for (auto edge : GetAdjacentEdgeRange(node))
{ {
if (new_edge_index == std::numeric_limits<EdgeID>::max())
{
throw util::exception("There are too many edges, OSRM only supports 2^32" +
SOURCE_REF);
}
edge_list[edge].target = old_to_new_node[edge_list[edge].target]; edge_list[edge].target = old_to_new_node[edge_list[edge].target];
BOOST_ASSERT(edge_list[edge].target != SPECIAL_NODEID); BOOST_ASSERT(edge_list[edge].target != SPECIAL_NODEID);
old_to_new_edge[edge] = new_edge_index++; old_to_new_edge[edge] = new_edge_index++;
-517
View File
@@ -1,517 +0,0 @@
#ifndef IEEE754_HPP
#define IEEE754_HPP
/**
Copyright (C) 2014 Milo Yip
Imported from:
https://github.com/miloyip/dtoa-benchmark/blob/c4020c62754950d38a1aaaed2975b05b441d1e7d/src/milo/dtoa_milo.h
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
**/
#include <assert.h>
#include <math.h>
#if defined(_MSC_VER)
#include "rapidjson/msinttypes/stdint.h"
#include <intrin.h>
#else
#include <stdint.h>
#endif
#define UINT64_C2(h, l) ((static_cast<uint64_t>(h) << 32) | static_cast<uint64_t>(l))
namespace osrm
{
namespace util
{
namespace ieee754
{
struct DiyFp
{
DiyFp() {}
DiyFp(uint64_t f, int e) : f(f), e(e) {}
DiyFp(double d)
{
union {
double d;
uint64_t u64;
} u = {d};
int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
uint64_t significand = (u.u64 & kDpSignificandMask);
if (biased_e != 0)
{
f = significand + kDpHiddenBit;
e = biased_e - kDpExponentBias;
}
else
{
f = significand;
e = kDpMinExponent + 1;
}
}
DiyFp operator-(const DiyFp &rhs) const
{
assert(e == rhs.e);
assert(f >= rhs.f);
return DiyFp(f - rhs.f, e);
}
DiyFp operator*(const DiyFp &rhs) const
{
#if defined(_MSC_VER) && defined(_M_AMD64)
uint64_t h;
uint64_t l = _umul128(f, rhs.f, &h);
if (l & (uint64_t(1) << 63)) // rounding
h++;
return DiyFp(h, e + rhs.e + 64);
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
unsigned __int128 p =
static_cast<unsigned __int128>(f) * static_cast<unsigned __int128>(rhs.f);
uint64_t h = p >> 64;
uint64_t l = static_cast<uint64_t>(p);
if (l & (uint64_t(1) << 63)) // rounding
h++;
return DiyFp(h, e + rhs.e + 64);
#else
const uint64_t M32 = 0xFFFFFFFF;
const uint64_t a = f >> 32;
const uint64_t b = f & M32;
const uint64_t c = rhs.f >> 32;
const uint64_t d = rhs.f & M32;
const uint64_t ac = a * c;
const uint64_t bc = b * c;
const uint64_t ad = a * d;
const uint64_t bd = b * d;
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
tmp += 1U << 31; /// mult_round
return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
#endif
}
DiyFp Normalize() const
{
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
return DiyFp(f << (63 - index), e - (63 - index));
#elif defined(__GNUC__)
int s = __builtin_clzll(f);
return DiyFp(f << s, e - s);
#else
DiyFp res = *this;
while (!(res.f & kDpHiddenBit))
{
res.f <<= 1;
res.e--;
}
res.f <<= (kDiySignificandSize - kDpSignificandSize - 1);
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1);
return res;
#endif
}
DiyFp NormalizeBoundary() const
{
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
return DiyFp(f << (63 - index), e - (63 - index));
#else
DiyFp res = *this;
while (!(res.f & (kDpHiddenBit << 1)))
{
res.f <<= 1;
res.e--;
}
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
return res;
#endif
}
void NormalizedBoundaries(DiyFp *minus, DiyFp *plus) const
{
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
mi.f <<= mi.e - pl.e;
mi.e = pl.e;
*plus = pl;
*minus = mi;
}
static const int kDiySignificandSize = 64;
static const int kDpSignificandSize = 52;
static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
static const int kDpMinExponent = -kDpExponentBias;
static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000);
static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000);
uint64_t f;
int e;
};
inline DiyFp GetCachedPower(int e, int *K)
{
// 10^-348, 10^-340, ..., 10^340
static const uint64_t kCachedPowers_F[] = {
UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76),
UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea),
UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df),
UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f),
UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c),
UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5),
UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d),
UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637),
UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7),
UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5),
UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b),
UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996),
UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8),
UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053),
UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd),
UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94),
UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b),
UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac),
UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3),
UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb),
UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c),
UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000),
UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984),
UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70),
UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245),
UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8),
UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a),
UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea),
UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85),
UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2),
UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3),
UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25),
UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece),
UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5),
UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a),
UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a),
UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129),
UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429),
UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d),
UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841),
UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9),
UINT64_C2(0xaf87023b, 0x9bf0ee6b)};
static const int16_t kCachedPowers_E[] = {
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, -927, -901,
-874, -847, -821, -794, -768, -741, -715, -688, -661, -635, -608, -582, -555,
-529, -502, -475, -449, -422, -396, -369, -343, -316, -289, -263, -236, -210,
-183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136,
162, 189, 216, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481,
508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827,
853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
// int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
double dk =
(-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
int k = static_cast<int>(dk);
if (k != dk)
k++;
unsigned index = static_cast<unsigned>((k >> 3) + 1);
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0]));
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
}
inline void
GrisuRound(char *buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w)
{
while (rest < wp_w && delta - rest >= ten_kappa && (rest + ten_kappa < wp_w || /// closer
wp_w - rest > rest + ten_kappa - wp_w))
{
buffer[len - 1]--;
rest += ten_kappa;
}
}
inline unsigned CountDecimalDigit32(uint32_t n)
{
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
if (n < 10)
return 1;
if (n < 100)
return 2;
if (n < 1000)
return 3;
if (n < 10000)
return 4;
if (n < 100000)
return 5;
if (n < 1000000)
return 6;
if (n < 10000000)
return 7;
if (n < 100000000)
return 8;
if (n < 1000000000)
return 9;
return 10;
}
inline void
DigitGen(const DiyFp &W, const DiyFp &Mp, uint64_t delta, char *buffer, int *len, int *K)
{
static const uint32_t kPow10[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1);
int kappa = static_cast<int>(CountDecimalDigit32(p1));
*len = 0;
while (kappa > 0)
{
uint32_t d;
switch (kappa)
{
case 10:
d = p1 / 1000000000;
p1 %= 1000000000;
break;
case 9:
d = p1 / 100000000;
p1 %= 100000000;
break;
case 8:
d = p1 / 10000000;
p1 %= 10000000;
break;
case 7:
d = p1 / 1000000;
p1 %= 1000000;
break;
case 6:
d = p1 / 100000;
p1 %= 100000;
break;
case 5:
d = p1 / 10000;
p1 %= 10000;
break;
case 4:
d = p1 / 1000;
p1 %= 1000;
break;
case 3:
d = p1 / 100;
p1 %= 100;
break;
case 2:
d = p1 / 10;
p1 %= 10;
break;
case 1:
d = p1;
p1 = 0;
break;
default:
#if defined(_MSC_VER)
__assume(0);
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
__builtin_unreachable();
#else
d = 0;
#endif
}
if (d || *len)
buffer[(*len)++] = '0' + static_cast<char>(d);
kappa--;
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
if (tmp <= delta)
{
*K += kappa;
GrisuRound(
buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
return;
}
}
// kappa = 0
for (;;)
{
p2 *= 10;
delta *= 10;
char d = static_cast<char>(p2 >> -one.e);
if (d || *len)
buffer[(*len)++] = '0' + d;
p2 &= one.f - 1;
kappa--;
if (p2 < delta)
{
*K += kappa;
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
return;
}
}
}
inline void Grisu2(double value, char *buffer, int *length, int *K)
{
const DiyFp v(value);
DiyFp w_m, w_p;
v.NormalizedBoundaries(&w_m, &w_p);
const DiyFp c_mk = GetCachedPower(w_p.e, K);
const DiyFp W = v.Normalize() * c_mk;
DiyFp Wp = w_p * c_mk;
DiyFp Wm = w_m * c_mk;
Wm.f++;
Wp.f--;
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
}
inline const char *GetDigitsLut()
{
static const char cDigitsLut[200] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0',
'8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6',
'1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2',
'5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3',
'3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', '4',
'2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0',
'5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5',
'9', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7',
'6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7',
'6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
'8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9',
'3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'};
return cDigitsLut;
}
inline void WriteExponent(int K, char *buffer)
{
if (K < 0)
{
*buffer++ = '-';
K = -K;
}
if (K >= 100)
{
*buffer++ = '0' + static_cast<char>(K / 100);
K %= 100;
const char *d = GetDigitsLut() + K * 2;
*buffer++ = d[0];
*buffer++ = d[1];
}
else if (K >= 10)
{
const char *d = GetDigitsLut() + K * 2;
*buffer++ = d[0];
*buffer++ = d[1];
}
else
*buffer++ = '0' + static_cast<char>(K);
*buffer = '\0';
}
inline void Prettify(char *buffer, int length, int k)
{
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
if (length <= kk && kk <= 21)
{
// 1234e7 -> 12340000000
for (int i = length; i < kk; i++)
buffer[i] = '0';
buffer[kk] = '.';
buffer[kk + 1] = '0';
buffer[kk + 2] = '\0';
}
else if (0 < kk && kk <= 21)
{
// 1234e-2 -> 12.34
memmove(&buffer[kk + 1], &buffer[kk], length - kk);
buffer[kk] = '.';
buffer[length + 1] = '\0';
}
else if (-6 < kk && kk <= 0)
{
// 1234e-6 -> 0.001234
const int offset = 2 - kk;
memmove(&buffer[offset], &buffer[0], length);
buffer[0] = '0';
buffer[1] = '.';
for (int i = 2; i < offset; i++)
buffer[i] = '0';
buffer[length + offset] = '\0';
}
else if (length == 1)
{
// 1e30
buffer[1] = 'e';
WriteExponent(kk - 1, &buffer[2]);
}
else
{
// 1234e30 -> 1.234e33
memmove(&buffer[2], &buffer[1], length - 1);
buffer[1] = '.';
buffer[length + 1] = 'e';
WriteExponent(kk - 1, &buffer[0 + length + 2]);
}
}
inline void dtoa_milo(double value, char *buffer)
{
// Not handling NaN and inf
assert(!isnan(value));
assert(!isinf(value));
if (value == 0)
{
buffer[0] = '0';
buffer[1] = '.';
buffer[2] = '0';
buffer[3] = '\0';
}
else
{
if (value < 0)
{
*buffer++ = '-';
value = -value;
}
int length, K;
Grisu2(value, buffer, &length, &K);
Prettify(buffer, length, K);
}
}
} // namespace ieee754
} // namespace util
} // namespace osrm
#endif // IEEE754_HPP
+2 -31
View File
@@ -5,7 +5,6 @@
#define JSON_RENDERER_HPP #define JSON_RENDERER_HPP
#include "util/cast.hpp" #include "util/cast.hpp"
#include "util/ieee754.hpp"
#include "util/string_util.hpp" #include "util/string_util.hpp"
#include "osrm/json_container.hpp" #include "osrm/json_container.hpp"
@@ -22,11 +21,6 @@ namespace util
namespace json namespace json
{ {
namespace
{
constexpr int MAX_FLOAT_STRING_LENGTH = 256;
}
struct Renderer struct Renderer
{ {
explicit Renderer(std::ostream &_out) : out(_out) {} explicit Renderer(std::ostream &_out) : out(_out) {}
@@ -40,31 +34,8 @@ struct Renderer
void operator()(const Number &number) const void operator()(const Number &number) const
{ {
char buffer[MAX_FLOAT_STRING_LENGTH] = {'\0'}; out.precision(10);
ieee754::dtoa_milo(number.value, buffer); out << number.value;
// Trucate to 10 decimal places
int pos = 0;
int decimalpos = 0;
while (decimalpos == 0 && pos < MAX_FLOAT_STRING_LENGTH && buffer[pos] != 0)
{
if (buffer[pos] == '.')
{
decimalpos = pos;
break;
}
++pos;
}
while (pos < MAX_FLOAT_STRING_LENGTH && buffer[pos] != 0)
{
if (pos - decimalpos == 10)
{
buffer[pos] = '\0';
break;
}
++pos;
}
out << buffer;
} }
void operator()(const Object &object) const void operator()(const Object &object) const
+16 -17
View File
@@ -15,14 +15,14 @@ namespace util
namespace detail namespace detail
{ {
template <typename T, typename MmapContainerT> template <typename T, typename RegionT>
util::vector_view<T> mmapFile(const boost::filesystem::path &file, MmapContainerT &mmap_container) util::vector_view<T> mmapFile(const boost::filesystem::path &file, RegionT &region)
{ {
try try
{ {
mmap_container.open(file); region.open(file);
std::size_t num_objects = mmap_container.size() / sizeof(T); std::size_t num_objects = region.size() / sizeof(T);
auto data_ptr = mmap_container.data(); auto data_ptr = region.data();
BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(T) == 0); BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(T) == 0);
return util::vector_view<T>(reinterpret_cast<T *>(data_ptr), num_objects); return util::vector_view<T>(reinterpret_cast<T *>(data_ptr), num_objects);
} }
@@ -34,10 +34,9 @@ util::vector_view<T> mmapFile(const boost::filesystem::path &file, MmapContainer
} }
} }
template <typename T, typename MmapContainerT> template <typename T, typename RegionT>
util::vector_view<T> mmapFile(const boost::filesystem::path &file, util::vector_view<T>
MmapContainerT &mmap_container, mmapFile(const boost::filesystem::path &file, RegionT &region, const std::size_t size)
const std::size_t size)
{ {
try try
{ {
@@ -46,10 +45,10 @@ util::vector_view<T> mmapFile(const boost::filesystem::path &file,
params.path = file.string(); params.path = file.string();
params.flags = boost::iostreams::mapped_file::readwrite; params.flags = boost::iostreams::mapped_file::readwrite;
params.new_file_size = size; params.new_file_size = size;
mmap_container.open(params); region.open(params);
std::size_t num_objects = size / sizeof(T); std::size_t num_objects = size / sizeof(T);
auto data_ptr = mmap_container.data(); auto data_ptr = region.data();
BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(T) == 0); BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(T) == 0);
return util::vector_view<T>(reinterpret_cast<T *>(data_ptr), num_objects); return util::vector_view<T>(reinterpret_cast<T *>(data_ptr), num_objects);
} }
@@ -64,24 +63,24 @@ util::vector_view<T> mmapFile(const boost::filesystem::path &file,
template <typename T> template <typename T>
util::vector_view<const T> mmapFile(const boost::filesystem::path &file, util::vector_view<const T> mmapFile(const boost::filesystem::path &file,
boost::iostreams::mapped_file_source &mmap_container) boost::iostreams::mapped_file_source &region)
{ {
return detail::mmapFile<const T>(file, mmap_container); return detail::mmapFile<const T>(file, region);
} }
template <typename T> template <typename T>
util::vector_view<T> mmapFile(const boost::filesystem::path &file, util::vector_view<T> mmapFile(const boost::filesystem::path &file,
boost::iostreams::mapped_file &mmap_container) boost::iostreams::mapped_file &region)
{ {
return detail::mmapFile<T>(file, mmap_container); return detail::mmapFile<T>(file, region);
} }
template <typename T> template <typename T>
util::vector_view<T> mmapFile(const boost::filesystem::path &file, util::vector_view<T> mmapFile(const boost::filesystem::path &file,
boost::iostreams::mapped_file &mmap_container, boost::iostreams::mapped_file &region,
std::size_t size) std::size_t size)
{ {
return detail::mmapFile<T>(file, mmap_container, size); return detail::mmapFile<T>(file, region, size);
} }
} }
} }
+4 -10
View File
@@ -9,7 +9,6 @@
#include <tbb/parallel_sort.h> #include <tbb/parallel_sort.h>
#include <iostream>
#include <memory> #include <memory>
#include <utility> #include <utility>
@@ -21,27 +20,24 @@ namespace util
struct NodeBasedEdgeData struct NodeBasedEdgeData
{ {
NodeBasedEdgeData() NodeBasedEdgeData()
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), : weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), geometry_id({0, false}),
distance(INVALID_EDGE_DISTANCE), geometry_id({0, false}), reversed(false), reversed(false), annotation_data(-1)
annotation_data(-1)
{ {
} }
NodeBasedEdgeData(EdgeWeight weight, NodeBasedEdgeData(EdgeWeight weight,
EdgeWeight duration, EdgeWeight duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
bool reversed, bool reversed,
extractor::NodeBasedEdgeClassification flags, extractor::NodeBasedEdgeClassification flags,
AnnotationID annotation_data) AnnotationID annotation_data)
: weight(weight), duration(duration), distance(distance), geometry_id(geometry_id), : weight(weight), duration(duration), geometry_id(geometry_id), reversed(reversed),
reversed(reversed), flags(flags), annotation_data(annotation_data) flags(flags), annotation_data(annotation_data)
{ {
} }
EdgeWeight weight; EdgeWeight weight;
EdgeWeight duration; EdgeWeight duration;
EdgeDistance distance;
GeometryID geometry_id; GeometryID geometry_id;
bool reversed : 1; bool reversed : 1;
extractor::NodeBasedEdgeClassification flags; extractor::NodeBasedEdgeClassification flags;
@@ -84,13 +80,11 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
const extractor::NodeBasedEdge &input_edge) { const extractor::NodeBasedEdge &input_edge) {
output_edge.data.weight = input_edge.weight; output_edge.data.weight = input_edge.weight;
output_edge.data.duration = input_edge.duration; output_edge.data.duration = input_edge.duration;
output_edge.data.distance = input_edge.distance;
output_edge.data.flags = input_edge.flags; output_edge.data.flags = input_edge.flags;
output_edge.data.annotation_data = input_edge.annotation_data; output_edge.data.annotation_data = input_edge.annotation_data;
BOOST_ASSERT(output_edge.data.weight > 0); BOOST_ASSERT(output_edge.data.weight > 0);
BOOST_ASSERT(output_edge.data.duration > 0); BOOST_ASSERT(output_edge.data.duration > 0);
BOOST_ASSERT(output_edge.data.distance >= 0);
}); });
tbb::parallel_sort(edges_list.begin(), edges_list.end()); tbb::parallel_sort(edges_list.begin(), edges_list.end());
-2
View File
@@ -226,14 +226,12 @@ class QueryHeap
Data &GetData(NodeID node) Data &GetData(NodeID node)
{ {
const auto index = node_index.peek_index(node); const auto index = node_index.peek_index(node);
BOOST_ASSERT((int)index >= 0 && (int)index < (int)inserted_nodes.size());
return inserted_nodes[index].data; return inserted_nodes[index].data;
} }
Data const &GetData(NodeID node) const Data const &GetData(NodeID node) const
{ {
const auto index = node_index.peek_index(node); const auto index = node_index.peek_index(node);
BOOST_ASSERT((int)index >= 0 && (int)index < (int)inserted_nodes.size());
return inserted_nodes[index].data; return inserted_nodes[index].data;
} }
+1 -1
View File
@@ -312,7 +312,7 @@ class StaticGraph
}); });
} }
protected: // private:
NodeIterator number_of_nodes; NodeIterator number_of_nodes;
EdgeIterator number_of_edges; EdgeIterator number_of_edges;
-3
View File
@@ -75,7 +75,6 @@ using NameID = std::uint32_t;
using AnnotationID = std::uint32_t; using AnnotationID = std::uint32_t;
using EdgeWeight = std::int32_t; using EdgeWeight = std::int32_t;
using EdgeDuration = std::int32_t; using EdgeDuration = std::int32_t;
using EdgeDistance = float;
using SegmentWeight = std::uint32_t; using SegmentWeight = std::uint32_t;
using SegmentDuration = std::uint32_t; using SegmentDuration = std::uint32_t;
using TurnPenalty = std::int16_t; // turn penalty in 100ms units using TurnPenalty = std::int16_t; // turn penalty in 100ms units
@@ -113,9 +112,7 @@ static const SegmentWeight MAX_SEGMENT_WEIGHT = INVALID_SEGMENT_WEIGHT - 1;
static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1; static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1;
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max(); static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max(); static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max();
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max(); static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent // FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any // within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
+25
View File
@@ -9,6 +9,31 @@ namespace util
{ {
namespace vector_tile namespace vector_tile
{ {
const constexpr std::uint32_t ID_TAG = 1;
const constexpr std::uint32_t NAME_TAG = 1;
const constexpr std::uint32_t FEATURE_TAG = 2;
const constexpr std::uint32_t LAYER_TAG = 3;
const constexpr std::uint32_t GEOMETRY_TAG = 3;
const constexpr std::uint32_t KEY_TAG = 3;
const constexpr std::uint32_t VARIANT_TAG = 4;
const constexpr std::uint32_t EXTENT_TAG = 5;
const constexpr std::uint32_t VERSION_TAG = 15;
const constexpr std::uint32_t FEATURE_ATTRIBUTES_TAG = 2;
const constexpr std::uint32_t FEATURE_GEOMETRIES_TAG = 4;
const constexpr std::uint32_t GEOMETRY_TYPE_POINT = 1;
const constexpr std::uint32_t GEOMETRY_TYPE_LINE = 2;
const constexpr std::uint32_t VARIANT_TYPE_STRING = 1;
const constexpr std::uint32_t VARIANT_TYPE_FLOAT = 2;
const constexpr std::uint32_t VARIANT_TYPE_DOUBLE = 3;
const constexpr std::uint32_t VARIANT_TYPE_UINT64 = 5;
const constexpr std::uint32_t VARIANT_TYPE_SINT64 = 6;
const constexpr std::uint32_t VARIANT_TYPE_BOOL = 7;
// Vector tiles are 4096 virtual pixels on each side // Vector tiles are 4096 virtual pixels on each side
const constexpr double EXTENT = 4096.0; const constexpr double EXTENT = 4096.0;
const constexpr double BUFFER = 128.0; const constexpr double BUFFER = 128.0;
-15
View File
@@ -195,10 +195,7 @@ template <> class vector_view<bool>
{ {
BOOST_ASSERT_MSG(index < m_size, "invalid size"); BOOST_ASSERT_MSG(index < m_size, "invalid size");
const std::size_t bucket = index / WORD_BITS; const std::size_t bucket = index / WORD_BITS;
// Note: ordering of bits here should match packBits in storage/serialization.hpp
// so that directly mmap-ing data is possible
const auto offset = index % WORD_BITS; const auto offset = index % WORD_BITS;
BOOST_ASSERT(WORD_BITS > offset);
return m_ptr[bucket] & (static_cast<Word>(1) << offset); return m_ptr[bucket] & (static_cast<Word>(1) << offset);
} }
@@ -227,23 +224,11 @@ template <> class vector_view<bool>
{ {
BOOST_ASSERT(index < m_size); BOOST_ASSERT(index < m_size);
const auto bucket = index / WORD_BITS; const auto bucket = index / WORD_BITS;
// Note: ordering of bits here should match packBits in storage/serialization.hpp
// so that directly mmap-ing data is possible
const auto offset = index % WORD_BITS; const auto offset = index % WORD_BITS;
BOOST_ASSERT(WORD_BITS > offset);
return reference{m_ptr + bucket, static_cast<Word>(1) << offset}; return reference{m_ptr + bucket, static_cast<Word>(1) << offset};
} }
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept; template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
friend std::ostream &operator<<(std::ostream &os, const vector_view<bool> &rhs)
{
for (std::size_t i = 0; i < rhs.size(); ++i)
{
os << (i > 0 ? " " : "") << rhs.at(i);
}
return os;
}
}; };
// Both vector_view<T> and the vector_view<bool> specializations share this impl. // Both vector_view<T> and the vector_view<bool> specializations share this impl.
+636 -4483
View File
File diff suppressed because it is too large Load Diff
+3 -9
View File
@@ -1,11 +1,11 @@
{ {
"name": "osrm", "name": "osrm",
"version": "5.20.0", "version": "5.17.0",
"private": false, "private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"nan": "^2.11.1", "nan": "^2.6.2",
"node-cmake": "^2.3.2", "node-cmake": "^2.3.2",
"node-pre-gyp": "^0.6.36", "node-pre-gyp": "^0.6.36",
"rimraf": "^2.5.4" "rimraf": "^2.5.4"
@@ -18,7 +18,7 @@
}, },
"scripts": { "scripts": {
"lint": "node ./node_modules/eslint/bin/eslint.js -c ./.eslintrc features/step_definitions/ features/support/", "lint": "node ./node_modules/eslint/bin/eslint.js -c ./.eslintrc features/step_definitions/ features/support/",
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify -m mmap && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld -m mmap", "test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
"clean": "rm -rf test/cache", "clean": "rm -rf test/cache",
"docs": "./scripts/build_api_docs.sh", "docs": "./scripts/build_api_docs.sh",
"install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh", "install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh",
@@ -38,25 +38,19 @@
"node": ">=4.0.0" "node": ">=4.0.0"
}, },
"devDependencies": { "devDependencies": {
"ansi-escape-sequences": "^4.0.0",
"aws-sdk": "~2.0.31", "aws-sdk": "~2.0.31",
"babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-class-properties": "^6.24.1",
"chalk": "^1.1.3", "chalk": "^1.1.3",
"command-line-args": "^5.0.2",
"command-line-usage": "^5.0.4",
"csv-stringify": "^3.0.0",
"cucumber": "^1.2.1", "cucumber": "^1.2.1",
"d3-queue": "^2.0.3", "d3-queue": "^2.0.3",
"docbox": "^1.0.6", "docbox": "^1.0.6",
"documentation": "^4.0.0-rc.1", "documentation": "^4.0.0-rc.1",
"eslint": "^2.4.0", "eslint": "^2.4.0",
"faucet": "^0.0.1", "faucet": "^0.0.1",
"jsonpath": "^1.0.0",
"node-timeout": "0.0.4", "node-timeout": "0.0.4",
"polyline": "^0.2.0", "polyline": "^0.2.0",
"request": "^2.69.0", "request": "^2.69.0",
"tape": "^4.7.0", "tape": "^4.7.0",
"turf": "^3.0.14",
"xmlbuilder": "^4.2.1" "xmlbuilder": "^4.2.1"
}, },
"bundleDependencies": [ "bundleDependencies": [
+15 -18
View File
@@ -38,10 +38,20 @@ function setup()
mode.pushing_bike mode.pushing_bike
}, },
barrier_blacklist = Set { barrier_whitelist = Set {
'yes', 'sump_buster',
'wall', 'bus_trap',
'fence' 'cycle_barrier',
'bollard',
'entrance',
'cattle_grid',
'border_control',
'toll_booth',
'sally_port',
'gate',
'lift_gate',
'no',
'block'
}, },
access_tag_whitelist = Set { access_tag_whitelist = Set {
@@ -183,16 +193,6 @@ function setup()
sett = 10 sett = 10
}, },
classes = Sequence {
'ferry', 'tunnel'
},
-- Which classes should be excludable
-- This increases memory usage so its disabled by default.
excludable = Sequence {
-- Set {'ferry'}
},
tracktype_speeds = { tracktype_speeds = {
}, },
@@ -235,7 +235,7 @@ function process_node(profile, node, result)
else else
local barrier = node:get_value_by_key("barrier") local barrier = node:get_value_by_key("barrier")
if barrier and "" ~= barrier then if barrier and "" ~= barrier then
if profile.barrier_blacklist[barrier] then if not profile.barrier_whitelist[barrier] then
result.barrier = true result.barrier = true
end end
end end
@@ -650,9 +650,6 @@ function process_way(profile, way, result)
-- set name, ref and pronunciation -- set name, ref and pronunciation
WayHandlers.names, WayHandlers.names,
-- set classes
WayHandlers.classes,
-- set weight properties of the way -- set weight properties of the way
WayHandlers.weights WayHandlers.weights
} }
-7
View File
@@ -42,10 +42,6 @@ function setup()
vehicle_height = 2.5, -- in meters, 2.5m is the height of van vehicle_height = 2.5, -- in meters, 2.5m is the height of van
vehicle_width = 1.9, -- in meters, ways with narrow tag are considered narrower than 2.2m vehicle_width = 1.9, -- in meters, ways with narrow tag are considered narrower than 2.2m
-- Size of the vehicle, to be limited mostly by legal restriction of the way
vehicle_length = 4.8, -- in meters, 4.8m is the length of large or familly car
vehicle_weight = 3500, -- in kilograms
-- a list of suffixes to suppress in name change instructions. The suffixes also include common substrings of each other -- a list of suffixes to suppress in name change instructions. The suffixes also include common substrings of each other
suffix_list = { suffix_list = {
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East', 'Nor', 'Sou', 'We', 'Ea' 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East', 'Nor', 'Sou', 'We', 'Ea'
@@ -280,7 +276,6 @@ function setup()
["de:rural"] = 100, ["de:rural"] = 100,
["de:motorway"] = 0, ["de:motorway"] = 0,
["dk:rural"] = 80, ["dk:rural"] = 80,
["fr:rural"] = 80,
["gb:nsl_single"] = (60*1609)/1000, ["gb:nsl_single"] = (60*1609)/1000,
["gb:nsl_dual"] = (70*1609)/1000, ["gb:nsl_dual"] = (70*1609)/1000,
["gb:motorway"] = (70*1609)/1000, ["gb:motorway"] = (70*1609)/1000,
@@ -392,8 +387,6 @@ function process_way(profile, way, result, relations)
WayHandlers.avoid_ways, WayHandlers.avoid_ways,
WayHandlers.handle_height, WayHandlers.handle_height,
WayHandlers.handle_width, WayHandlers.handle_width,
WayHandlers.handle_length,
WayHandlers.handle_weight,
-- determine access status by checking our hierarchy of -- determine access status by checking our hierarchy of
-- access tags, e.g: motorcar, motor_vehicle, vehicle -- access tags, e.g: motorcar, motor_vehicle, vehicle
+14 -5
View File
@@ -24,10 +24,19 @@ function setup()
default_speed = walking_speed, default_speed = walking_speed,
oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway' oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway'
barrier_blacklist = Set { barrier_whitelist = Set {
'yes', 'cycle_barrier',
'wall', 'bollard',
'fence' 'entrance',
'cattle_grid',
'border_control',
'toll_booth',
'sally_port',
'gate',
'lift_gate',
'no',
'kerb',
'block'
}, },
access_tag_whitelist = Set { access_tag_whitelist = Set {
@@ -148,7 +157,7 @@ function process_node(profile, node, result)
local bollard = node:get_value_by_key("bollard") local bollard = node:get_value_by_key("bollard")
local rising_bollard = bollard and "rising" == bollard local rising_bollard = bollard and "rising" == bollard
if profile.barrier_blacklist[barrier] and not rising_bollard then if not profile.barrier_whitelist[barrier] and not rising_bollard then
result.barrier = true result.barrier = true
end end
end end
+26 -20
View File
@@ -5,7 +5,6 @@ Measure = {}
-- measurements conversion constants -- measurements conversion constants
local inch_to_meters = 0.0254 local inch_to_meters = 0.0254
local feet_to_inches = 12 local feet_to_inches = 12
local pound_to_kilograms = 0.45359237
--- Parse string as a height in meters. --- Parse string as a height in meters.
--- according to http://wiki.openstreetmap.org/wiki/Key:maxheight --- according to http://wiki.openstreetmap.org/wiki/Key:maxheight
@@ -26,19 +25,33 @@ function Measure.parse_value_meters(value)
end end
end end
--- Parse weight value in kilograms. --- according to http://wiki.openstreetmap.org/wiki/Map_Features/Units#Explicit_specifications
--- according to https://wiki.openstreetmap.org/wiki/Key:maxweight local tonns_parse_patterns = Sequence {
"%d+",
"%d+.%d+",
"%d+.%d+ ?t"
}
local kg_parse_patterns = Sequence {
"%d+ ?kg"
}
--- Parse weight value in kilograms
function Measure.parse_value_kilograms(value) function Measure.parse_value_kilograms(value)
local n = tonumber(value:gsub(",", "."):match("%d+%.?%d*")) -- try to parse kilograms
if n then for i, templ in ipairs(kg_parse_patterns) do
if string.match(value, "lbs") then m = string.match(value, templ)
n = n * pound_to_kilograms if m then
elseif string.match(value, "kg") then return tonumber(m)
-- n = n end
else -- Default, metric tons end
n = n * 1000
-- try to parse tonns
for i, templ in ipairs(tonns_parse_patterns) do
m = string.match(value, templ)
if m then
return tonumber(m) * 1000
end end
return n
end end
end end
@@ -70,14 +83,7 @@ function Measure.get_max_width(raw_value)
end end
end end
--- Get maxlength of specified way in meters. --- Get maxweight of specified way in kilogramms
function Measure.get_max_length(raw_value)
if raw_value then
return Measure.parse_value_meters(raw_value)
end
end
--- Get maxweight of specified way in kilogramms.
function Measure.get_max_weight(raw_value) function Measure.get_max_weight(raw_value)
if raw_value then if raw_value then
return Measure.parse_value_kilograms(raw_value) return Measure.parse_value_kilograms(raw_value)
+8 -49
View File
@@ -306,46 +306,37 @@ end
-- add class information -- add class information
function WayHandlers.classes(profile,way,result,data) function WayHandlers.classes(profile,way,result,data)
if not profile.classes then
return
end
local allowed_classes = Set {}
for k, v in pairs(profile.classes) do
allowed_classes[v] = true
end
local forward_toll, backward_toll = Tags.get_forward_backward_by_key(way, data, "toll") local forward_toll, backward_toll = Tags.get_forward_backward_by_key(way, data, "toll")
local forward_route, backward_route = Tags.get_forward_backward_by_key(way, data, "route") local forward_route, backward_route = Tags.get_forward_backward_by_key(way, data, "route")
local tunnel = way:get_value_by_key("tunnel") local tunnel = way:get_value_by_key("tunnel")
if allowed_classes["tunnel"] and tunnel and tunnel ~= "no" then if tunnel and tunnel ~= "no" then
result.forward_classes["tunnel"] = true result.forward_classes["tunnel"] = true
result.backward_classes["tunnel"] = true result.backward_classes["tunnel"] = true
end end
if allowed_classes["toll"] and forward_toll == "yes" then if forward_toll == "yes" then
result.forward_classes["toll"] = true result.forward_classes["toll"] = true
end end
if allowed_classes["toll"] and backward_toll == "yes" then if backward_toll == "yes" then
result.backward_classes["toll"] = true result.backward_classes["toll"] = true
end end
if allowed_classes["ferry"] and forward_route == "ferry" then if forward_route == "ferry" then
result.forward_classes["ferry"] = true result.forward_classes["ferry"] = true
end end
if allowed_classes["ferry"] and backward_route == "ferry" then if backward_route == "ferry" then
result.backward_classes["ferry"] = true result.backward_classes["ferry"] = true
end end
if allowed_classes["restricted"] and result.forward_restricted then if result.forward_restricted then
result.forward_classes["restricted"] = true result.forward_classes["restricted"] = true
end end
if allowed_classes["restricted"] and result.backward_restricted then if result.backward_restricted then
result.backward_classes["restricted"] = true result.backward_classes["restricted"] = true
end end
if allowed_classes["motorway"] and (data.highway == "motorway" or data.highway == "motorway_link") then if data.highway == "motorway" or data.highway == "motorway_link" then
result.forward_classes["motorway"] = true result.forward_classes["motorway"] = true
result.backward_classes["motorway"] = true result.backward_classes["motorway"] = true
end end
@@ -511,38 +502,6 @@ function WayHandlers.handle_width(profile,way,result,data)
end end
end end
-- handle maxweight tags
function WayHandlers.handle_weight(profile,way,result,data)
local keys = Sequence { 'maxweight' }
local forward, backward = Tags.get_forward_backward_by_set(way,data,keys)
forward = Measure.get_max_weight(forward)
backward = Measure.get_max_weight(backward)
if forward and forward < profile.vehicle_weight then
result.forward_mode = mode.inaccessible
end
if backward and backward < profile.vehicle_weight then
result.backward_mode = mode.inaccessible
end
end
-- handle maxlength tags
function WayHandlers.handle_length(profile,way,result,data)
local keys = Sequence { 'maxlength' }
local forward, backward = Tags.get_forward_backward_by_set(way,data,keys)
forward = Measure.get_max_length(forward)
backward = Measure.get_max_length(backward)
if forward and forward < profile.vehicle_length then
result.forward_mode = mode.inaccessible
end
if backward and backward < profile.vehicle_length then
result.backward_mode = mode.inaccessible
end
end
-- handle oneways tags -- handle oneways tags
function WayHandlers.oneway(profile,way,result,data) function WayHandlers.oneway(profile,way,result,data)
if not profile.oneway_handling then if not profile.oneway_handling then
+6 -6
View File
@@ -5,7 +5,7 @@
-- Secondary road: 18km/h = 18000m/3600s = 100m/20s -- Secondary road: 18km/h = 18000m/3600s = 100m/20s
-- Tertiary road: 12km/h = 12000m/3600s = 100m/30s -- Tertiary road: 12km/h = 12000m/3600s = 100m/30s
api_version = 4 api_version = 3
function setup() function setup()
return { return {
@@ -14,7 +14,7 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration', weight_name = 'duration',
process_call_tagless_node = false, process_call_tagless_node = false,
u_turn_penalty = 20, uturn_penalty = 20,
traffic_light_penalty = 7, -- seconds traffic_light_penalty = 7, -- seconds
use_turn_restrictions = true use_turn_restrictions = true
}, },
@@ -32,7 +32,7 @@ function setup()
primary = 36, primary = 36,
secondary = 18, secondary = 18,
tertiary = 12, tertiary = 12,
steps = 6 steps = 6,
} }
} }
end end
@@ -128,9 +128,9 @@ function process_way (profile, way, result)
end end
function process_turn (profile, turn) function process_turn (profile, turn)
if turn.is_u_turn then if turn.direction_modifier == direction_modifier.uturn then
turn.duration = turn.duration + profile.properties.u_turn_penalty turn.duration = profile.properties.uturn_penalty
turn.weight = turn.weight + profile.properties.u_turn_penalty turn.weight = profile.properties.uturn_penalty
end end
if turn.has_traffic_light then if turn.has_traffic_light then
turn.duration = turn.duration + profile.properties.traffic_light_penalty turn.duration = turn.duration + profile.properties.traffic_light_penalty
+1 -3
View File
@@ -9,8 +9,6 @@ lonlat = lambda x: (coord2float(x['lon']['__value']), coord2float(x['lat']['__va
def call(this, method, *args): def call(this, method, *args):
"""Call this.method(args)""" """Call this.method(args)"""
if (str(this) == '<optimized out>'):
raise BaseException('"this" is optimized out')
command = '(*({})({})).{}({})'.format(this.type.target().pointer(), this.address, method, ','.join((str(x) for x in args))) command = '(*({})({})).{}({})'.format(this.type.target().pointer(), this.address, method, ','.join((str(x) for x in args)))
return gdb.parse_and_eval(command) return gdb.parse_and_eval(command)
@@ -236,6 +234,7 @@ class SVGPrinter (gdb.Command):
mld_facade = facade.cast(gdb.lookup_type('osrm::engine::datafacade::ContiguousInternalMemoryAlgorithmDataFacade<osrm::engine::routing_algorithms::mld::Algorithm>')) mld_facade = facade.cast(gdb.lookup_type('osrm::engine::datafacade::ContiguousInternalMemoryAlgorithmDataFacade<osrm::engine::routing_algorithms::mld::Algorithm>'))
mld_partition = mld_facade['mld_partition'] mld_partition = mld_facade['mld_partition']
mld_levels = call(mld_partition, 'GetNumberOfLevels') mld_levels = call(mld_partition, 'GetNumberOfLevels')
print (mld_level, mld_levels)
if mld_level < mld_levels: if mld_level < mld_levels:
sentinel_node = call(mld_partition['partition'], 'size') - 1 # GetSentinelNode sentinel_node = call(mld_partition['partition'], 'size') - 1 # GetSentinelNode
number_of_cells = call(mld_partition, 'GetCell', mld_level, sentinel_node) # GetNumberOfCells number_of_cells = call(mld_partition, 'GetCell', mld_level, sentinel_node) # GetNumberOfCells
@@ -273,7 +272,6 @@ class SVGPrinter (gdb.Command):
for node in nodes: for node in nodes:
geometry_id = call(facade, 'GetGeometryIndex', node) geometry_id = call(facade, 'GetGeometryIndex', node)
direction = 'forward' if geometry_id['forward'] else 'reverse' direction = 'forward' if geometry_id['forward'] else 'reverse'
print (geometry_id, direction)
geometry = SVGPrinter.getByGeometryId(facade, geometry_id, 'Geometry') geometry = SVGPrinter.getByGeometryId(facade, geometry_id, 'Geometry')
weights = SVGPrinter.getByGeometryId(facade, geometry_id, 'Weights') weights = SVGPrinter.getByGeometryId(facade, geometry_id, 'Weights')

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