Compare commits

..

11 Commits

Author SHA1 Message Date
Daniel Patterson c5167d4ade Bump nodejs version to make new package. 2017-10-03 09:10:03 -07:00
Daniel Patterson 1548803a77 Merge branch 'downgrade_libstdc++' of github.com:Project-OSRM/osrm-backend into downgrade_libstdc++ 2017-10-03 09:09:18 -07:00
Daniel J. Hofmann 2b2906f97a Bumps Boost from Mason to 1.65.1 2017-10-03 12:09:33 +02:00
Daniel Patterson ca464fcd5d Tag for release. 2017-10-02 14:14:05 -07:00
Daniel Patterson e9b7b68427 Move workaround into single TU. 2017-10-02 14:06:49 -07:00
Daniel Patterson 6b8ae24df6 Needs some kind of std:: namespace import to find _throw_out_of_range symbol 2017-10-02 12:58:09 -07:00
Daniel Patterson 65385b55e9 Add include via cmake rather than environment variable - env variable breaks compiler detection. 2017-10-02 12:40:31 -07:00
Daniel Patterson f20dda55c0 Fix relative path to override include. 2017-10-02 12:22:43 -07:00
Daniel Patterson ff7f8557e3 Workaround GLIBC 4.9 importing one useless (to us) symbol that causes a version update. 2017-10-02 12:17:34 -07:00
Daniel Patterson eff1d4e622 Try 4.9 to see if that clears up a few of the C++14 errors. 2017-10-02 11:40:41 -07:00
Daniel Patterson f82908d509 Try downgrading libstdc++ so we can run inside non-upgrade glibc environments. 2017-10-02 11:18:33 -07:00
213 changed files with 8499 additions and 8026 deletions
+3 -13
View File
@@ -13,7 +13,6 @@ notifications:
branches:
only:
- master
- "5.13"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@@ -69,19 +68,10 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev', 'lcov']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
before_script:
- cd ${TRAVIS_BUILD_DIR}
- lcov --directory . --zerocounters # clean cached da files
after_success:
# Creating report
- cd ${TRAVIS_BUILD_DIR}
- lcov --directory . --capture --output-file coverage.info # capture coverage info
- lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter out system
- lcov --list coverage.info #debug info
# Uploading report to CodeCov
- bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports"
- bash <(curl -s https://codecov.io/bash)
- os: linux
compiler: "gcc-6-debug-asan"
@@ -96,7 +86,7 @@ matrix:
addons: &clang40
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['libstdc++-4.9-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
+7 -26
View File
@@ -1,34 +1,15 @@
# 5.13.0 RC2
- Changes from 5.12:
# UNRELEASED
- Profile:
- Append cardinal directions from route relations to ref fields to improve instructions
- New function to support relations: `process_relation`. Read more in profiles documentation.
- Support of `distance` weight in foot and bicycle profiles
- Support of relations processing
- Added `way:get_location_tag(key)` method to get location-dependent tags https://github.com/Project-OSRM/osrm-backend/wiki/Using-location-dependent-data-in-profiles
- Left-side driving mode is specified by a local Boolean flag `is_left_hand_driving` in `ExtractionWay` and `ExtractionTurn`
- Support literal values for maxspeeds in NO, PL and ZA
- Infrastructure:
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
- Fixed pkg-config version of OSRM
- Removed `.osrm.core` file since CoreCH is deprecated now.
- Tools:
- Because of boost/program_options#32 with boost 1.65+ we needed to change the behavior of the following flags to not accept `={true|false}` anymore:
- `--use-locations-cache=false` becomes `--disable-location-cache`
- `--parse-conditional-restrictions=true` becomes `--parse-conditional-restrictions`
- The deprecated options `--use-level-cache` and `--generate-edge-lookup`
- Bugfixes:
- Fixed #4348: Some cases of sliproads pre-processing were broken
- Fixed #4331: Correctly compute left/right modifiers of forks in case the fork is curved.
- Fixed #4472: Correctly count the number of lanes using the delimter in `turn:lanes` tag.
- Fixed #4214: Multiple runs of `osrm-partition` lead to crash.
- Fixed #4348: Fix assorted problems around slip roads.
- Fixed #4420: A bug that would result in unnecessary instructions, due to problems in suffix/prefix detection
- Algorithm
- Deprecate CoreCH functionality. Usage of CoreCH specific options will fall back to using CH with core_factor of 1.0
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices which yields speedup.
- Node.js Bindings:
- Exposes `use_threads_number=Number` parameter of `EngineConfig` to limit a number of threads in a TBB internal pool
- Internals
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices
# 5.12.0
- Changes from 5.11:
- Guidance
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways)
- Adds new instruction types at the exit of roundabouts and rotaries `exit roundabout` and `exit rotary`.
@@ -91,7 +72,7 @@
- Bugfixes
- Properly save/retrieve datasource annotations for road segments ([#4346](https://github.com/Project-OSRM/osrm-backend/issues/4346)
- Fix conditional restriction grammer parsing so it works for single-day-of-week restrictions ([#4357](https://github.com/Project-OSRM/osrm-backend/pull/4357))
- Algorithm
- Algorithm)
- BREAKING: the file format requires re-processing due to the changes on via-ways
- Added support for via-way restrictions
+13 -14
View File
@@ -212,19 +212,19 @@ endif()
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "Configuring debug mode flags")
set(ENABLE_ASSERTIONS ON)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline -fno-omit-frame-pointer")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb")
else()
# Don't override the -O parameter for RelWithDebInfo, we want an optimized build
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb")
endif()
endif()
endif()
endif()
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fno-inline -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-inline -fno-omit-frame-pointer")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ggdb")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -ggdb")
endif()
if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "Configuring release mode optimizations")
# Check if LTO is available
@@ -304,11 +304,10 @@ if (ENABLE_COVERAGE)
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
message(ERROR "ENABLE_COVERAGE=ON only make sense with a Debug build")
endif()
message(STATUS "Enabling coverage")
message(INFO "Enabling coverage")
set(MAYBE_COVERAGE_LIBRARIES "-lgcov")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ftest-coverage -fprofile-arcs")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
endif()
if (ENABLE_SANITIZER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -fsanitize=address")
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+24 -13
View File
@@ -41,14 +41,6 @@ Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
The easiest and quickest way to setup your own routing engine is to use Docker images we provide.
There are two pre-processing pipelines available:
- Contraction Hierarchies (CH)
- Multi-Level Dijkstra (MLD)
we recommend using MLD by default except for special use-cases such as very large distance matrices where CH is still a better fit for the time being.
In the following we explain the MLD pipeline.
If you want to use the CH pipeline instead replace `osrm-partition` and `osrm-customize` with a single `osrm-contract` and change the algorithm option for `osrm-routed` to `--algorithm ch`.
### Using Docker
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
@@ -60,10 +52,9 @@ Download OpenStreetMap extracts for example from [Geofabrik](http://download.geo
Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-partition /data/berlin-latest.osrm
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-customize /data/berlin-latest.osrm
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed --algorithm mld /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
Make requests against the HTTP server
@@ -99,8 +90,8 @@ Install dependencies
```bash
sudo apt install build-essential git cmake pkg-config \
libbz2-dev libxml2-dev libzip-dev libboost-all-dev \
lua5.2 liblua5.2-dev libtbb-dev
libbz2-dev libstxxl-dev libstxxl1v5 libxml2-dev \
libzip-dev libboost-all-dev lua5.2 liblua5.2-dev libtbb-dev
```
Compile and install OSRM binaries
@@ -113,6 +104,26 @@ cmake --build .
sudo cmake --build . --target install
```
Grab a `.osm.pbf` extract from [Geofabrik](http://download.geofabrik.de/index.html) or [Mapzen's Metro Extracts](https://mapzen.com/data/metro-extracts/)
```bash
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
```
Pre-process the extract and start the HTTP server
```
osrm-extract berlin-latest.osm.pbf -p profiles/car.lua
osrm-contract berlin-latest.osrm
osrm-routed berlin-latest.osrm
```
Running Queries
```
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
```
### Request Against the Demo Server
Read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy).
+1 -1
View File
@@ -4,7 +4,7 @@ libdir=@PKGCONFIG_LIBRARY_DIR@
Name: libOSRM
Description: Project OSRM library
Version: @OSRM_VERSION@
Version: v@OSRM_VERSION@
Requires:
Libs: -L${libdir} -losrm @PKGCONFIG_OSRM_LDFLAGS@
Libs.private: @PKGCONFIG_OSRM_DEPENDENT_LIBRARIES@
+3 -3
View File
@@ -1,7 +1,7 @@
module.exports = {
default: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions',
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
default: '--strict --tags ~@stress --tags ~@mld --tags ~@todo --require features/support --require features/step_definitions',
verify: '--strict --tags ~@stress --tags ~@mld --tags ~@todo -f progress --require features/support --require features/step_definitions',
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
all: '--strict --require features/support --require features/step_definitions',
mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@ch --require features/support --require features/step_definitions -f progress'
};
+52 -4
View File
@@ -104,7 +104,6 @@ max_speed_for_map_matching | Float | Maximum vehicle speed to be as
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `process_segment` will be called for all segments (default `false`)
The following additional global properties can be set in the hash you return in the `setup` function:
Attribute | Type | Notes
@@ -114,7 +113,6 @@ excludable | Sequence of Sets | Determines which class
classes | Sequence | Determines the allowed classes that can be referenced using `{forward,backward}_classes` on the way in the `process_way` function.
restrictions | Sequence | Determines which turn restrictions will be used for this profile.
suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES".
relation_types | Sequence | Determines wich relations should be cached for processing in this profile. It contains relations types
### process_node(profile, node, result, relations)
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
@@ -124,7 +122,7 @@ Argument | Description
profile | The configuration table you returned in `setup`.
node | The input node to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `node` is a member.
relations| The list of relation attributes passed from `process_relation` function for this node.
The following attributes can be set on `result`:
@@ -141,7 +139,7 @@ Argument | Description
profile | The configuration table you returned in `setup`.
node | The input way to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `way` is a member.
relations| The list of relation attributes passed from `process_relation` function for this way.
Importantly it will set `result.forward_mode` and `result.backward_mode` to indicate the travel mode in each direction, as well as set `result.forward_speed` and `result.backward_speed` to integer values representing the speed for traversing the way.
@@ -181,6 +179,56 @@ road_classification.road_priority_class | Enum | Guidance: order in priority
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
### process_relation(profile, relation, result)
Supported since API **version 3**.
Given an OpenStreetMap relation, the `process_relation` function should setup values into result structure.
Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
node | The input relation to process (read-only).
result | The output that you will modify.
Relation process work flow consist of next steps:
1. Calls `process_relation` function for each relation. It should fill a `result` structure
2. After that each data will be passed for each member of processed relation into `process_node` and `process_way` functions
The following attributes can be set on that result in `process_relation`:
Attribute | Type | Notes
----------------------------------------|----------|--------------------------------------------------------------------------
is_restriction | Boolean | Flag to determine if relation is a turn restriction
Example processing code:
```lua
function process_way(profile, way, result, relations)
for _, r in ipairs(relations) do
for k, v in pairs(r) do
print('data_' .. k .. '_value_' .. v)
end
end
print ('process_way ' .. way:id() .. ' ' .. result.name)
end
function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
if t == "route" then
for _, m in ipairs(relation:members()) do
if m:role == "north" then
result[m]['direction'] = 'north'
print('direction_north')
end
end
print('route_relation')
end
end
```
### process_segment(profile, segment)
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
+179 -179
View File
@@ -17,27 +17,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | only_right_turn @ (has_pygmies > 10 p) |
| restriction | ej | nj | j | only_right_turn @ (has_pygmies > 10 p) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Restriction would be on, but the restriction was badly tagged
@@ -48,29 +48,29 @@ Feature: Car - Turn restrictions
Given the node map
"""
a
n
p |
\ |
j
| \
c m
s m
"""
And the ways
| nodes |
| aj |
| jc |
| nj |
| js |
| pjm |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | aj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
| restriction | jc | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) |
| restriction | nj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
| restriction | js | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) |
When I route I should get
| from | to | route |
| a | m | aj,pjm,pjm |
| c | m | jc,pjm,pjm |
| n | m | nj,pjm,pjm |
| s | m | js,pjm,pjm |
@no_turning @conditionals
Scenario: Car - Restriction With Compressed Geometry
@@ -149,29 +149,29 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | no |
| jd | no |
| nj | no |
| js | no |
| ej | no |
| jp | no |
And the relations
| type | way:from | way:to | node:via | restriction:conditional | except |
| restriction | bj | aj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar |
| restriction | jd | aj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar |
| restriction | jp | nj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus |
When I route I should get
| from | to | route | # |
| b | c | bj,jc,jc | |
| b | a | bj,aj,aj | restriction does not apply to cars |
| b | d | bj,jd,jd | |
| d | c | jd,aj,aj,jc,jc | restriction excepting busses still applies to cars |
| e | s | ej,js,js | |
| e | n | ej,nj,nj | restriction does not apply to cars |
| e | p | ej,jp,jp | |
| p | s | jp,nj,nj,js,js | restriction excepting busses still applies to cars |
@no_turning @conditionals
Scenario: Car - only_right_turn
@@ -181,27 +181,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,aj,aj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,nj,nj,jp,jp |
@no_turning @conditionals
Scenario: Car - No right turn
@@ -211,27 +211,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
When I route I should get
| from | to | route | # |
| b | c | bj,jc,jc | normal turn |
| b | a | bj,jc,jc,aj,aj | avoids right turn |
| b | d | bj,jd,jd | normal maneuver |
| e | s | ej,js,js | normal turn |
| e | n | ej,js,js,nj,nj | avoids right turn |
| e | p | ej,jp,jp | normal maneuver |
@only_turning @conditionals
Scenario: Car - only_left_turn
@@ -241,27 +241,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jc,jc,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,js,js,jp,jp |
@no_turning @conditionals
Scenario: Car - No left turn
@@ -271,27 +271,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | no_left_turn @ (Mo-Su 00:00-23:59) |
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is off
@@ -301,27 +301,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is on
@@ -331,27 +331,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction with multiple time windows
@@ -362,28 +362,28 @@ Feature: Car - Turn restrictions
Given the node map
"""
a
n
p |
\ |
j
| \
c m
s m
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| nj | no |
| js | no |
| jp | yes |
| mj | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | aj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
| restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| a | p | aj,jc,jc,jp,jp |
| n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp |
@no_turning @conditionals
@@ -394,27 +394,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,aj,aj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,nj,nj,jp,jp |
@no_turning @conditionals
Scenario: Car - No right turn
@@ -424,27 +424,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
When I route I should get
| from | to | route | # |
| b | c | bj,jc,jc | normal turn |
| b | a | bj,jc,jc,aj,aj | avoids right turn |
| b | d | bj,jd,jd | normal maneuver |
| e | s | ej,js,js | normal turn |
| e | n | ej,js,js,nj,nj | avoids right turn |
| e | p | ej,jp,jp | normal maneuver |
@only_turning @conditionals
Scenario: Car - only_left_turn
@@ -454,27 +454,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jc,jc,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,js,js,jp,jp |
@no_turning @conditionals
Scenario: Car - No left turn
@@ -484,27 +484,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | jc | j | no_left_turn @ (Mo-Su 00:00-23:59) |
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
When I route I should get
| from | to | route |
| b | c | bj,aj,aj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is off
@@ -514,27 +514,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | bj | aj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is on
@@ -544,27 +544,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the node map
"""
a
d j b
c
n
p j e
s
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| bj | yes |
| jd | yes |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | jb | aj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
When I route I should get
| from | to | route |
| b | c | bj,jc,jc |
| b | a | bj,jc,jc,aj,aj |
| b | d | bj,jd,jd |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction with multiple time windows
@@ -575,28 +575,28 @@ Feature: Car - Turn restrictions
Given the node map
"""
a
n
p |
\ |
j
| \
c m
s m
"""
And the ways
| nodes | oneway |
| aj | no |
| jc | no |
| nj | no |
| js | no |
| jp | yes |
| mj | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | aj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
| restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| a | p | aj,jc,jc,jp,jp |
| n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp |
@restriction-way
@@ -677,7 +677,7 @@ Feature: Car - Turn restrictions
# https://www.openstreetmap.org/#map=18/38.91099/-77.00888
@no_turning @conditionals
Scenario: Car - DC North capitol situation, two on one off
Given the extract extra arguments "--parse-conditional-restrictions"
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 9pm Wed 02 May, 2017 UTC, 5pm EDT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
@@ -724,7 +724,7 @@ Feature: Car - Turn restrictions
@no_turning @conditionals
Scenario: Car - DC North capitol situation, one on two off
Given the extract extra arguments "--parse-conditional-restrictions"
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 10:30am utc, wed, 6:30am est
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
@@ -848,7 +848,7 @@ Feature: Car - Turn restrictions
@only_turning @conditionals
Scenario: Car - Somewhere in London, the UK, GMT timezone
Given the extract extra arguments "--parse-conditional-restrictions"
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 9am UTC, 10am BST
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
+128 -134
View File
@@ -11,27 +11,27 @@ Feature: Car - Turn restrictions
Scenario: Car - No left turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | no_left_turn |
| restriction | sj | wj | j | no_left_turn |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Car - No straight on
@@ -67,259 +67,253 @@ Feature: Car - Turn restrictions
Scenario: Car - No right turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | bj | j | no_right_turn |
| restriction | sj | ej | j | no_right_turn |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | cj,aj,aj |
| c | b | |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | |
@no_turning
Scenario: Car - No u-turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | no_u_turn |
| restriction | sj | wj | j | no_u_turn |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Car - Handle any no_* relation
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | no_weird_zigzags |
| restriction | sj | wj | j | no_weird_zigzags |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning
Scenario: Car - Only left turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | only_left_turn |
When I route I should get
| from | to | route |
| c | a | |
| c | b | |
| c | d | cj,dj,dj |
| restriction | sj | wj | j | only_left_turn |
Scenario: Car - Only right turn, invalid
Given the node map
"""
a
d j b r
c
n
w j e r
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| rb | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
| re | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | br | j | only_right_on |
| restriction | sj | er | j | only_right_on |
When I route I should get
| from | to | route |
| c | r | cj,bj,rb,rb |
| s | r | sj,ej,re,re |
@only_turning
Scenario: Car - Only right turn
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | bj | j | only_right_turn |
| restriction | sj | ej | j | only_right_turn |
When I route I should get
| from | to | route |
| c | d | |
| c | a | |
| c | b | cj,bj,bj |
| s | w | |
| s | n | |
| s | e | sj,ej,ej |
@only_turning
Scenario: Car - Only straight on
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | aj | j | only_straight_on |
| restriction | sj | nj | j | only_straight_on |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | |
| s | w | |
| s | n | sj,nj,nj |
| s | e | |
@no_turning
Scenario: Car - Handle any only_* restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | aj | j | only_weird_zigzags |
| restriction | sj | nj | j | only_weird_zigzags |
When I route I should get
| from | to | route |
| c | d | |
| c | a | cj,aj,aj |
| c | b | |
| s | w | |
| s | n | sj,nj,nj |
| s | e | |
@specific
Scenario: Car - :hgv-qualified on a standard turn restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction:hgv |
| restriction | cj | aj | j | no_straight_on |
| restriction | sj | nj | j | no_straight_on |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@specific
Scenario: Car - :motorcar-qualified on a standard turn restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction:motorcar |
| restriction | cj | aj | j | no_straight_on |
| restriction | sj | nj | j | no_straight_on |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | |
| c | b | cj,bj,bj |
| s | w | sj,wj,wj |
| s | n | |
| s | e | sj,ej,ej |
@except
Scenario: Car - Except tag and on no_ restrictions
@@ -490,27 +484,27 @@ Feature: Car - Turn restrictions
Scenario: Car - Ignore unrecognized restriction
Given the node map
"""
a
d j b
c
n
w j e
s
"""
And the ways
| nodes | oneway |
| cj | yes |
| aj | -1 |
| dj | -1 |
| bj | -1 |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | cj | dj | j | yield |
| restriction | sj | wj | j | yield |
When I route I should get
| from | to | route |
| c | d | cj,dj,dj |
| c | a | cj,aj,aj |
| c | b | cj,bj,bj |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@restriction @compression
Scenario: Restriction On Compressed Geometry
-232
View File
@@ -1,232 +0,0 @@
@routing @car @relations
Feature: Car - route relations
Background:
Given the profile "car"
Scenario: Assignment using relation membership roles
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | way:east | way:west | route | ref | network |
| route | cd | ba | road | 80 | US:I |
| route | cd | ba | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80 $west,I 80 $west |
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
Scenario: Assignment using relation direction property (no role on members)
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | direction | way | route | ref | network |
| route | west | ba | road | 80 | US:I |
| route | east | cd | road | 80 | US:I |
| route | east | cd | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80 $west,I 80 $west |
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
Scenario: Forward assignment on one-way roads using relation direction property
Given the node map
"""
a----------------b
c----------------d
"""
And the ways
| nodes | name | highway | ref |
| ba | westbound | motorway | I 80 |
| cd | eastbound | motorway | I 80;CO 93 |
And the relations
| type | direction | way:forward | route | ref | network |
| route | west | ba | road | 80 | US:I |
| route | east | cd | road | 80 | US:I |
| route | east | cd | road | 93 | US:CO |
When I route I should get
| waypoints | route | ref |
| b,a | westbound,westbound | I 80 $west,I 80 $west |
| c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east |
# Scenario: Forward/backward assignment on non-divided roads with role direction tag
# Given the node map
# """
# a----------------b
# """
#
# And the ways
# | nodes | name | highway | ref | oneway |
# | ab | mainroad | motorway | I 80 | no |
#
# And the relations
# | type | direction | way:forward | route | ref | network |
# | route | west | ab | road | 80 | US:I |
#
# And the relations
# | type | direction | way:backward | route | ref | network |
# | route | east | ab | road | 80 | US:I |
#
# When I route I should get
# | waypoints | route | ref |
# | b,a | mainroad,mainroad | I 80 $west,I 80 $west |
# | a,b | mainroad,mainroad | I 80 $east,I 80 $east |
Scenario: Conflict between role and direction
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | direction | way:east | route | ref | network |
| route | west | ab | road | 80 | US:I |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80,I 80 |
Scenario: Conflict between role and superrelation direction
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:east | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | direction | relation | route | ref | network | name |
| route | west | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80,I 80 |
Scenario: Conflict between role and superrelation role
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:east | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | relation:west | route | ref | network | name |
| route | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80,I 80 |
Scenario: Direction only available via superrelation role
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:forward | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | relation:east | route | ref | network | name |
| route | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80 $east,I 80 $east |
Scenario: Direction only available via superrelation direction
Given the node map
"""
a----------------b
"""
And the ways
| nodes | name | highway | ref |
| ab | eastbound | motorway | I 80 |
And the relations
| type | way:forward | route | ref | network | name |
| route | ab | road | 80 | US:I | baserelation |
And the relations
| type | direction | relation | route | ref | network | name |
| route | east | baserelation | road | 80 | US:I | superrelation |
When I route I should get
| waypoints | route | ref |
| a,b | eastbound,eastbound | I 80 $east,I 80 $east |
# Scenario: Three levels of indirection
# Given the node map
# """
# a----------------b
# """
#
# And the ways
# | nodes | name | highway | ref |
# | ab | eastbound | motorway | I 80 |
#
# And the relations
# | type | way:forward | route | ref | network | name |
# | route | ab | road | 80 | US:I | baserelation |
#
# And the relations
# | type | relation | route | ref | network | name |
# | route | baserelation | road | 80 | US:I | superrelation1 |
#
# And the relations
# | type | direction | relation | route | ref | network | name |
# | route | east | superrelation1 | road | 80 | US:I | superrelation2 |
#
# When I route I should get
# | waypoints | route | ref |
# | a,b | eastbound,eastbound | I 80 $east,I 80 $east |
+4 -73
View File
@@ -5,9 +5,9 @@ Feature: Testbot - side bias
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.turn_bias = 1.075
profile.turn_bias = 1/1.075
"""
And the node map
Given the node map
"""
a b c
@@ -28,7 +28,7 @@ Feature: Testbot - side bias
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.turn_bias = 1 / 1.075
profile.turn_bias = 1.075
"""
And the node map
"""
@@ -42,77 +42,8 @@ Feature: Testbot - side bias
| bc |
| bd |
When I route I should get
| from | to | route | time | # |
| d | a | bd,ab,ab | 27s +-1 | should be inverse of left hand bias |
| d | c | bd,bc,bc | 24s +-1 | |
Scenario: Roundabout exit counting for left sided driving
Given the profile file "testbot" initialized with
"""
profile.left_hand_driving = true
"""
And a grid size of 10 meters
And the node map
"""
a
b
h g c d
e
f
"""
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
Scenario: Left-hand bias via location-dependent tags
Given the profile "car"
And the node map
"""
a b c
d
"""
And the ways with locations
| nodes |
| ab |
| bc |
| bd |
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | time |
| d | a | bd,ab,ab | 24s +-1 |
| d | c | bd,bc,bc | 27s +-1 |
Scenario: Left-hand bias via OSM tags
Given the profile "car"
And the node map
"""
a b c
d
"""
And the ways with locations
| nodes | driving_side |
| ab | right |
| bc | right |
| bd | right |
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | time |
| d | a | bd,ab,ab | 27s +-1 |
# should be inverse of left hand bias
| d | c | bd,bc,bc | 24s +-1 |
-29
View File
@@ -147,32 +147,3 @@ Feature: Collapse
| waypoints | route | turns |
| a,d | road,left,left | depart,turn left,arrive |
| a,e | road,right,right | depart,turn right,arrive |
# https://www.openstreetmap.org/#map=18/53.89755/27.54306
Scenario: Wide turn into invalid u-turn
Given the node map
"""
g
|
|
f - - - - e
|
|
|
h - - d
|
|
|
a - - - - b - - - - c
"""
And the ways
| nodes | highway | name |
| abc | secondary | road |
| bdfg | service | |
| hd | service | |
| fe | service | |
When I route I should get
| waypoints | route | turns |
| c,e | road,,, | depart,turn right,turn right,arrive |
-34
View File
@@ -22,40 +22,6 @@ Feature: Continue Instructions
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,d | abc,bd,bd | depart,turn straight,arrive |
Scenario: Road turning left, Suffix changes
Given the node map
"""
c
a - b-d
"""
And the ways
| nodes | highway | name |
| ab | primary | North Capitol Northeast |
| bc | primary | North Capitol Northwest |
| bd | primary | some random street |
When I route I should get
| waypoints | route | turns |
| a,c | North Capitol Northeast,North Capitol Northwest,North Capitol Northwest | depart,continue left,arrive |
Scenario: Road turning left, Suffix changes, no-spaces
Given the node map
"""
c
a - b-d
"""
And the ways
| nodes | highway | name |
| ab | primary | North CapitolNortheast |
| bc | primary | North CapitolNorthwest |
| bd | primary | some random street |
When I route I should get
| waypoints | route | turns |
| a,c | North CapitolNortheast,North CapitolNorthwest,North CapitolNorthwest | depart,continue left,arrive |
Scenario: Road turning left and straight
Given the node map
"""
+1 -56
View File
@@ -995,59 +995,4 @@ Feature: Slipways and Dedicated Turn Lanes
When I route I should get
| waypoints | route | turns | locations |
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
@sliproads
Scenario: Sliproad from link via link to primary
Given the node map
"""
d
.
s . a . b
` .
` .
'.
c
.
f
"""
And the ways
| nodes | highway | name | oneway |
| sab | primary_link | sab | |
| dbcf | primary | dbcf | |
| ac | primary_link | ae | yes |
When I route I should get
| waypoints | route | turns | locations |
| s,f | sab,dbcf,dbcf | depart,turn right,arrive | s,a,f |
@sliproads
Scenario: Sliproad with a single intersection in a cross-road
Given the node map
"""
d
.
s . a . b
` .
' c . g
..
e
.
f
"""
And the ways
| nodes | highway | name | oneway |
| sab | primary | sab | |
| dbcef | primary | dbcef | |
| ae | primary_link | sab | yes |
| cg | primary | cg | |
When I route I should get
| waypoints | route | turns | locations |
| s,f | sab,dbcef,dbcef | depart,turn right,arrive | s,a,f |
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
@@ -523,42 +523,3 @@ Feature: Merge Segregated Roads
| a,d | horiz,horiz | true:90,false:0 true:60 true:90 true:180 false:270,false:0 true:90 false:180 false:270 true:300;true:270 |
| j,h | vert,horiz,horiz | true:0;true:0 true:90 false:180 false:270 true:300,false:60 false:120 false:240 true:300,false:0 false:90 false:120 true:180 true:270;true:90 |
| j,l | vert,vert | true:0,true:0 true:90 false:180 false:270 true:300,true:0 false:90 false:180 true:240 false:270;true:180 |
Scenario: Square Area - Don't merge almost circular roads
Given a grid size of 2 meters
Given the node map
"""
i
/
/
/
b---- g .
/ p .
a / \ f
\ / o /
\ / \ /
c n /
/ \ \/
/ k e
/ \ /
h l /
\ /
m . d
/
j
"""
And the ways
| nodes | name | oneway |
| ac | Halenseestraße | yes |
| gb | Halenseestraße | yes |
| cklmdenopgc | Rathenauplatz | yes |
| ig | Kurfürstendamm | yes |
| ef | Kurfürstendamm | yes |
| ch | Hubertusallee | yes |
| jd | Hubertusallee | yes |
When I route I should get
| waypoints | route | turns |
| i,h | Kurfürstendamm,Hubertusallee,Hubertusallee | depart,turn straight,arrive |
+4 -4
View File
@@ -274,8 +274,8 @@ Feature: New-Name Instructions
| bc | Central Expressway | US 75 | motorway |
When I route I should get
| waypoints | route | turns |
| a,c | North Central Expressway,Central Expressway | depart,arrive |
| waypoints | route | turns |
| a,c | North Central Expressway,Central Expressway,Central Expressway | depart,new name straight,arrive |
Scenario: Prefix Change
Given the node map
@@ -289,8 +289,8 @@ Feature: New-Name Instructions
| cb | Central Expressway | US 75 | motorway |
When I route I should get
| waypoints | route | turns |
| c,a | Central Expressway,North Central Expressway | depart,arrive |
| waypoints | route | turns |
| c,a | Central Expressway,North Central Expressway,North Central Expressway | depart,new name straight,arrive |
Scenario: No Name, Same Reference
Given the node map
@@ -5,7 +5,7 @@ Feature: Basic Roundabout
Given a grid size of 10 meters
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.properties.left_hand_driving = true
"""
Scenario: Roundabout exit counting for left sided driving
+10 -10
View File
@@ -829,16 +829,16 @@ Feature: Basic Roundabout
"""
And the ways
| nodes | highway | junction | oneway | # |
| abcda | tertiary | roundabout | | circle |
| ebds | tertiary | | | road |
| cm | tertiary | | | |
| ds | tertiary | | | road |
| rstur | tertiary | roundabout | | circle2 |
| ufghl | tertiary | | | road |
| tv | tertiary | | | |
| gi | tertiary_link | | yes | sliproad |
| jhik | tertiary | | | crossroad |
| nodes | highway | junction | oneway | # |
| abcda | tertiary | roundabout | | circle |
| ebds | tertiary | | | road |
| cm | tertiary | | | |
| ds | tertiary | | | road |
| rstur | tertiary | roundabout | | circle2 |
| ufghl | tertiary | | | road |
| tv | tertiary | | | |
| gi | tertiary | | yes | sliproad |
| jhik | tertiary | | | crossroad |
When I route I should get
+2 -2
View File
@@ -20,11 +20,11 @@ module.exports = {
});
},
hashOfFile: (path, additional_content, cb) => {
hashOfFile: (path, cb) => {
fs.readFile(path, (err, result) => {
if (err) return cb(err);
let checksum = crypto.createHash('md5');
checksum.update(result + (additional_content || "") );
checksum.update(result);
cb(null, checksum.digest('hex'));
});
}
+6 -13
View File
@@ -61,13 +61,8 @@ class DB {
});
w.nodes.forEach((k) => {
let nd = way.ele('nd')
way.ele('nd')
.att('ref', k.id);
if (w.add_locations) {
nd.att('lon', k.lon);
nd.att('lat', k.lat);
}
});
for (var k in w.tags) {
@@ -86,12 +81,11 @@ class DB {
});
r.members.forEach((m) => {
var d = {
relation.ele('member', {
type: m.type,
ref: m.id
};
if (m.role) d.role = m.role;
relation.ele('member', d);
ref: m.id,
role: m.role
});
});
for (var k in r.tags) {
@@ -126,14 +120,13 @@ class Node {
}
class Way {
constructor (id, OSM_USER, OSM_TIMESTAMP, OSM_UID, add_locations) {
constructor (id, OSM_USER, OSM_TIMESTAMP, OSM_UID) {
this.id = id;
this.OSM_USER = OSM_USER;
this.OSM_TIMESTAMP = OSM_TIMESTAMP;
this.OSM_UID = OSM_UID;
this.tags = {};
this.nodes = [];
this.add_locations = add_locations;
}
addNode (node) {
+3
View File
@@ -12,6 +12,7 @@ Feature: osrm-contract command line options: help
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--core"
And stdout should contain "--level-cache"
And stdout should contain "--segment-speed-file"
And it should exit with an error
@@ -26,6 +27,7 @@ Feature: osrm-contract command line options: help
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--core"
And stdout should contain "--level-cache"
And stdout should contain "--segment-speed-file"
And it should exit successfully
@@ -40,5 +42,6 @@ Feature: osrm-contract command line options: help
And stdout should contain "Configuration:"
And stdout should contain "--threads"
And stdout should contain "--core"
And stdout should contain "--level-cache"
And stdout should contain "--segment-speed-file"
And it should exit successfully
+12 -130
View File
@@ -1,12 +1,22 @@
@extract
Feature: osrm-extract lua ways:get_nodes()
Background:
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
Scenario: osrm-extract - Passing base file
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result)
function way_function(profile, way, result)
for _, node in ipairs(way:get_nodes()) do
print('node id ' .. node:id())
end
@@ -14,138 +24,10 @@ Feature: osrm-extract lua ways:get_nodes()
result.forward_speed = 1
end
functions.process_way = way_function
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file}"
Then it should exit successfully
And stdout should contain "node id 1"
And stdout should contain "node id 2"
Scenario: osrm-extract location-dependent data without add-locations-to-ways preprocessing and node locations cache
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print(way:get_location_tag('driving_side'))
end
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I try to run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --disable-location-cache"
Then it should exit with an error
And stderr should contain "invalid location"
Scenario: osrm-extract location-dependent data
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
for _, key in ipairs({'answer', 'boolean', 'object', 'array'}) do
print (key .. ' ' .. tostring(way:get_location_tag(key)))
end
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node map
"""
a b
"""
And the ways with locations
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --disable-location-cache"
Then it should exit successfully
And stdout should contain "answer 42"
And stdout should contain "boolean true"
And stdout should contain "array nil"
And stdout should contain "object nil"
Scenario: osrm-extract location-dependent data with multi-polygons
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print('ISO3166-1 ' .. (way:get_location_tag('ISO3166-1') or 'none'))
print('answer ' .. (way:get_location_tag('answer') or 'none'))
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node locations
| node | lat | lon | id |
| a | 22.4903670 | 113.9455227 | 1 |
| b | 22.4901701 | 113.9455899 | 2 |
| c | 22.4901852 | 113.9458608 | 3 |
| d | 22.4904033 | 113.9456999 | 4 |
| e | 1.1 | 1 | 5 |
| f | 1.2 | 1 | 6 |
And the ways with locations
| nodes | # |
| ab | Hong Kong |
| cd | China Mainland |
| ef | Null Island |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --location-dependent-data test/data/regions/hong-kong.geojson --disable-location-cache"
Then it should exit successfully
And stdout should not contain "1 GeoJSON polygon"
And stdout should contain "2 GeoJSON polygons"
And stdout should contain "ISO3166-1 HK"
And stdout should contain "ISO3166-1 none"
And stdout should contain "answer 42"
Scenario: osrm-extract location-dependent data via locations cache
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print ('answer ' .. tostring(way:get_location_tag('answer')))
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson"
Then it should exit successfully
And stdout should contain "answer 42"
+26 -8
View File
@@ -14,6 +14,7 @@ Feature: Profile API version 3
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
function setup()
return {
properties = {
@@ -22,8 +23,7 @@ Feature: Profile API version 3
continue_straight_at_waypoint = true,
weight_name = 'test_version2',
weight_precision = 2
},
relation_types = Sequence { "route" }
}
}
end
@@ -39,15 +39,30 @@ Feature: Profile API version 3
result.forward_speed = 36
result.backward_speed = 36
local rel_id_list = relations:get_relations(way)
for i, rel_id in ipairs(rel_id_list) do
local rel = relations:relation(rel_id)
local role = rel:get_role(way)
print('role_' .. role)
for _, r in ipairs(relations) do
for k, v in pairs(r) do
print('data_' .. k .. '_value_' .. v)
end
end
print ('process_way ' .. way:id() .. ' ' .. result.name)
end
function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
if t == "route" then
for _, m in ipairs(relation:members()) do
if m:role() == "north" then
result[m]['direction'] = 'north'
print('direction_north')
end
end
print('route_relation')
end
print ('process_relation ' .. relation:id())
end
function process_turn (profile, turn)
print('process_turn', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
turn.weight = turn.angle == 0 and 0 or 4.2
@@ -88,11 +103,14 @@ Feature: Profile API version 3
When I run "osrm-extract --profile {profile_file} {osm_file}"
Then it should exit successfully
And stdout should contain "process_relation"
And stdout should contain "route_relation"
And stdout should contain "direction_north"
And stdout should contain "data_direction_value_north"
And stdout should contain "process_node"
And stdout should contain "process_way"
And stdout should contain "process_turn"
And stdout should contain "process_segment"
And stdout should contain "role_north"
When I route I should get
| from | to | route | time |
+5 -20
View File
@@ -8,7 +8,7 @@ var OSM = require('../lib/osm');
module.exports = function () {
this.Given(/^the profile "([^"]*)"$/, (profile, callback) => {
this.profile = this.OSRM_PROFILE || profile;
this.profile = profile;
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
callback();
});
@@ -129,13 +129,13 @@ module.exports = function () {
q.awaitAll(callback);
});
this.Given(/^the ways( with locations)?$/, (add_locations, table, callback) => {
this.Given(/^the ways$/, (table, callback) => {
if (this.osm_str) throw new Error('*** Map data already defined - did you pass an input file in this scenario?');
let q = d3.queue();
let addWay = (row, cb) => {
let way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID, !!add_locations);
let way = new OSM.Way(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID);
let nodes = row.nodes;
if (this.nameWayHash.nodes) throw new Error(util.format('*** duplicate way %s', nodes));
@@ -188,12 +188,9 @@ module.exports = function () {
let addRelation = (row, cb) => {
let relation = new OSM.Relation(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID);
var name = null;
for (let key in row) {
let isNode = key.match(/^node:?(.*)/),
isWay = key.match(/^way:?(.*)/),
isRelation = key.match(/^relation:?(.*)/),
let isNode = key.match(/^node:(.*)/),
isWay = key.match(/^way:(.*)/),
isColonSeparated = key.match(/^(.*):(.*)/);
if (isNode) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => {
@@ -208,26 +205,14 @@ module.exports = function () {
if (!way) throw new Error(util.format('*** unknown relation way member "%s"', wayName));
relation.addMember('way', way.id, isWay[1]);
});
} else if (isRelation) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((relName) => {
let otherrelation = this.findRelationByName(relName);
if (!otherrelation) throw new Error(util.format('*** unknown relation relation member "%s"', relName));
relation.addMember('relation', otherrelation.id, isRelation[1]);
});
} else if (isColonSeparated && isColonSeparated[1] !== 'restriction') {
throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"', isColonSeparated[1], isColonSeparated[2]));
} else {
relation.addTag(key, row[key]);
if (key.match(/name/)) name = row[key];
}
}
relation.uid = this.OSM_UID;
if (name) {
this.nameRelationHash[name] = relation;
}
this.OSMDB.addRelation(relation);
cb();
+2 -4
View File
@@ -54,14 +54,12 @@ module.exports = function () {
this.Then(/^stdout should( not)? contain "(.*?)"$/, (not, str) => {
const contains = this.stdout.indexOf(str) > -1;
assert.ok(typeof not === 'undefined' ? contains : !contains,
'stdout ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
assert.ok(typeof not === 'undefined' ? contains : !contains);
});
this.Then(/^stderr should( not)? contain "(.*?)"$/, (not, str) => {
const contains = this.stderr.indexOf(str) > -1;
assert.ok(typeof not === 'undefined' ? contains : !contains,
'stderr ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
assert.ok(typeof not === 'undefined' ? contains : !contains);
});
this.Then(/^stdout should contain \/(.*)\/$/, (regexStr) => {
+2 -5
View File
@@ -28,16 +28,13 @@ module.exports = function() {
let uri = feature.getUri();
// setup cache for feature data
// if OSRM_PROFILE is set to force a specific profile, then
// include the profile name in the hash of the profile file
hash.hashOfFile(uri, this.OSRM_PROFILE, (err, hash) => {
hash.hashOfFile(uri, (err, hash) => {
if (err) return callback(err);
// shorten uri to be realtive to 'features/'
let featurePath = path.relative(path.resolve('./features'), uri);
// bicycle/bollards/{HASH}/
let featureID = path.join(featurePath, hash);
let featureID = path.join(featurePath, hash);
let featureCacheDirectory = this.getFeatureCacheDirectory(featureID);
let featureProcessedCacheDirectory = this.getFeatureProcessedCacheDirectory(featureCacheDirectory, this.osrmHash);
this.featureIDs[uri] = featureID;
-5
View File
@@ -144,10 +144,6 @@ module.exports = function () {
return this.nameWayHash[s.toString()] || this.nameWayHash[s.toString().split('').reverse().join('')];
};
this.findRelationByName = (s) => {
return this.nameRelationHash[s.toString()] || this.nameRelationHash[s.toString().split('').reverse().join('')];
};
this.makeOSMId = () => {
this.osmID = this.osmID + 1;
return this.osmID;
@@ -159,7 +155,6 @@ module.exports = function () {
this.locationHash = {};
this.shortcutsHash = {};
this.nameWayHash = {};
this.nameRelationHash = {};
this.osmID = 0;
};
-2
View File
@@ -44,8 +44,6 @@ module.exports = function () {
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
this.OSRM_PROFILE = process.env.OSRM_PROFILE;
if (this.PLATFORM_WINDOWS) {
this.TERMSIGNAL = 9;
+1 -1
View File
@@ -22,7 +22,7 @@ module.exports = function () {
});
this.BeforeFeature((feature, callback) => {
this.profile = this.OSRM_PROFILE || this.DEFAULT_PROFILE;
this.profile = this.DEFAULT_PROFILE;
this.profileFile = path.join(this.PROFILES_PATH, this.profile + '.lua');
this.setupFeatureCache(feature);
callback();
-3
View File
@@ -12,9 +12,6 @@ Feature: Alternative route
g h i j
"""
# enforce multiple cells for filterUnpackedPathsBySharing check
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
And the ways
| nodes |
| ab |
+12 -48
View File
@@ -2,11 +2,11 @@
Feature: Approach parameter
Background:
Given a grid size of 10 meters
Given the profile "testbot"
And a grid size of 10 meters
Scenario: Start End same approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -22,8 +22,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End same approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -39,8 +38,7 @@ Feature: Approach parameter
| s | e | unrestricted curb | ab,bc,bc |
Scenario: Start End opposite approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -57,8 +55,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End opposite approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -80,8 +77,7 @@ Feature: Approach parameter
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -97,8 +93,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -114,8 +109,7 @@ Feature: Approach parameter
| s | e | unrestricted curb | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -132,8 +126,7 @@ Feature: Approach parameter
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
Given the node map
"""
s
a------b------c
@@ -154,8 +147,7 @@ Feature: Approach parameter
##############
Scenario: UTurn test, router can't found a route because uturn unauthorized on the segment selected
Given the profile "testbot"
And the node map
Given the node map
"""
s e
a------b------c
@@ -176,8 +168,7 @@ Feature: Approach parameter
Scenario: UTurn test, router can find a route because he can use the roundabout
Given the profile "testbot"
And the node map
Given the node map
"""
h
s e / \
@@ -199,30 +190,3 @@ Feature: Approach parameter
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
Scenario: Start End same approach, option unrestricted for Start and curb for End, left-hand driving
Given the profile file
"""
local functions = require('testbot')
local testbot_process_way = functions.process_way
functions.process_way = function(profile, way, result)
testbot_process_way(profile, way, result)
result.is_left_hand_driving = true
end
return functions
"""
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
+1 -35
View File
@@ -6,7 +6,6 @@ Feature: Basic Distance Matrix
Background:
Given the profile "testbot"
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
Scenario: Testbot - Travel time matrix of minimal network
Given the node map
@@ -125,7 +124,7 @@ Feature: Basic Distance Matrix
| d | 20 | 30 | 0 | 30 |
| e | 30 | 40 | 10 | 0 |
Scenario: Testbot - Rectangular travel time matrix
Scenario: Testbot - Travel time matrix and with only one source
Given the node map
"""
a b c
@@ -151,39 +150,6 @@ Feature: Basic Distance Matrix
| 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
"""
@@ -63,7 +63,6 @@ Feature: Multi level routing
| cm | primary |
| hj | primary |
| kp | primary |
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16"
When I route I should get
| from | to | route | time |
@@ -83,28 +82,6 @@ Feature: Multi level routing
| l | 144.7 | 124.7 | 0 | 60 |
| o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| f | 229.4 |
| l | 144.7 |
| o | 124.7 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get
| | a | o |
| a | 0 | 124.7 |
| f | 229.4 | 144.7 |
| l | 144.7 | 60 |
| o | 124.7 | 0 |
Scenario: Testbot - Multi level routing: horizontal road
Given the node map
@@ -12,32 +12,14 @@ namespace osrm
namespace contractor
{
using GraphAndFilter = std::tuple<QueryGraph, std::vector<std::vector<bool>>>;
inline auto contractFullGraph(ContractorGraph contractor_graph,
std::vector<EdgeWeight> node_weights)
{
auto num_nodes = contractor_graph.GetNumberOfNodes();
contractGraph(contractor_graph, node_weights);
auto edges = toEdges<QueryEdge>(std::move(contractor_graph));
std::vector<bool> edge_filter(edges.size(), true);
return GraphAndFilter{QueryGraph{num_nodes, std::move(edges)}, {std::move(edge_filter)}};
}
using GraphFilterAndCore =
std::tuple<QueryGraph, std::vector<std::vector<bool>>, std::vector<std::vector<bool>>>;
inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
std::vector<EdgeWeight> node_weights,
const std::vector<std::vector<bool>> &filters)
const std::vector<std::vector<bool>> &filters,
const float core_factor = 1.0)
{
if (filters.size() == 1)
{
if (std::all_of(filters.front().begin(), filters.front().end(), [](auto v) { return v; }))
{
return contractFullGraph(std::move(contractor_graph_), std::move(node_weights));
}
}
auto num_nodes = contractor_graph_.GetNumberOfNodes();
ContractedEdgeContainer edge_container;
ContractorGraph shared_core_graph;
@@ -57,8 +39,10 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
// a very dense core. This increases the overall graph sizes a little bit
// but increases the final CH quality and contraction speed.
constexpr float BASE_CORE = 0.9;
is_shared_core =
contractGraph(contractor_graph, std::move(always_allowed), node_weights, BASE_CORE);
is_shared_core = contractGraph(contractor_graph,
std::move(always_allowed),
node_weights,
std::min<float>(BASE_CORE, core_factor));
// Add all non-core edges to container
{
@@ -76,16 +60,26 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
[&is_shared_core](const NodeID node) { return is_shared_core[node]; });
}
std::vector<std::vector<bool>> cores;
for (const auto &filter : filters)
{
auto filtered_core_graph =
shared_core_graph.Filter([&filter](const NodeID node) { return filter[node]; });
auto core = contractGraph(
filtered_core_graph, is_shared_core, is_shared_core, node_weights, core_factor);
if (core_factor == 1.0)
{
core.clear();
}
cores.push_back(std::move(core));
edge_container.Merge(toEdges<QueryEdge>(std::move(filtered_core_graph)));
}
return GraphAndFilter{QueryGraph{num_nodes, std::move(edge_container.edges)},
edge_container.MakeEdgeFilters()};
return GraphFilterAndCore{QueryGraph{num_nodes, std::move(edge_container.edges)},
edge_container.MakeEdgeFilters(),
std::move(cores)};
}
}
}
@@ -2,17 +2,9 @@
#define OSRM_CONTRACTOR_CONTRACTED_EDGE_CONTAINER_HPP
#include "contractor/query_edge.hpp"
#include "util/deallocating_vector.hpp"
#include "util/integer_range.hpp"
#include "util/permutation.hpp"
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <climits>
#include <cstdint>
#include <numeric>
#include <vector>
namespace osrm
{
@@ -51,7 +43,7 @@ struct ContractedEdgeContainer
}
public:
void Insert(std::vector<QueryEdge> new_edges)
void Insert(util::DeallocatingVector<QueryEdge> new_edges)
{
BOOST_ASSERT(edges.size() == 0);
BOOST_ASSERT(flags.empty());
@@ -60,70 +52,80 @@ struct ContractedEdgeContainer
flags.resize(edges.size(), ALL_FLAGS);
}
void Merge(std::vector<QueryEdge> new_edges)
void Merge(util::DeallocatingVector<QueryEdge> new_edges)
{
BOOST_ASSERT(index < sizeof(MergedFlags) * CHAR_BIT);
const MergedFlags flag = 1 << index++;
auto edge_iter = edges.cbegin();
auto edge_end = edges.cend();
std::vector<MergedFlags> merged_flags;
merged_flags.reserve(flags.size() * 1.1);
util::DeallocatingVector<QueryEdge> merged_edges;
merged_edges.reserve(edges.size() * 1.1);
auto flags_iter = flags.begin();
// destructive iterators, this is single-pass only
// FIXME using dbegin() dend() will result in segfaults.
auto edges_iter = edges.dbegin();
auto edges_end = edges.dend();
auto new_edges_iter = new_edges.dbegin();
auto new_edges_end = new_edges.dend();
// Remove all edges that are contained in the old set of edges and set the appropriate flag.
auto new_end =
std::remove_if(new_edges.begin(), new_edges.end(), [&](const QueryEdge &edge) {
// check if the new edge would be sorted before the currend old edge
// if so it is not contained yet in the set of old edges
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
{
return false;
}
while (edges_iter != edges_end && new_edges_iter != new_edges_end)
{
while (edges_iter != edges_end && mergeCompare(*edges_iter, *new_edges_iter))
{
merged_edges.push_back(*edges_iter);
merged_flags.push_back(*flags_iter);
edges_iter++;
flags_iter++;
}
// find the first old edge that is equal or greater then the new edge
while (edge_iter != edge_end && mergeCompare(*edge_iter, edge))
{
BOOST_ASSERT(flags_iter != flags.end());
edge_iter++;
flags_iter++;
}
if (edges_iter == edges_end)
{
break;
}
// all new edges will be sorted after the old edges
if (edge_iter == edge_end)
{
return false;
}
while (new_edges_iter != new_edges_end && mergeCompare(*new_edges_iter, *edges_iter))
{
merged_edges.push_back(*new_edges_iter);
merged_flags.push_back(flag);
new_edges_iter++;
}
BOOST_ASSERT(edge_iter != edge_end);
if (mergable(edge, *edge_iter))
{
*flags_iter = *flags_iter | flag;
return true;
}
BOOST_ASSERT(mergeCompare(edge, *edge_iter));
return false;
});
if (new_edges_iter == new_edges_end)
{
break;
}
// append new edges
edges.insert(edges.end(), new_edges.begin(), new_end);
auto edges_size = edges.size();
auto new_edges_size = std::distance(new_edges.begin(), new_end);
BOOST_ASSERT(edges_size >= new_edges_size);
flags.resize(edges_size);
std::fill(flags.begin() + edges_size - new_edges_size, flags.end(), flag);
while (edges_iter != edges_end && new_edges_iter != new_edges_end &&
mergable(*edges_iter, *new_edges_iter))
{
merged_edges.push_back(*edges_iter);
merged_flags.push_back(*flags_iter | flag);
// enforce sorting for next merge step
std::vector<unsigned> ordering(edges_size);
std::iota(ordering.begin(), ordering.end(), 0);
tbb::parallel_sort(
ordering.begin(), ordering.end(), [&](const auto lhs_idx, const auto rhs_idx) {
return mergeCompare(edges[lhs_idx], edges[rhs_idx]);
});
auto permutation = util::orderingToPermutation(ordering);
edges_iter++;
flags_iter++;
new_edges_iter++;
}
}
util::inplacePermutation(edges.begin(), edges.end(), permutation);
util::inplacePermutation(flags.begin(), flags.end(), permutation);
BOOST_ASSERT(std::is_sorted(edges.begin(), edges.end(), mergeCompare));
while (edges_iter != edges_end)
{
BOOST_ASSERT(new_edges_iter == new_edges_end);
merged_edges.push_back(*edges_iter++);
merged_flags.push_back(*flags_iter++);
}
while (new_edges_iter != new_edges_end)
{
BOOST_ASSERT(edges_iter == edges_end);
merged_edges.push_back(*new_edges_iter++);
merged_flags.push_back(flag);
}
flags = std::move(merged_flags);
edges = std::move(merged_edges);
}
auto MakeEdgeFilters() const
@@ -143,7 +145,7 @@ struct ContractedEdgeContainer
std::size_t index = 0;
std::vector<MergedFlags> flags;
std::vector<QueryEdge> edges;
util::DeallocatingVector<QueryEdge> edges;
};
}
}
+21 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -29,6 +29,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define CONTRACTOR_CONTRACTOR_HPP
#include "contractor/contractor_config.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "util/deallocating_vector.hpp"
#include "util/typedefs.hpp"
#include <string>
#include <vector>
#include <cstddef>
namespace osrm
{
@@ -39,6 +49,8 @@ namespace contractor
class Contractor
{
public:
using EdgeData = QueryEdge::EdgeData;
explicit Contractor(const ContractorConfig &config_) : config{config_} {}
Contractor(const Contractor &) = delete;
@@ -46,6 +58,14 @@ class Contractor
int Run();
protected:
void ContractGraph(const unsigned max_edge_id,
util::DeallocatingVector<extractor::EdgeBasedEdge> &edge_based_edge_list,
util::DeallocatingVector<QueryEdge> &contracted_edge_list,
std::vector<EdgeWeight> &&node_weights,
std::vector<bool> &is_core_node,
std::vector<float> &inout_node_levels) const;
private:
ContractorConfig config;
};
+2 -4
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -45,7 +45,7 @@ struct ContractorConfig final : storage::IOConfig
ContractorConfig()
: IOConfig({".osrm.ebg", ".osrm.ebg_nodes", ".osrm.properties"},
{},
{".osrm.hsgr", ".osrm.enw"}),
{".osrm.level", ".osrm.core", ".osrm.hsgr", ".osrm.enw"}),
requested_num_threads(0)
{
}
@@ -61,12 +61,10 @@ struct ContractorConfig final : storage::IOConfig
updater::UpdaterConfig updater_config;
// DEPRECATED to be removed in v6.0
bool use_cached_priority;
unsigned requested_num_threads;
// DEPRECATED to be removed in v6.0
// A percentage of vertices that will be contracted for the hierarchy.
// Offers a trade-off between preprocessing and query time.
// The remaining vertices form the core of the hierarchy
+49
View File
@@ -14,6 +14,37 @@ namespace contractor
{
namespace files
{
// reads .osrm.core
template <typename CoreVectorT>
void readCoreMarker(const boost::filesystem::path &path, std::vector<CoreVectorT> &cores)
{
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
"cores must be a vector of boolean vectors");
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
auto num_cores = reader.ReadElementCount64();
cores.resize(num_cores);
for (const auto index : util::irange<std::size_t>(0, num_cores))
{
storage::serialization::read(reader, cores[index]);
}
}
// writes .osrm.core
template <typename CoreVectorT>
void writeCoreMarker(const boost::filesystem::path &path, const std::vector<CoreVectorT> &cores)
{
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
"cores must be a vector of boolean vectors");
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
writer.WriteElementCount64(cores.size());
for (const auto &core : cores)
{
storage::serialization::write(writer, core);
}
}
// reads .osrm.hsgr file
template <typename QueryGraphT, typename EdgeFilterT>
inline void readGraph(const boost::filesystem::path &path,
@@ -65,6 +96,24 @@ inline void writeGraph(const boost::filesystem::path &path,
storage::serialization::write(writer, filter);
}
}
// reads .levels file
inline void readLevels(const boost::filesystem::path &path, std::vector<float> &node_levels)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
storage::serialization::read(reader, node_levels);
}
// writes .levels file
inline void writeLevels(const boost::filesystem::path &path, const std::vector<float> &node_levels)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, node_levels);
}
}
}
}
@@ -2,7 +2,6 @@
#define OSRM_CONTRACTOR_GRAPH_CONTRACTION_ADAPTORS_HPP_
#include "contractor/contractor_graph.hpp"
#include "util/log.hpp"
#include "util/percent.hpp"
@@ -126,10 +125,9 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
return ContractorGraph{number_of_nodes, edges};
}
template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT graph)
template <class Edge, typename GraphT> inline util::DeallocatingVector<Edge> toEdges(GraphT graph)
{
std::vector<Edge> edges;
edges.reserve(graph.GetNumberOfEdges());
util::DeallocatingVector<Edge> edges;
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
@@ -165,7 +163,6 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
tbb::parallel_sort(edges.begin(), edges.end());
auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin());
edges.shrink_to_fit();
return edges;
}
+26
View File
@@ -17,6 +17,13 @@ struct Algorithm final
{
};
}
// Contraction Hiearchy with core
namespace corech
{
struct Algorithm final
{
};
}
// Multi-Level Dijkstra
namespace mld
{
@@ -28,6 +35,7 @@ struct Algorithm final
// Algorithm names
template <typename AlgorithmT> const char *name();
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
@@ -75,6 +83,24 @@ template <> struct HasExcludeFlags<ch::Algorithm> final : std::true_type
{
};
// Algorithms supported by Contraction Hierarchies with core
// the rest is disabled because of performance reasons
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
{
};
template <> struct HasExcludeFlags<corech::Algorithm> final : std::true_type
{
};
// Algorithms supported by Multi-Level Dijkstra
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
{
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -20,6 +20,7 @@ namespace datafacade
// Namespace local aliases for algorithms
using CH = routing_algorithms::ch::Algorithm;
using CoreCH = routing_algorithms::corech::Algorithm;
using MLD = routing_algorithms::mld::Algorithm;
template <typename AlgorithmT> class AlgorithmDataFacade;
@@ -56,6 +57,14 @@ template <> class AlgorithmDataFacade<CH>
const std::function<bool(EdgeData)> filter) const = 0;
};
template <> class AlgorithmDataFacade<CoreCH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
virtual bool IsCoreNode(const NodeID id) const = 0;
};
template <> class AlgorithmDataFacade<MLD>
{
public:
@@ -12,7 +12,6 @@
#include "customizer/edge_based_graph.hpp"
#include "extractor/datasources.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/intersection_bearings_container.hpp"
@@ -166,6 +165,50 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
: public datafacade::AlgorithmDataFacade<CoreCH>
{
private:
util::vector_view<bool> m_is_core_node;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
void InitializeCoreInformationPointer(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
auto core_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::CH_CORE_MARKER_0 + exclude_index);
auto core_marker_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, core_block_id);
util::vector_view<bool> is_core_node(core_marker_ptr,
data_layout.num_entries[core_block_id]);
m_is_core_node = std::move(is_core_node);
}
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
}
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
InitializeCoreInformationPointer(data_layout, memory_block, exclude_index);
}
bool IsCoreNode(const NodeID id) const override final
{
BOOST_ASSERT(m_is_core_node.empty() || id < m_is_core_node.size());
return !m_is_core_node.empty() || m_is_core_node[id];
}
};
/**
* This base class implements the Datafacade interface for accessing
* data that's stored in a single large block of memory (RAM).
@@ -294,21 +337,36 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
char *memory_ptr)
{
const auto edge_based_node_list_ptr = layout.GetBlockPtr<extractor::EdgeBasedNode>(
memory_ptr, storage::DataLayout::EDGE_BASED_NODE_DATA_LIST);
util::vector_view<extractor::EdgeBasedNode> edge_based_node_data_list(
edge_based_node_list_ptr,
layout.num_entries[storage::DataLayout::EDGE_BASED_NODE_DATA_LIST]);
const auto via_geometry_list_ptr =
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST);
util::vector_view<GeometryID> geometry_ids(
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]);
const auto annotation_data_list_ptr =
layout.GetBlockPtr<extractor::NodeBasedEdgeAnnotation>(
memory_ptr, storage::DataLayout::ANNOTATION_DATA_LIST);
util::vector_view<extractor::NodeBasedEdgeAnnotation> annotation_data(
annotation_data_list_ptr,
layout.num_entries[storage::DataLayout::ANNOTATION_DATA_LIST]);
const auto name_id_list_ptr =
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST);
util::vector_view<NameID> name_ids(name_id_list_ptr,
layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
edge_based_node_data = extractor::EdgeBasedNodeDataView(
std::move(edge_based_node_data_list), std::move(annotation_data));
const auto component_id_list_ptr =
layout.GetBlockPtr<ComponentID>(memory_ptr, storage::DataLayout::COMPONENT_ID_LIST);
util::vector_view<ComponentID> component_ids(
component_id_list_ptr, layout.num_entries[storage::DataLayout::COMPONENT_ID_LIST]);
const auto travel_mode_list_ptr = layout.GetBlockPtr<extractor::TravelMode>(
memory_ptr, storage::DataLayout::TRAVEL_MODE_LIST);
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
const auto classes_list_ptr =
layout.GetBlockPtr<extractor::ClassData>(memory_ptr, storage::DataLayout::CLASSES_LIST);
util::vector_view<extractor::ClassData> classes(
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
std::move(name_ids),
std::move(component_ids),
std::move(travel_modes),
std::move(classes));
}
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
@@ -400,6 +458,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
auto num_entries = data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST];
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::vector_view<NodeID> geometry_node_list(geometries_node_list_ptr, num_entries);
@@ -880,10 +939,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
m_lane_description_offsets[lane_description_id + 1]);
}
bool IsLeftHandDriving(const NodeID id) const override final
bool IsLeftHandDriving() const override final
{
// TODO: can be moved to a data block indexed by GeometryID
return edge_based_node_data.IsLeftHandDriving(id);
return m_profile_properties->left_hand_driving;
}
};
@@ -904,6 +962,21 @@ class ContiguousInternalMemoryDataFacade<CH>
}
};
template <>
class ContiguousInternalMemoryDataFacade<CoreCH> final
: public ContiguousInternalMemoryDataFacade<CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacade<CH>(allocator, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator, exclude_index)
{
}
};
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
{
// MLD data
@@ -190,7 +190,7 @@ class BaseDataFacade
virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0;
virtual bool IsLeftHandDriving(const NodeID id) const = 0;
virtual bool IsLeftHandDriving() const = 0;
};
}
}
+42 -23
View File
@@ -24,6 +24,8 @@
#include "util/fingerprint.hpp"
#include "util/json_container.hpp"
#include <tbb/task_scheduler_init.h>
#include <memory>
#include <string>
@@ -53,7 +55,8 @@ template <typename Algorithm> class Engine final : public EngineInterface
{
public:
explicit Engine(const EngineConfig &config)
: route_plugin(config.max_locations_viaroute, config.max_alternatives), //
: task_scheduler(config.use_threads_number),
route_plugin(config.max_locations_viaroute, config.max_alternatives), //
table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), //
@@ -116,7 +119,7 @@ template <typename Algorithm> class Engine final : public EngineInterface
return tile_plugin.HandleRequest(GetAlgorithms(params), params, result);
}
static bool CheckCompatibility(const EngineConfig &config);
static bool CheckCompability(const EngineConfig &config);
private:
template <typename ParametersT> auto GetAlgorithms(const ParametersT &params) const
@@ -125,6 +128,7 @@ template <typename Algorithm> class Engine final : public EngineInterface
}
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
mutable SearchEngineData<Algorithm> heaps;
tbb::task_scheduler_init task_scheduler;
const plugins::ViaRoutePlugin route_plugin;
const plugins::TablePlugin table_plugin;
@@ -135,7 +139,7 @@ template <typename Algorithm> class Engine final : public EngineInterface
};
template <>
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompatibility(const EngineConfig &config)
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (config.use_shared_memory)
{
@@ -161,7 +165,39 @@ bool Engine<routing_algorithms::ch::Algorithm>::CheckCompatibility(const EngineC
}
template <>
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompatibility(const EngineConfig &config)
bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (!Engine<routing_algorithms::ch::Algorithm>::CheckCompability(config))
{
return false;
}
if (config.use_shared_memory)
{
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
using mutex_type = typename decltype(barrier)::mutex_type;
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
auto mem = storage::makeSharedMemory(barrier.data().region);
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER_0) >
sizeof(std::uint64_t) + sizeof(util::FingerPrint);
}
else
{
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.core")))
return false;
storage::io::FileReader in(config.storage_config.GetPath(".osrm.core"),
storage::io::FileReader::VerifyFingerprint);
in.ReadElementCount64(); // number of core markers
const auto number_of_core_markers = in.ReadElementCount64();
return number_of_core_markers > 0;
}
}
template <>
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (config.use_shared_memory)
{
@@ -171,28 +207,11 @@ bool Engine<routing_algorithms::mld::Algorithm>::CheckCompatibility(const Engine
auto mem = storage::makeSharedMemory(barrier.data().region);
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
// checks that all the needed memory blocks are populated
// DataLayout::MLD_CELL_SOURCE_BOUNDARY and DataLayout::MLD_CELL_DESTINATION_BOUNDARY
// are not checked, because in situations where there are so few nodes in the graph that
// they all fit into one cell, they can be empty.
bool empty_data = layout->GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELLS) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_NODE_LIST) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_EDGE_LIST) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_WEIGHTS_0) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_DURATIONS_0) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET) > 0;
return empty_data;
return layout->GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0;
}
else
{
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.partition")) ||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.cells")) ||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.mldgr")) ||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.cell_metrics")))
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.partition")))
return false;
storage::io::FileReader in(config.storage_config.GetPath(".osrm.partition"),
storage::io::FileReader::VerifyFingerprint);
+11 -8
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -57,14 +57,16 @@ namespace engine
*
* You can chose between three algorithms:
* - Algorithm::CH
* Contraction Hierarchies, extremely fast queries but slow pre-processing. The default right
* Contraction Hierarchies, extremely fast queries but slow pre-processing. The default right
* now.
* - Algorithm::CoreCH
* Deprecated, to be removed in v6.0
* Contraction Hierachies with partial contraction for faster pre-processing but slower
* queries.
* Contractoin Hierachies with partial contraction for faster pre-processing but slower queries.
* - Algorithm::MLD
* Multi Level Dijkstra, moderately fast in both pre-processing and query.
* Multi Level Dijkstra which is experimental and moderately fast in both pre-processing and
* query.
*
* Algorithm::CH is specified we will automatically upgrade to CoreCH if we find the data for it.
* If Algorithm::CoreCH is specified and we don't find the speedup data, we fail hard.
*
* \see OSRM, StorageConfig
*/
@@ -74,8 +76,8 @@ struct EngineConfig final
enum class Algorithm
{
CH,
CoreCH, // Deprecated, will be removed in v6.0
CH, // will upgrade to CoreCH if it finds core data
CoreCH, // will fail hard if there is no core data
MLD
};
@@ -88,6 +90,7 @@ struct EngineConfig final
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true;
Algorithm algorithm = Algorithm::CH;
int use_threads_number = 1;
std::string verbosity;
};
}
+1 -1
View File
@@ -650,7 +650,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool input_coordinate_is_at_right = !util::coordinate_calculation::isCCW(
coordinates[segment.data.u], coordinates[segment.data.v], input_coordinate);
if (datafacade.IsLeftHandDriving(segment.data.forward_segment_id.id))
if (datafacade.IsLeftHandDriving())
input_coordinate_is_at_right = !input_coordinate_is_at_right;
return std::make_pair(input_coordinate_is_at_right, (!input_coordinate_is_at_right));
@@ -4,7 +4,6 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include "util/bearing.hpp"
#include "util/guidance/name_announcements.hpp"
#include <boost/range/algorithm_ext/erase.hpp>
@@ -190,27 +189,6 @@ inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> st
return steps;
}
inline double totalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_step)
{
if (entry_step.geometry_begin > exit_step.geometry_begin)
return totalTurnAngle(exit_step, entry_step);
const auto exit_intersection = exit_step.intersections.front();
const auto entry_intersection = entry_step.intersections.front();
if ((exit_intersection.out >= exit_intersection.bearings.size()) ||
(entry_intersection.in >= entry_intersection.bearings.size()))
return entry_intersection.bearings[entry_intersection.out];
const auto exit_step_exit_bearing = exit_intersection.bearings[exit_intersection.out];
const auto entry_step_entry_bearing =
util::bearing::reverse(entry_intersection.bearings[entry_intersection.in]);
const double total_angle =
util::bearing::angleBetween(entry_step_entry_bearing, exit_step_exit_bearing);
return total_angle;
}
} /* namespace guidance */
} /* namespace engine */
} /* namespace osrm */
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+3 -2
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -181,7 +181,8 @@ struct PhantomNode
unsigned short is_valid_forward_target : 1;
unsigned short is_valid_reverse_source : 1;
unsigned short is_valid_reverse_target : 1;
unsigned short bearing : 12;
unsigned short bearing : 9;
unsigned short : 3; // Unused padding out to 16 bits (2 bytes)
};
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
+18 -26
View File
@@ -183,32 +183,6 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatc
allow_splitting);
}
template <typename Algorithm>
std::vector<EdgeDuration> RoutingAlgorithms<Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &_source_indices,
const std::vector<std::size_t> &_target_indices) const
{
BOOST_ASSERT(!phantom_nodes.empty());
auto source_indices = _source_indices;
auto target_indices = _target_indices;
if (source_indices.empty())
{
source_indices.resize(phantom_nodes.size());
std::iota(source_indices.begin(), source_indices.end(), 0);
}
if (target_indices.empty())
{
target_indices.resize(phantom_nodes.size());
std::iota(target_indices.begin(), target_indices.end(), 0);
}
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, std::move(source_indices), std::move(target_indices));
}
template <typename Algorithm>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::GetTileTurns(
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
@@ -217,6 +191,24 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::G
return routing_algorithms::getTileTurns(*facade, edges, sorted_edge_indexes);
}
// CoreCH overrides
template <>
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &,
unsigned) const
{
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
}
template <>
inline std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
{
throw util::exception("ManyToManySearch is disabled due to performance reasons");
}
} // ns engine
} // ns osrm
@@ -15,11 +15,11 @@ namespace engine
namespace routing_algorithms
{
/// This is a stripped down version of the general shortest path algorithm.
/// This is a striped down version of the general shortest path algorithm.
/// The general algorithm always computes two queries for each leg. This is only
/// necessary in case of vias, where the directions of the start node is constrained
/// necessary in case of vias, where the directions of the start node is constrainted
/// by the previous route.
/// This variation is only an optimization for graphs with slow queries, for example
/// This variation is only an optimazation for graphs with slow queries, for example
/// not fully contracted graphs.
template <typename Algorithm>
InternalRouteResult directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
@@ -16,45 +16,24 @@ namespace engine
namespace routing_algorithms
{
namespace
{
struct NodeBucket
{
NodeID middle_node;
unsigned column_index; // a column in the weight/duration matrix
EdgeWeight weight;
EdgeDuration duration;
NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
: middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
{
}
// partial order comparison
bool operator<(const NodeBucket &rhs) const { return middle_node < rhs.middle_node; }
// functor for equal_range
struct Compare
{
bool operator()(const NodeBucket &lhs, const NodeID &rhs) const
{
return lhs.middle_node < rhs;
}
bool operator()(const NodeID &lhs, const NodeBucket &rhs) const
{
return lhs < rhs.middle_node;
}
};
};
}
template <typename Algorithm>
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
namespace mld
{
template <bool DIRECTION>
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
} // mld
} // namespace routing_algorithms
} // namespace engine
@@ -375,6 +375,52 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
} // namespace ch
namespace corech
{
// assumes that heaps are already setup correctly.
// A forced loop might be necessary, if source and target are on the same segment.
// If this is the case and the offsets of the respective direction are larger for the source
// than the target
// then a force loop is required (e.g. source_phantom.forward_segment_id ==
// target_phantom.forward_segment_id
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<corech::Algorithm> &facade,
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
int &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<corech::Algorithm> &facade,
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const PhantomNodes &phantom_nodes,
std::vector<PathData> &unpacked_path)
{
return ch::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
}
} // namespace corech
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -255,8 +255,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
// MLD uses loops forcing only to prune single node paths in forward and/or
// backward direction (there is no need to force loops in MLD but in CH)
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
+6
View File
@@ -64,6 +64,12 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
};
template <>
struct SearchEngineData<routing_algorithms::corech::Algorithm>
: public SearchEngineData<routing_algorithms::ch::Algorithm>
{
};
struct MultiLayerDijkstraHeapData
{
NodeID parent;
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+15 -13
View File
@@ -14,6 +14,8 @@
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_index.hpp"
#include "extractor/way_restriction_map.hpp"
@@ -24,6 +26,7 @@
#include "util/guidance/entry_class.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/packed_vector.hpp"
#include "util/typedefs.hpp"
#include "storage/io.hpp"
@@ -68,12 +71,13 @@ class EdgeBasedGraphFactory
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete;
explicit EdgeBasedGraphFactory(const util::NodeBasedDynamicGraph &node_based_graph,
EdgeBasedNodeDataContainer &node_data_container,
const CompressedEdgeContainer &compressed_edge_container,
explicit EdgeBasedGraphFactory(std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
const std::vector<util::Coordinate> &coordinates,
const extractor::PackedOSMIDs &osm_node_ids,
ProfileProperties profile_properties,
const util::NameTable &name_table,
guidance::LaneDescriptionMap &lane_description_map);
@@ -91,6 +95,7 @@ class EdgeBasedGraphFactory
// The following get access functions destroy the content in the factory
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodes(EdgeBasedNodeDataContainer &data_container);
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
@@ -139,7 +144,7 @@ class EdgeBasedGraphFactory
//! list of edge based nodes (compressed segments)
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
EdgeBasedNodeDataContainer &m_edge_based_node_container;
EdgeBasedNodeDataContainer m_edge_based_node_container;
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
// The number of edge-based nodes is mostly made up out of the edges in the node-based graph.
@@ -150,20 +155,19 @@ class EdgeBasedGraphFactory
std::uint64_t m_number_of_edge_based_nodes;
const std::vector<util::Coordinate> &m_coordinates;
const util::NodeBasedDynamicGraph &m_node_based_graph;
const extractor::PackedOSMIDs &m_osm_node_ids;
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
const std::unordered_set<NodeID> &m_barrier_nodes;
const std::unordered_set<NodeID> &m_traffic_lights;
const CompressedEdgeContainer &m_compressed_edge_container;
CompressedEdgeContainer &m_compressed_edge_container;
ProfileProperties profile_properties;
const util::NameTable &name_table;
guidance::LaneDescriptionMap &lane_description_map;
// In the edge based graph, any traversable (non reversed) edge of the node-based graph forms a
// node of the edge-based graph. To be able to name these nodes, we loop over the node-based
// graph and create a mapping from edges (node-based) to nodes (edge-based). The mapping is
// essentially a prefix-sum over all previous non-reversed edges of the node-based graph.
unsigned LabelEdgeBasedNodes();
unsigned RenumberEdges();
// During the generation of the edge-expanded nodes, we need to also generate duplicates that
// represent state during via-way restrictions (see
@@ -190,8 +194,6 @@ class EdgeBasedGraphFactory
std::size_t skipped_uturns_counter;
std::size_t skipped_barrier_turns_counter;
// mapping of node-based edges to edge-based nodes
std::vector<NodeID> nbe_to_ebn_mapping;
util::ConcurrentIDMap<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
std::vector<BearingClassID> bearing_class_by_node_based_node;
util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID> entry_class_hash;
-21
View File
@@ -1,21 +0,0 @@
#ifndef OSRM_EXTRACTOR_EDGE_BASED_NODE_HPP_
#define OSRM_EXTRACTOR_EDGE_BASED_NODE_HPP_
#include "util/typedefs.hpp"
namespace osrm
{
namespace extractor
{
struct EdgeBasedNode
{
GeometryID geometry_id;
ComponentID component_id;
AnnotationID annotation_id;
};
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_EDGE_BASED_NODE_HPP_
@@ -28,14 +28,12 @@ class ExtractionContainers
void WriteNodes(storage::io::FileWriter &file_out) const;
void WriteEdges(storage::io::FileWriter &file_out) const;
void WriteMetadata(storage::io::FileWriter &file_out) const;
void WriteCharData(const std::string &file_name);
public:
using NodeIDVector = std::vector<OSMNodeID>;
using NodeVector = std::vector<QueryNode>;
using EdgeVector = std::vector<InternalExtractorEdge>;
using AnnotationDataVector = std::vector<NodeBasedEdgeAnnotation>;
using WayIDStartEndVector = std::vector<FirstAndLastSegmentOfWay>;
using NameCharData = std::vector<unsigned char>;
using NameOffsets = std::vector<unsigned>;
@@ -45,7 +43,6 @@ class ExtractionContainers
NodeIDVector used_node_id_list;
NodeVector all_nodes_list;
EdgeVector all_edges_list;
AnnotationDataVector all_edges_annotation_data_list;
NameCharData name_char_data;
NameOffsets name_offsets;
// an adjacency array containing all turn lane masks
+30 -150
View File
@@ -1,8 +1,6 @@
#ifndef EXTRACTION_RELATION_HPP
#define EXTRACTION_RELATION_HPP
#include "util/exception.hpp"
#include <osmium/osm/relation.hpp>
#include <boost/assert.hpp>
@@ -18,181 +16,63 @@ namespace extractor
struct ExtractionRelation
{
class OsmIDTyped
using AttributesMap = std::unordered_map<std::string, std::string>;
using OsmIDTyped = std::pair<osmium::object_id_type, osmium::item_type>;
struct OsmIDTypedHash
{
public:
OsmIDTyped(osmium::object_id_type _id, osmium::item_type _type) : id(_id), type(_type) {}
std::uint64_t GetID() const { return std::uint64_t(id); }
osmium::item_type GetType() const { return type; }
std::uint64_t Hash() const { return id ^ (static_cast<std::uint64_t>(type) << 56); }
private:
osmium::object_id_type id;
osmium::item_type type;
std::size_t operator()(const OsmIDTyped &id) const
{
return id.first ^ (static_cast<std::uint64_t>(id.second) << 56);
}
};
using AttributesList = std::vector<std::pair<std::string, std::string>>;
using MembersRolesList = std::vector<std::pair<std::uint64_t, std::string>>;
ExtractionRelation() : is_restriction(false) {}
explicit ExtractionRelation(const OsmIDTyped &_id) : id(_id) {}
void Clear()
void clear()
{
attributes.clear();
members_role.clear();
is_restriction = false;
values.clear();
}
const char *GetAttr(const std::string &attr) const
bool IsRestriction() const { return is_restriction; }
AttributesMap &GetMember(const osmium::RelationMember &member)
{
auto it = std::lower_bound(
attributes.begin(), attributes.end(), std::make_pair(attr, std::string()));
if (it != attributes.end() && (*it).first == attr)
return (*it).second.c_str();
return nullptr;
return values[OsmIDTyped(member.ref(), member.type())];
}
void Prepare()
{
std::sort(attributes.begin(), attributes.end());
std::sort(members_role.begin(), members_role.end());
}
void AddMember(const OsmIDTyped &member_id, const char *role)
{
members_role.emplace_back(std::make_pair(member_id.Hash(), std::string(role)));
}
const char *GetRole(const OsmIDTyped &member_id) const
{
const auto hash = member_id.Hash();
auto it = std::lower_bound(
members_role.begin(), members_role.end(), std::make_pair(hash, std::string()));
if (it != members_role.end() && (*it).first == hash)
return (*it).second.c_str();
return nullptr;
}
OsmIDTyped id;
AttributesList attributes;
MembersRolesList members_role;
bool is_restriction;
std::unordered_map<OsmIDTyped, AttributesMap, OsmIDTypedHash> values;
};
// It contains data of all parsed relations for each node/way element
class ExtractionRelationContainer
{
public:
using AttributesMap = ExtractionRelation::AttributesList;
using AttributesMap = ExtractionRelation::AttributesMap;
using OsmIDTyped = ExtractionRelation::OsmIDTyped;
using RelationList = std::vector<AttributesMap>;
using RelationIDList = std::vector<ExtractionRelation::OsmIDTyped>;
using RelationRefMap = std::unordered_map<std::uint64_t, RelationIDList>;
void AddRelation(ExtractionRelation &&rel)
void AddRelation(const ExtractionRelation &rel)
{
rel.Prepare();
BOOST_ASSERT(relations_data.find(rel.id.GetID()) == relations_data.end());
relations_data.insert(std::make_pair(rel.id.GetID(), std::move(rel)));
BOOST_ASSERT(!rel.is_restriction);
for (auto it : rel.values)
data[it.first].push_back(it.second);
}
void AddRelationMember(const OsmIDTyped &relation_id, const OsmIDTyped &member_id)
const RelationList &Get(const OsmIDTyped &id) const
{
switch (member_id.GetType())
{
case osmium::item_type::node:
node_refs[member_id.GetID()].push_back(relation_id);
break;
const auto it = data.find(id);
if (it != data.end())
return it->second;
case osmium::item_type::way:
way_refs[member_id.GetID()].push_back(relation_id);
break;
case osmium::item_type::relation:
rel_refs[member_id.GetID()].push_back(relation_id);
break;
default:
break;
};
}
void Merge(ExtractionRelationContainer &&other)
{
for (auto it : other.relations_data)
{
const auto res = relations_data.insert(std::make_pair(it.first, std::move(it.second)));
BOOST_ASSERT(res.second);
(void)res; // prevent unused warning in release
}
auto MergeRefMap = [&](RelationRefMap &source, RelationRefMap &target) {
for (auto it : source)
{
auto &v = target[it.first];
v.insert(v.end(), it.second.begin(), it.second.end());
}
};
MergeRefMap(other.way_refs, way_refs);
MergeRefMap(other.node_refs, node_refs);
MergeRefMap(other.rel_refs, rel_refs);
}
std::size_t GetRelationsNum() const { return relations_data.size(); }
const RelationIDList &GetRelations(const OsmIDTyped &member_id) const
{
auto getFromMap = [this](std::uint64_t id,
const RelationRefMap &map) -> const RelationIDList & {
auto it = map.find(id);
if (it != map.end())
return it->second;
return empty_rel_list;
};
switch (member_id.GetType())
{
case osmium::item_type::node:
return getFromMap(member_id.GetID(), node_refs);
case osmium::item_type::way:
return getFromMap(member_id.GetID(), way_refs);
case osmium::item_type::relation:
return getFromMap(member_id.GetID(), rel_refs);
default:
break;
}
return empty_rel_list;
}
const ExtractionRelation &GetRelationData(const ExtractionRelation::OsmIDTyped &rel_id) const
{
auto it = relations_data.find(rel_id.GetID());
if (it == relations_data.end())
throw osrm::util::exception("Can't find relation data for " +
std::to_string(rel_id.GetID()));
return it->second;
static RelationList empty;
return empty;
}
private:
RelationIDList empty_rel_list;
std::unordered_map<std::uint64_t, ExtractionRelation> relations_data;
// each map contains list of relation id's, that has keyed id as a member
RelationRefMap way_refs;
RelationRefMap node_refs;
RelationRefMap rel_refs;
std::unordered_map<OsmIDTyped, RelationList, ExtractionRelation::OsmIDTypedHash> data;
};
} // namespace extractor
+8 -19
View File
@@ -14,28 +14,19 @@ namespace extractor
struct ExtractionTurn
{
ExtractionTurn(const guidance::ConnectedRoad &turn,
bool has_traffic_light,
bool source_restricted,
bool target_restricted,
bool is_left_hand_driving)
ExtractionTurn(const guidance::ConnectedRoad &turn, bool has_traffic_light)
: angle(180. - turn.angle), turn_type(turn.instruction.type),
direction_modifier(turn.instruction.direction_modifier),
has_traffic_light(has_traffic_light), source_restricted(source_restricted),
target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving),
weight(0.), duration(0.)
has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false),
target_restricted(false)
{
}
ExtractionTurn(bool has_traffic_light,
bool source_restricted,
bool target_restricted,
bool is_left_hand_driving)
ExtractionTurn(const bool has_traffic_light = false)
: angle(0), turn_type(guidance::TurnType::NoTurn),
direction_modifier(guidance::DirectionModifier::Straight),
has_traffic_light(has_traffic_light), source_restricted(source_restricted),
target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving),
weight(0.), duration(0.)
has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false),
target_restricted(false)
{
}
@@ -43,12 +34,10 @@ struct ExtractionTurn
const guidance::TurnType::Enum turn_type;
const guidance::DirectionModifier::Enum direction_modifier;
const bool has_traffic_light;
const bool source_restricted;
const bool target_restricted;
const bool is_left_hand_driving;
double weight;
double duration;
bool source_restricted;
bool target_restricted;
};
}
}
+6 -11
View File
@@ -46,22 +46,21 @@ struct ExtractionWay
backward_rate = -1;
duration = -1;
weight = -1;
roundabout = false;
circular = false;
is_startpoint = true;
name.clear();
ref.clear();
pronunciation.clear();
destinations.clear();
exits.clear();
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
turn_lanes_forward.clear();
turn_lanes_backward.clear();
road_classification = guidance::RoadClassification();
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
roundabout = false;
circular = false;
is_startpoint = true;
forward_restricted = false;
backward_restricted = false;
is_left_hand_driving = false;
forward_restricted = false;
}
// wrappers to allow assigning nil (nullptr) to string values
@@ -110,15 +109,11 @@ struct ExtractionWay
guidance::RoadClassification road_classification;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
// Boolean flags
bool roundabout : 1;
bool circular : 1;
bool is_startpoint : 1;
bool forward_restricted : 1;
bool backward_restricted : 1;
bool is_left_hand_driving : 1;
bool : 2;
};
}
}
+19 -23
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -32,7 +32,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "extractor/edge_based_graph_factory.hpp"
#include "extractor/extractor_config.hpp"
#include "extractor/graph_compressor.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@@ -62,27 +61,19 @@ class Extractor
std::vector<ConditionalTurnRestriction>>
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
EdgeID BuildEdgeExpandedGraph(
// input data
const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
const std::vector<TurnRestriction> &turn_restrictions,
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
// might have to be updated to add new lane combinations
guidance::LaneDescriptionMap &turn_lane_map,
// for calculating turn penalties
ScriptingEnvironment &scripting_environment,
// output data
EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file);
std::pair<std::size_t, EdgeID>
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
std::vector<util::Coordinate> &coordinates,
extractor::PackedOSMIDs &osm_node_ids,
EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
guidance::LaneDescriptionMap &turn_lane_map);
void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
const std::vector<EdgeBasedNodeSegment> &input_node_segments,
@@ -91,6 +82,11 @@ class Extractor
std::vector<bool> node_is_startpoint,
const std::vector<util::Coordinate> &coordinates);
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
std::shared_ptr<util::NodeBasedDynamicGraph>
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
std::unordered_set<NodeID> &traffic_lights,
std::vector<util::Coordinate> &coordinates,
extractor::PackedOSMIDs &osm_node_ids);
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
static void WriteCompressedNodeBasedGraph(const std::string &path,
+2 -5
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -68,8 +68,7 @@ struct ExtractorConfig final : storage::IOConfig
".osrm.icd",
".osrm.cnbg",
".osrm.cnbg_to_ebg"}),
requested_num_threads(0),
use_locations_cache(true)
requested_num_threads(0)
{
}
@@ -80,7 +79,6 @@ struct ExtractorConfig final : storage::IOConfig
boost::filesystem::path input_path;
boost::filesystem::path profile_path;
std::vector<boost::filesystem::path> location_dependent_data_paths;
unsigned requested_num_threads;
unsigned small_component_size;
@@ -89,7 +87,6 @@ struct ExtractorConfig final : storage::IOConfig
bool use_metadata;
bool parse_conditionals;
bool use_locations_cache;
};
}
}
+4 -4
View File
@@ -78,27 +78,27 @@ inline void writeProfileProperties(const boost::filesystem::path &path,
template <typename EdgeBasedEdgeVector>
void writeEdgeBasedGraph(const boost::filesystem::path &path,
EdgeID const number_of_edge_based_nodes,
EdgeID const max_edge_id,
const EdgeBasedEdgeVector &edge_based_edge_list)
{
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
writer.WriteElementCount64(number_of_edge_based_nodes);
writer.WriteElementCount64(max_edge_id);
storage::serialization::write(writer, edge_based_edge_list);
}
template <typename EdgeBasedEdgeVector>
void readEdgeBasedGraph(const boost::filesystem::path &path,
EdgeID &number_of_edge_based_nodes,
EdgeID &max_edge_id,
EdgeBasedEdgeVector &edge_based_edge_list)
{
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
number_of_edge_based_nodes = reader.ReadElementCount64();
max_edge_id = reader.ReadElementCount64();
storage::serialization::read(reader, edge_based_edge_list);
}
-1
View File
@@ -29,7 +29,6 @@ class GraphCompressor
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
util::NodeBasedDynamicGraph &graph,
const std::vector<NodeBasedEdgeAnnotation> &node_data_container,
CompressedEdgeContainer &geometry_compressor);
private:
@@ -225,7 +225,7 @@ class CoordinateExtractor
const std::vector<double> &segment_distances,
const double segment_length,
const double considered_lane_width,
const extractor::NodeBasedEdgeClassification &edge_data) const;
const util::NodeBasedEdgeData &edge_data) const;
/*
* If the very first coordinate is within lane offsets and the rest offers a near straight line,
@@ -16,7 +16,6 @@ class DrivewayHandler final : public IntersectionHandler
public:
DrivewayHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
@@ -38,7 +38,6 @@ class IntersectionGenerator
{
public:
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes,
const std::vector<util::Coordinate> &coordinates,
@@ -111,7 +110,6 @@ class IntersectionGenerator
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes;
const std::vector<util::Coordinate> &coordinates;
@@ -33,7 +33,6 @@ class IntersectionHandler
{
public:
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
@@ -51,7 +50,6 @@ class IntersectionHandler
protected:
const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const std::vector<util::Coordinate> &coordinates;
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
@@ -126,6 +124,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const IntersectionType &intersection) const
{
using Road = typename IntersectionType::value_type;
using EdgeData = osrm::util::NodeBasedDynamicGraph::EdgeData;
using osrm::util::angularDeviation;
// no obvious road
@@ -136,8 +135,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (intersection.size() == 2)
return 1;
const auto &in_way_edge = node_based_graph.GetEdgeData(via_edge);
const auto &in_way_data = node_data_container.GetAnnotation(in_way_edge.annotation_data);
const EdgeData &in_way_data = node_based_graph.GetEdgeData(via_edge);
// the strategy for picking the most obvious turn involves deciding between
// an overall best candidate and a best candidate that shares the same name
@@ -148,35 +146,35 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
double best_continue_deviation = 180;
/* helper functions */
const auto IsContinueRoad = [&](const NodeBasedEdgeAnnotation &way_data) {
const auto IsContinueRoad = [&](const EdgeData &way_data) {
return !util::guidance::requiresNameAnnounced(
in_way_data.name_id, way_data.name_id, name_table, street_name_suffix_table);
};
auto sameOrHigherPriority = [&](const auto &way_data) {
return way_data.flags.road_classification.GetPriority() <=
in_way_edge.flags.road_classification.GetPriority();
auto sameOrHigherPriority = [&in_way_data](const auto &way_data) {
return way_data.road_classification.GetPriority() <=
in_way_data.road_classification.GetPriority();
};
auto IsLowPriority = [](const auto &way_data) {
return way_data.flags.road_classification.IsLowPriorityRoadClass();
return way_data.road_classification.IsLowPriorityRoadClass();
};
// These two Compare functions are used for sifting out best option and continue
// candidates by evaluating all the ways in an intersection by what they share
// with the in way. Ideal candidates are of similar road class with the in way
// and are require relatively straight turns.
const auto RoadCompare = [&](const auto &lhs, const auto &rhs) {
const auto &lhs_edge = node_based_graph.GetEdgeData(lhs.eid);
const auto &rhs_edge = node_based_graph.GetEdgeData(rhs.eid);
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
const auto lhs_deviation = angularDeviation(lhs.angle, STRAIGHT_ANGLE);
const auto rhs_deviation = angularDeviation(rhs.angle, STRAIGHT_ANGLE);
const bool rhs_same_classification =
rhs_edge.flags.road_classification == in_way_edge.flags.road_classification;
rhs_data.road_classification == in_way_data.road_classification;
const bool lhs_same_classification =
lhs_edge.flags.road_classification == in_way_edge.flags.road_classification;
const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_edge);
const bool rhs_low_priority = IsLowPriority(rhs_edge);
const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_edge);
const bool lhs_low_priority = IsLowPriority(lhs_edge);
lhs_data.road_classification == in_way_data.road_classification;
const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_data);
const bool rhs_low_priority = IsLowPriority(rhs_data);
const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_data);
const bool lhs_low_priority = IsLowPriority(lhs_data);
auto left_tie = std::tie(lhs.entry_allowed,
lhs_same_or_higher_priority,
rhs_low_priority,
@@ -190,10 +188,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
return left_tie > right_tie;
};
const auto RoadCompareSameName = [&](const auto &lhs, const auto &rhs) {
const auto &lhs_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(lhs.eid).annotation_data);
const auto &rhs_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(rhs.eid).annotation_data);
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
const auto lhs_continues = IsContinueRoad(lhs_data);
const auto rhs_continues = IsContinueRoad(rhs_data);
const auto left_tie = std::tie(lhs.entry_allowed, lhs_continues);
@@ -208,14 +204,12 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
best_option = std::distance(begin(intersection), best_option_it);
best_option_deviation = angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE);
const auto &best_option_edge = node_based_graph.GetEdgeData(intersection[best_option].eid);
const auto &best_option_data =
node_data_container.GetAnnotation(best_option_edge.annotation_data);
const auto &best_option_data = node_based_graph.GetEdgeData(intersection[best_option].eid);
// Unless the in way is also low priority, it is generally undesirable to
// indicate that a low priority road is obvious
if (IsLowPriority(best_option_edge) &&
best_option_edge.flags.road_classification != in_way_edge.flags.road_classification)
if (IsLowPriority(best_option_data) &&
best_option_data.road_classification != in_way_data.road_classification)
{
best_option = 0;
best_option_deviation = 180;
@@ -225,13 +219,13 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto straightest = intersection.findClosestTurn(STRAIGHT_ANGLE);
if (straightest != best_option_it)
{
const auto &straightest_edge = node_based_graph.GetEdgeData(straightest->eid);
const EdgeData &straightest_data = node_based_graph.GetEdgeData(straightest->eid);
double straightest_data_deviation = angularDeviation(straightest->angle, STRAIGHT_ANGLE);
const auto deviation_diff =
std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE;
const auto not_ramp_class = !straightest_edge.flags.road_classification.IsRampClass();
const auto not_link_class = !straightest_edge.flags.road_classification.IsLinkClass();
if (deviation_diff && !IsLowPriority(straightest_edge) && not_ramp_class &&
const auto not_ramp_class = !straightest_data.road_classification.IsRampClass();
const auto not_link_class = !straightest_data.road_classification.IsLinkClass();
if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class &&
not_link_class && !IsContinueRoad(best_option_data))
{
best_option = std::distance(begin(intersection), straightest);
@@ -246,9 +240,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
auto best_continue_it =
std::min_element(begin(intersection), end(intersection), RoadCompareSameName);
const auto best_continue_edge = node_based_graph.GetEdgeData(best_continue_it->eid);
const auto best_continue_data =
node_data_container.GetAnnotation(best_continue_edge.annotation_data);
const auto best_continue_data = node_based_graph.GetEdgeData(best_continue_it->eid);
if (IsContinueRoad(best_continue_data) ||
(in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID))
{
@@ -260,7 +252,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
// if the best angle is going straight but the road is turning, declare no obvious turn
if (0 != best_continue && best_option != best_continue &&
best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
best_continue_edge.flags.road_classification == best_option_edge.flags.road_classification)
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification ==
best_option_data.road_classification)
{
return 0;
}
@@ -269,21 +262,17 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
// continue instruction because they share a name with the approaching way
const std::int64_t continue_count =
count_if(++begin(intersection), end(intersection), [&](const auto &way) {
return IsContinueRoad(node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(way.eid).annotation_data));
return IsContinueRoad(node_based_graph.GetEdgeData(way.eid));
});
const std::int64_t continue_count_valid =
count_if(++begin(intersection), end(intersection), [&](const auto &way) {
return IsContinueRoad(node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(way.eid).annotation_data)) &&
way.entry_allowed;
return IsContinueRoad(node_based_graph.GetEdgeData(way.eid)) && way.entry_allowed;
});
// checks if continue candidates are sharp turns
const bool all_continues_are_narrow = [&]() {
return std::count_if(begin(intersection), end(intersection), [&](const Road &road) {
const auto &road_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(road.eid).annotation_data);
const EdgeData &road_data = node_based_graph.GetEdgeData(road.eid);
const double &road_angle = angularDeviation(road.angle, STRAIGHT_ANGLE);
return IsContinueRoad(road_data) && (road_angle < NARROW_TURN_ANGLE);
}) == continue_count;
@@ -307,32 +296,32 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
return true;
// continue data now most certainly exists
const auto &continue_edge = node_based_graph.GetEdgeData(intersection[best_continue].eid);
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
// best_continue is obvious by road class
if (obviousByRoadClass(in_way_edge.flags.road_classification,
continue_edge.flags.road_classification,
best_option_edge.flags.road_classification))
if (obviousByRoadClass(in_way_data.road_classification,
continue_data.road_classification,
best_option_data.road_classification))
return false;
// best_option is obvious by road class
if (obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_edge.flags.road_classification,
continue_edge.flags.road_classification))
if (obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
continue_data.road_classification))
return true;
// the best_option deviation is very straight and not a ramp
if (best_option_deviation < best_continue_deviation &&
best_option_deviation < FUZZY_ANGLE_DIFFERENCE &&
!best_option_edge.flags.road_classification.IsRampClass())
!best_option_data.road_classification.IsRampClass())
return true;
// the continue road is of a lower priority, while the road continues on the same priority
// with a better angle
if (best_option_deviation < best_continue_deviation &&
in_way_edge.flags.road_classification == best_option_edge.flags.road_classification &&
continue_edge.flags.road_classification.GetPriority() >
best_option_edge.flags.road_classification.GetPriority())
in_way_data.road_classification == best_option_data.road_classification &&
continue_data.road_classification.GetPriority() >
best_option_data.road_classification.GetPriority())
return true;
return false;
@@ -346,25 +335,24 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto in_through_candidate =
intersection.FindClosestBearing(util::bearing::reverse(road.bearing));
const auto &in_edge = node_based_graph.GetEdgeData(in_through_candidate->eid);
const auto &out_edge = node_based_graph.GetEdgeData(road.eid);
const auto &in_data = node_based_graph.GetEdgeData(in_through_candidate->eid);
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
// by asking for the same class, we ensure that we do not overrule obvious by road-class
// decisions
const auto same_class =
in_edge.flags.road_classification == out_edge.flags.road_classification;
const auto same_class = in_data.road_classification == out_data.road_classification;
// only if the entry is allowed for one of the two, but not the other, we need to check.
// Otherwise other handlers do it better
const bool is_oneway = !in_through_candidate->entry_allowed && road.entry_allowed;
const bool not_roundabout = !(in_edge.flags.roundabout || in_edge.flags.circular ||
out_edge.flags.roundabout || out_edge.flags.circular);
const bool not_roundabout =
!(in_data.roundabout || in_data.circular || out_data.roundabout || out_data.circular);
// for the purpose of this check, we do not care about low-priority roads (parking lots,
// mostly). Since we postulate both classes to be the same, checking one of the two is
// enough
const bool not_low_priority = !in_edge.flags.road_classification.IsLowPriorityRoadClass();
const bool not_low_priority = !in_data.road_classification.IsLowPriorityRoadClass();
const auto in_deviation = angularDeviation(in_through_candidate->angle, STRAIGHT_ANGLE);
const auto out_deviaiton = angularDeviation(road.angle, STRAIGHT_ANGLE);
@@ -383,11 +371,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto index_candidate = (best_option + 1) % intersection.size();
if (index_candidate == 0)
return index_candidate;
const auto &candidate_edge =
const auto &candidate_data =
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
if (obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_edge.flags.road_classification,
candidate_edge.flags.road_classification))
if (obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
candidate_data.road_classification))
return (index_candidate + 1) % intersection.size();
else
return index_candidate;
@@ -398,11 +386,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto index_candidate = best_option - 1;
if (index_candidate == 0)
return index_candidate;
const auto &candidate_edge =
const auto candidate_data =
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
if (obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_edge.flags.road_classification,
candidate_edge.flags.road_classification))
if (obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
candidate_data.road_classification))
return index_candidate - 1;
else
return index_candidate;
@@ -419,17 +407,17 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best_option;
const auto &left_edge = node_based_graph.GetEdgeData(intersection[left_index].eid);
const auto &right_edge = node_based_graph.GetEdgeData(intersection[right_index].eid);
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid);
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid);
const bool obvious_to_left =
left_index == 0 || obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_edge.flags.road_classification,
left_edge.flags.road_classification);
left_index == 0 || obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
left_data.road_classification);
const bool obvious_to_right =
right_index == 0 || obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_edge.flags.road_classification,
right_edge.flags.road_classification);
right_index == 0 || obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
right_data.road_classification);
// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
// consider the turn obvious
@@ -459,15 +447,14 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
distinction rate. If the road category is smaller, its also adjusted. Only
roads of the same priority require the full distinction ratio.
*/
const auto &best_option_edge =
const auto &best_option_data =
node_based_graph.GetEdgeData(intersection[best_option].eid);
const auto adjusted_distinction_ratio = [&]() {
// obviousness by road classes
if (in_way_edge.flags.road_classification ==
best_option_edge.flags.road_classification &&
best_option_edge.flags.road_classification.GetPriority() <
if (in_way_data.road_classification == best_option_data.road_classification &&
best_option_data.road_classification.GetPriority() <
node_based_graph.GetEdgeData(intersection[index].eid)
.flags.road_classification.GetPriority())
.road_classification.GetPriority())
return 0.8 * DISTINCTION_RATIO;
// if road classes are the same, we use the full ratio
else
@@ -485,9 +472,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
}
else
{
const auto &continue_edge = node_based_graph.GetEdgeData(intersection[best_continue].eid);
const auto &continue_data =
node_data_container.GetAnnotation(continue_edge.annotation_data);
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
if (std::abs(best_continue_deviation) < 1)
return best_continue;
@@ -503,12 +488,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (i == best_continue || !intersection[i].entry_allowed)
continue;
const auto &turn_edge = node_based_graph.GetEdgeData(intersection[i].eid);
const auto &turn_data = node_data_container.GetAnnotation(turn_edge.annotation_data);
const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].eid);
const bool is_obvious_by_road_class =
obviousByRoadClass(in_way_edge.flags.road_classification,
continue_edge.flags.road_classification,
turn_edge.flags.road_classification);
obviousByRoadClass(in_way_data.road_classification,
continue_data.road_classification,
turn_data.road_classification);
// if the main road is obvious by class, we ignore the current road as a potential
// prevention of obviousness
@@ -516,9 +500,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
continue;
// continuation could be grouped with a straight turn and the turning road is a ramp
if (turn_edge.flags.road_classification.IsRampClass() &&
if (turn_data.road_classification.IsRampClass() &&
best_continue_deviation < GROUP_ANGLE &&
!continue_edge.flags.road_classification.IsRampClass())
!continue_data.road_classification.IsRampClass())
continue;
// perfectly straight turns prevent obviousness
@@ -583,13 +567,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
// actually represents a near 180 degree different in bearings between the two
// roads. So if there is a road that is enterable in the opposite direction just
// prior, a turn is not obvious
const auto &turn_edge_data = node_based_graph.GetEdgeData(comparison_road.eid);
const auto &turn_data =
node_data_container.GetAnnotation(turn_edge_data.annotation_data);
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.eid);
if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
angularDeviation(comparison_road.angle, continue_road.angle) <
FUZZY_ANGLE_DIFFERENCE &&
!turn_edge_data.reversed && continue_data.CanCombineWith(turn_data))
!turn_data.reversed && continue_data.CanCombineWith(turn_data))
return 0;
}
}
@@ -43,7 +43,6 @@ class IntersectionNormalizer
std::vector<IntersectionNormalizationOperation> performed_merges;
};
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &node_coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
@@ -37,7 +37,6 @@ class MergableRoadDetector
using MergableRoadData = IntersectionShapeData;
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &node_coordinates,
const IntersectionGenerator &intersection_generator,
const CoordinateExtractor &coordinate_extractor,
@@ -78,10 +77,8 @@ class MergableRoadDetector
// When it comes to merging roads, we need to find out if two ways actually represent the
// same road. This check tries to identify roads which are the same road in opposite directions
bool EdgeDataSupportsMerge(const NodeBasedEdgeClassification &lhs_flags,
const NodeBasedEdgeClassification &rhs_flags,
const NodeBasedEdgeAnnotation &lhs_edge_annotation,
const NodeBasedEdgeAnnotation &rhs_edge_annotation) const;
bool EdgeDataSupportsMerge(const util::NodeBasedEdgeData &lhs_edge_data,
const util::NodeBasedEdgeData &rhs_edge_data) const;
// Detect traffic loops.
// Since OSRM cannot handle loop edges, we cannot directly see a connection between a node and
@@ -141,7 +138,6 @@ class MergableRoadDetector
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const std::vector<util::Coordinate> &node_coordinates;
const IntersectionGenerator &intersection_generator;
const CoordinateExtractor &coordinate_extractor;
@@ -24,7 +24,6 @@ class MotorwayHandler : public IntersectionHandler
{
public:
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
@@ -28,7 +28,6 @@ class NodeBasedGraphWalker
{
public:
NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const IntersectionGenerator &intersection_generator);
/*
@@ -47,7 +46,6 @@ class NodeBasedGraphWalker
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const IntersectionGenerator &intersection_generator;
};
@@ -108,8 +106,7 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
const util::NodeBasedDynamicGraph &node_based_graph) const;
private:
const NameID desired_name_id;
@@ -134,8 +131,7 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
const util::NodeBasedDynamicGraph &node_based_graph) const;
private:
const NameID desired_name_id;
@@ -205,11 +201,8 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
if (next_intersection.size() <= 1)
return {};
auto next_edge_id = selector(current_node_id,
current_edge_id,
next_intersection,
node_based_graph,
node_data_container);
auto next_edge_id =
selector(current_node_id, current_edge_id, next_intersection, node_based_graph);
if (!next_edge_id)
return {};
@@ -231,8 +224,7 @@ struct SkipTrafficSignalBarrierRoadSelector
boost::optional<EdgeID> operator()(const NodeID,
const EdgeID,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &,
const EdgeBasedNodeDataContainer &) const
const util::NodeBasedDynamicGraph &) const
{
if (intersection.isTrafficSignalOrBarrier())
{
@@ -7,6 +7,7 @@
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/roundabout_type.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "util/name_table.hpp"
@@ -40,11 +41,11 @@ class RoundaboutHandler : public IntersectionHandler
{
public:
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties,
const IntersectionGenerator &intersection_generator);
~RoundaboutHandler() override final = default;
@@ -85,6 +86,8 @@ class RoundaboutHandler : public IntersectionHandler
qualifiesAsRoundaboutIntersection(const std::unordered_set<NodeID> &roundabout_nodes) const;
const CompressedEdgeContainer &compressed_edge_container;
const ProfileProperties &profile_properties;
const CoordinateExtractor coordinate_extractor;
};
@@ -26,7 +26,6 @@ class SliproadHandler final : public IntersectionHandler
public:
SliproadHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
@@ -23,7 +23,6 @@ class SuppressModeHandler final : public IntersectionHandler
public:
SuppressModeHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
+2 -2
View File
@@ -41,13 +41,13 @@ class TurnAnalysis
{
public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties);
/* Full Analysis Process for a single node/edge combination. Use with caution, as the process is
* relatively expensive */
@@ -28,7 +28,6 @@ class TurnHandler : public IntersectionHandler
{
public:
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
@@ -73,7 +73,6 @@ class TurnLaneHandler
typedef std::vector<TurnLaneData> LaneDataVector;
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis,
util::guidance::LaneDataIdMap &id_map);
@@ -89,7 +88,6 @@ class TurnLaneHandler
// we need to be able to look at previous intersections to, in some cases, find the correct turn
// lanes for a turn
const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
std::vector<std::uint32_t> turn_lane_offsets;
std::vector<TurnLaneType::Mask> turn_lane_masks;
LaneDescriptionMap &lane_description_map;
+84 -16
View File
@@ -58,24 +58,62 @@ struct InternalExtractorEdge
using WeightData = detail::ByEdgeOrByMeterValue;
using DurationData = detail::ByEdgeOrByMeterValue;
explicit InternalExtractorEdge() : weight_data(), duration_data() {}
explicit InternalExtractorEdge(OSMNodeID source,
OSMNodeID target,
WeightData weight_data,
DurationData duration_data,
util::Coordinate source_coordinate)
: result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
explicit InternalExtractorEdge()
: result(MIN_OSM_NODEID,
MIN_OSM_NODEID,
SPECIAL_NODEID,
0,
0,
false, // forward
false, // backward
false, // roundabout
false, // circular
true, // can be startpoint
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE,
0,
guidance::TurnLaneType::empty,
guidance::RoadClassification()),
weight_data(), duration_data()
{
}
explicit InternalExtractorEdge(NodeBasedEdgeWithOSM edge,
explicit InternalExtractorEdge(OSMNodeID source,
OSMNodeID target,
NodeID name_id,
WeightData weight_data,
DurationData duration_data,
bool forward,
bool backward,
bool roundabout,
bool circular,
bool startpoint,
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
LaneDescriptionID lane_description,
guidance::RoadClassification road_classification,
util::Coordinate source_coordinate)
: result(std::move(edge)), weight_data(weight_data), duration_data(duration_data),
source_coordinate(source_coordinate)
: result(source,
target,
name_id,
0,
0,
forward,
backward,
roundabout,
circular,
startpoint,
restricted,
is_split,
travel_mode,
classes,
lane_description,
std::move(road_classification)),
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
source_coordinate(std::move(source_coordinate))
{
}
@@ -91,13 +129,43 @@ struct InternalExtractorEdge
// necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_osm_value()
{
return InternalExtractorEdge(
MIN_OSM_NODEID, MIN_OSM_NODEID, WeightData(), DurationData(), util::Coordinate());
return InternalExtractorEdge(MIN_OSM_NODEID,
MIN_OSM_NODEID,
SPECIAL_NODEID,
WeightData(),
DurationData(),
false, // forward
false, // backward
false, // roundabout
false, // circular
true, // can be startpoint
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE,
0,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassification(),
util::Coordinate());
}
static InternalExtractorEdge max_osm_value()
{
return InternalExtractorEdge(
MAX_OSM_NODEID, MAX_OSM_NODEID, WeightData(), DurationData(), util::Coordinate());
return InternalExtractorEdge(MAX_OSM_NODEID,
MAX_OSM_NODEID,
SPECIAL_NODEID,
WeightData(),
DurationData(),
false, // forward
false, // backward
false, // roundabout
false, // circular
true, // can be startpoint
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE,
0,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassification(),
util::Coordinate());
}
static InternalExtractorEdge min_internal_value()
@@ -1,54 +0,0 @@
#ifndef OSRM_LOCATION_DEPENDENT_DATA_HPP
#define OSRM_LOCATION_DEPENDENT_DATA_HPP
#include <boost/filesystem/path.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <osmium/osm/way.hpp>
#include <string>
#include <unordered_map>
namespace osrm
{
namespace extractor
{
struct LocationDependentData
{
using point_t = boost::geometry::model::d2::
point_xy<double, boost::geometry::cs::spherical_equatorial<boost::geometry::degree>>;
using segment_t = boost::geometry::model::segment<point_t>;
using polygon_t = boost::geometry::model::polygon<point_t>;
using polygon_bands_t = std::vector<std::vector<segment_t>>;
using box_t = boost::geometry::model::box<point_t>;
using polygon_position_t = std::size_t;
using rtree_t = boost::geometry::index::rtree<std::pair<box_t, polygon_position_t>,
boost::geometry::index::rstar<8>>;
using property_t = boost::variant<boost::blank, double, std::string, bool>;
using properties_t = std::unordered_map<std::string, property_t>;
LocationDependentData(const std::vector<boost::filesystem::path> &file_paths);
bool empty() const { return rtree.empty(); }
std::vector<std::size_t> GetPropertyIndexes(const point_t &point) const;
property_t FindByKey(const std::vector<std::size_t> &property_indexes, const char *key) const;
private:
void loadLocationDependentData(const boost::filesystem::path &file_path,
std::vector<rtree_t::value_type> &bounding_boxes);
rtree_t rtree;
std::vector<std::pair<polygon_bands_t, std::size_t>> polygons;
std::vector<properties_t> properties;
};
}
}
#endif
+90 -100
View File
@@ -1,9 +1,6 @@
#ifndef NODE_BASED_EDGE_HPP
#define NODE_BASED_EDGE_HPP
#include <cstdint>
#include <tuple>
#include "extractor/class_data.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
@@ -15,98 +12,65 @@ namespace osrm
namespace extractor
{
// Flags describing the class of the road. This data is used during creation of graphs/guidance
// generation but is not available in annotation/navigation
struct NodeBasedEdgeClassification
{
std::uint8_t forward : 1; // 1
std::uint8_t backward : 1; // 1
std::uint8_t is_split : 1; // 1
std::uint8_t roundabout : 1; // 1
std::uint8_t circular : 1; // 1
std::uint8_t startpoint : 1; // 1
std::uint8_t restricted : 1; // 1
guidance::RoadClassification road_classification; // 16 2
NodeBasedEdgeClassification();
NodeBasedEdgeClassification(const bool forward,
const bool backward,
const bool is_split,
const bool roundabout,
const bool circular,
const bool startpoint,
const bool restricted,
guidance::RoadClassification road_classification)
: forward(forward), backward(backward), is_split(is_split), roundabout(roundabout),
circular(circular), startpoint(startpoint), restricted(restricted),
road_classification(road_classification)
{
}
bool operator==(const NodeBasedEdgeClassification &other) const
{
return (road_classification == other.road_classification) && (forward == other.forward) &&
(backward == other.backward) && (is_split) == (other.is_split) &&
(roundabout == other.roundabout) && (circular == other.circular) &&
(startpoint == other.startpoint) && (restricted == other.restricted);
}
};
// Annotative data, used in parts in guidance generation, in parts during navigation (classes) but
// mostly for annotation of edges. The entry can be shared between multiple edges and usually
// describes features present on OSM ways. This is the place to put specific data that you want to
// see as part of the API output but that does not influence navigation
struct NodeBasedEdgeAnnotation
{
NameID name_id; // 32 4
LaneDescriptionID lane_description_id; // 16 2
ClassData classes; // 8 1
TravelMode travel_mode : 4; // 4
bool is_left_hand_driving : 1; // 1
bool CanCombineWith(const NodeBasedEdgeAnnotation &other) const
{
return (
std::tie(name_id, classes, travel_mode, is_left_hand_driving) ==
std::tie(other.name_id, other.classes, other.travel_mode, other.is_left_hand_driving));
}
};
struct NodeBasedEdge
{
NodeBasedEdge();
NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
EdgeDuration duration,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags);
bool forward,
bool backward,
bool roundabout,
bool circular,
bool startpoint,
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification);
bool operator<(const NodeBasedEdge &other) const;
NodeID source; // 32 4
NodeID target; // 32 4
EdgeWeight weight; // 32 4
EdgeDuration duration; // 32 4
GeometryID geometry_id; // 32 4
AnnotationID annotation_data; // 32 4
NodeBasedEdgeClassification flags; // 32 4
NodeID source; // 32 4
NodeID target; // 32 4
NodeID name_id; // 32 4
EdgeWeight weight; // 32 4
EdgeDuration duration; // 32 4
std::uint8_t forward : 1; // 1
std::uint8_t backward : 1; // 1
std::uint8_t roundabout : 1; // 1
std::uint8_t circular : 1; // 1
std::uint8_t startpoint : 1; // 1
std::uint8_t restricted : 1; // 1
std::uint8_t is_split : 1; // 1
TravelMode travel_mode : 4; // 4
ClassData classes; // 8 1
LaneDescriptionID lane_description_id; // 16 2
guidance::RoadClassification road_classification; // 16 2
};
struct NodeBasedEdgeWithOSM : NodeBasedEdge
{
NodeBasedEdgeWithOSM();
NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target,
NodeID name_id,
EdgeWeight weight,
EdgeDuration duration,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags);
bool forward,
bool backward,
bool roundabout,
bool circular,
bool startpoint,
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification);
OSMNodeID osm_source_id;
OSMNodeID osm_target_id;
@@ -114,26 +78,35 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
// Impl.
inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
: forward(false), backward(false), is_split(false), roundabout(false), circular(false),
startpoint(false), restricted(false)
{
}
inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), duration(0),
forward(false), backward(false), roundabout(false), circular(false), startpoint(true),
restricted(false), is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
inline NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
EdgeDuration duration,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags)
: source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
annotation_data(annotation_data), flags(flags)
bool forward,
bool backward,
bool roundabout,
bool circular,
bool startpoint,
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification)
: source(source), target(target), name_id(name_id), weight(weight), duration(duration),
forward(forward), backward(backward), roundabout(roundabout), circular(circular),
startpoint(startpoint), restricted(restricted), is_split(is_split), travel_mode(travel_mode),
classes(classes), lane_description_id(lane_description_id),
road_classification(std::move(road_classification))
{
}
@@ -145,8 +118,7 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{
if (weight == other.weight)
{
return flags.forward && flags.backward &&
((!other.flags.forward) || (!other.flags.backward));
return forward && backward && ((!other.forward) || (!other.backward));
}
return weight < other.weight;
}
@@ -157,22 +129,40 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target,
NodeID name_id,
EdgeWeight weight,
EdgeDuration duration,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags)
: NodeBasedEdge(
SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
bool forward,
bool backward,
bool roundabout,
bool circular,
bool startpoint,
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification)
: NodeBasedEdge(SPECIAL_NODEID,
SPECIAL_NODEID,
name_id,
weight,
duration,
forward,
backward,
roundabout,
circular,
startpoint,
restricted,
is_split,
travel_mode,
classes,
lane_description_id,
std::move(road_classification)),
osm_source_id(std::move(source)), osm_target_id(std::move(target))
{
}
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
: osm_source_id(MIN_OSM_NODEID), osm_target_id(MIN_OSM_NODEID)
{
}
static_assert(sizeof(extractor::NodeBasedEdge) == 28,
"Size of extractor::NodeBasedEdge type is "
"bigger than expected. This will influence "
@@ -1,101 +0,0 @@
#ifndef OSRM_EXTRACTOR_NODE_BASED_GRAPH_FACTORY_HPP_
#define OSRM_EXTRACTOR_NODE_BASED_GRAPH_FACTORY_HPP_
#include "extractor/compressed_edge_container.hpp"
#include "extractor/node_based_edge.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/scripting_environment.hpp"
#include "util/coordinate.hpp"
#include "util/node_based_graph.hpp"
#include <boost/filesystem/path.hpp>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
namespace osrm
{
namespace extractor
{
// Turn the output of the extraction process into a graph that represents junctions as nodes and
// ways as edges between these nodes. The graph forms the further input for OSRMs creation of the
// edge-based graph and is also the basic concept for annotating paths. All information from ways
// that is transferred into the API response is connected to the edges of the node-based graph.
//
// The input to the graph creation is the set of edges, traffic signals, barriers, meta-data,...
// which is generated during extraction and stored within the extraction containers.
class NodeBasedGraphFactory
{
public:
// The node-based graph factory loads the *.osrm file and transforms the data within into the
// node-based graph to represent the OSM network. This includes geometry compression, annotation
// data optimisation and many other aspects. After this step, the edge-based graph factory can
// turn the graph into the routing graph to be used with the navigation algorithms.
NodeBasedGraphFactory(const boost::filesystem::path &input_file,
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
auto const &GetGraph() const { return compressed_output_graph; }
auto const &GetBarriers() const { return barriers; }
auto const &GetTrafficSignals() const { return traffic_signals; }
auto &GetCompressedEdges() { return compressed_edge_container; }
auto &GetCoordinates() { return coordinates; }
auto &GetAnnotationData() { return annotation_data; }
auto &GetOsmNodes() { return osm_node_ids; }
// to reduce the memory footprint, the node-based graph factory allows releasing memory after it
// might have been used for the last time:
void ReleaseOsmNodes();
private:
// Get the information from the *.osrm file (direct product of the extractor callback/extraction
// containers) and prepare the graph creation process
void LoadDataFromFile(const boost::filesystem::path &input_file);
// Compress the node-based graph into a compact representation of itself. This removes storing a
// single edge for every part of the geometry and might also combine meta-data for multiple
// edges into a single representative form
void Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
// Most ways are bidirectional, making the geometry in forward and backward direction the same,
// except for reversal. We make use of this fact by keeping only one representation of the
// geometry around
void CompressGeometry();
// After graph compression, some of the annotation entries might not be referenced anymore. We
// compress the annotation data by relabeling the node-based graph references and removing all
// unreferenced entries
void CompressAnnotationData();
// After produce, this will contain a compresse version of the node-based graph
util::NodeBasedDynamicGraph compressed_output_graph;
// To store the meta-data for the graph that is purely annotative / not used for the navigation
// itself. Since the edges of a node-based graph form the nodes of the edge based graphs, we
// transform this data into the EdgeBasedNodeDataContainer as output storage.
std::vector<NodeBasedEdgeAnnotation> annotation_data;
// General Information about the graph, not used outside of extractor
std::unordered_set<NodeID> barriers;
std::unordered_set<NodeID> traffic_signals;
std::vector<util::Coordinate> coordinates;
// data to keep in sync with the node-based graph
extractor::PackedOSMIDs osm_node_ids;
// for the compressed geometry
extractor::CompressedEdgeContainer compressed_edge_container;
};
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_NODE_BASED_GRAPH_FACTORY_HPP_
+52 -52
View File
@@ -2,8 +2,6 @@
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
#include "extractor/class_data.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/node_based_edge.hpp"
#include "extractor/travel_mode.hpp"
#include "storage/io_fwd.hpp"
@@ -17,10 +15,6 @@ namespace osrm
{
namespace extractor
{
class Extractor;
class EdgeBasedGraphFactory;
namespace detail
{
template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl;
@@ -44,47 +38,54 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
using TravelMode = extractor::TravelMode;
// to fill in data on edgeBasedNodes
friend class osrm::extractor::Extractor;
friend class osrm::extractor::EdgeBasedGraphFactory;
public:
EdgeBasedNodeDataContainerImpl() = default;
EdgeBasedNodeDataContainerImpl(const NodeID number_of_edge_based_nodes,
const AnnotationID number_of_annotations)
: nodes(number_of_edge_based_nodes), annotation_data(number_of_annotations)
EdgeBasedNodeDataContainerImpl(std::size_t size)
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size), classes(size)
{
}
EdgeBasedNodeDataContainerImpl(Vector<EdgeBasedNode> nodes,
Vector<NodeBasedEdgeAnnotation> annotation_data)
: nodes(std::move(nodes)), annotation_data(std::move(annotation_data))
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids,
Vector<NameID> name_ids,
Vector<ComponentID> component_ids,
Vector<TravelMode> travel_modes,
Vector<ClassData> classes)
: geometry_ids(std::move(geometry_ids)), name_ids(std::move(name_ids)),
component_ids(std::move(component_ids)), travel_modes(std::move(travel_modes)),
classes(std::move(classes))
{
}
GeometryID GetGeometryID(const NodeID node_id) const { return nodes[node_id].geometry_id; }
GeometryID GetGeometryID(const NodeID node_id) const { return geometry_ids[node_id]; }
ComponentID GetComponentID(const NodeID node_id) const { return nodes[node_id].component_id; }
TravelMode GetTravelMode(const NodeID node_id) const { return travel_modes[node_id]; }
TravelMode GetTravelMode(const NodeID node_id) const
NameID GetNameID(const NodeID node_id) const { return name_ids[node_id]; }
ComponentID GetComponentID(const NodeID node_id) const { return component_ids[node_id]; }
ClassData GetClassData(const NodeID node_id) const { return classes[node_id]; }
// Used by EdgeBasedGraphFactory to fill data structure
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
void SetData(NodeID node_id,
GeometryID geometry_id,
NameID name_id,
TravelMode travel_mode,
ClassData class_data)
{
return annotation_data[nodes[node_id].annotation_id].travel_mode;
geometry_ids[node_id] = geometry_id;
name_ids[node_id] = name_id;
travel_modes[node_id] = travel_mode;
classes[node_id] = class_data;
}
bool IsLeftHandDriving(const NodeID node_id) const
// Used by EdgeBasedGraphFactory to fill data structure
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
void SetComponentID(NodeID node_id, ComponentID component_id)
{
return annotation_data[nodes[node_id].annotation_id].is_left_hand_driving;
}
NameID GetNameID(const NodeID node_id) const
{
return annotation_data[nodes[node_id].annotation_id].name_id;
}
ClassData GetClassData(const NodeID node_id) const
{
return annotation_data[nodes[node_id].annotation_id].classes;
component_ids[node_id] = component_id;
}
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
@@ -96,30 +97,29 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
void Renumber(const std::vector<std::uint32_t> &permutation)
{
util::inplacePermutation(nodes.begin(), nodes.end(), permutation);
util::inplacePermutation(geometry_ids.begin(), geometry_ids.end(), permutation);
util::inplacePermutation(name_ids.begin(), name_ids.end(), permutation);
util::inplacePermutation(component_ids.begin(), component_ids.end(), permutation);
util::inplacePermutation(travel_modes.begin(), travel_modes.end(), permutation);
util::inplacePermutation(classes.begin(), classes.end(), permutation);
}
NodeID NumberOfNodes() const { return nodes.size(); }
// the number of annotations differs from the number of nodes, since annotations can be shared
// between a large set of nodes
AnnotationID NumberOfAnnotations() const { return annotation_data.size(); }
EdgeBasedNode &GetNode(const NodeID node_id) { return nodes[node_id]; }
EdgeBasedNode const &GetNode(const NodeID node_id) const { return nodes[node_id]; }
NodeBasedEdgeAnnotation &GetAnnotation(const AnnotationID annotation)
// all containers have the exact same size
std::size_t Size() const
{
return annotation_data[annotation];
}
NodeBasedEdgeAnnotation const &GetAnnotation(const AnnotationID annotation) const
{
return annotation_data[annotation];
BOOST_ASSERT(geometry_ids.size() == name_ids.size());
BOOST_ASSERT(geometry_ids.size() == component_ids.size());
BOOST_ASSERT(geometry_ids.size() == travel_modes.size());
BOOST_ASSERT(geometry_ids.size() == classes.size());
return geometry_ids.size();
}
private:
Vector<EdgeBasedNode> nodes;
Vector<NodeBasedEdgeAnnotation> annotation_data;
Vector<GeometryID> geometry_ids;
Vector<NameID> name_ids;
Vector<ComponentID> component_ids;
Vector<TravelMode> travel_modes;
Vector<ClassData> classes;
};
}
@@ -128,7 +128,7 @@ using EdgeBasedNodeDataExternalContainer =
using EdgeBasedNodeDataContainer =
detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::Container>;
using EdgeBasedNodeDataView = detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::View>;
} // namespace extractor
} // namespace osrm
}
}
#endif
+2 -2
View File
@@ -28,7 +28,7 @@ struct ProfileProperties
: traffic_signal_penalty(0), u_turn_penalty(0),
max_speed_for_map_matching(DEFAULT_MAX_SPEED), continue_straight_at_waypoint(true),
use_turn_restrictions(false), left_hand_driving(false), fallback_to_duration(true),
weight_name{"duration"}, class_names{}, call_tagless_node_function(true)
weight_name{"duration"}, call_tagless_node_function(true)
{
std::fill(excludable_classes.begin(), excludable_classes.end(), INAVLID_CLASS_DATA);
BOOST_ASSERT(weight_name[MAX_WEIGHT_NAME_LENGTH] == '\0');
@@ -124,7 +124,7 @@ struct ProfileProperties
bool continue_straight_at_waypoint;
//! flag used for restriction parser (e.g. used for the walk profile)
bool use_turn_restrictions;
bool left_hand_driving; // DEPRECATED: property value is local to edges from API version 2
bool left_hand_driving;
bool fallback_to_duration;
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
+9 -10
View File
@@ -37,6 +37,7 @@ class RestrictionParser;
class ExtractionRelationContainer;
struct ExtractionNode;
struct ExtractionWay;
struct ExtractionRelation;
struct ExtractionTurn;
struct ExtractionSegment;
@@ -58,19 +59,17 @@ class ScriptingEnvironment
virtual std::vector<std::string> GetClassNames() = 0;
virtual std::vector<std::string> GetNameSuffixList() = 0;
virtual std::vector<std::string> GetRestrictions() = 0;
virtual std::vector<std::string> GetRelations() = 0;
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
virtual void
ProcessElements(const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
virtual bool HasLocationDependentData() const = 0;
virtual void ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
};
}
}
+14 -28
View File
@@ -2,7 +2,6 @@
#define SCRIPTING_ENVIRONMENT_LUA_HPP
#include "extractor/extraction_relation.hpp"
#include "extractor/location_dependent_data.hpp"
#include "extractor/raster_source.hpp"
#include "extractor/scripting_environment.hpp"
@@ -21,18 +20,13 @@ namespace extractor
struct LuaScriptingContext final
{
LuaScriptingContext(const LocationDependentData &location_dependent_data)
: location_dependent_data(location_dependent_data),
last_location_point(0., 180.) // assume (0,180) is invalid coordinate
{
}
void ProcessNode(const osmium::Node &,
ExtractionNode &result,
const ExtractionRelationContainer &relations);
const ExtractionRelationContainer::RelationList &relations);
void ProcessWay(const osmium::Way &,
ExtractionWay &result,
const ExtractionRelationContainer &relations);
const ExtractionRelationContainer::RelationList &relations);
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
ProfileProperties properties;
RasterContainer raster_sources;
@@ -41,20 +35,17 @@ struct LuaScriptingContext final
bool has_turn_penalty_function;
bool has_node_function;
bool has_way_function;
bool has_relation_function;
bool has_segment_function;
sol::function turn_function;
sol::function way_function;
sol::function node_function;
sol::function relation_function;
sol::function segment_function;
int api_version;
sol::table profile_table;
// Reference to immutable location dependent data and locations memo
const LocationDependentData &location_dependent_data;
LocationDependentData::point_t last_location_point;
std::vector<std::size_t> last_location_indexes;
};
/**
@@ -70,9 +61,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
static const constexpr int SUPPORTED_MAX_API_VERSION = 3;
explicit Sol2ScriptingEnvironment(
const std::string &file_name,
const std::vector<boost::filesystem::path> &location_dependent_data_paths);
explicit Sol2ScriptingEnvironment(const std::string &file_name);
~Sol2ScriptingEnvironment() override = default;
const ProfileProperties &GetProfileProperties() override;
@@ -81,19 +70,17 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
std::vector<std::string> GetNameSuffixList() override;
std::vector<std::string> GetClassNames() override;
std::vector<std::string> GetRestrictions() override;
std::vector<std::string> GetRelations() override;
void ProcessTurn(ExtractionTurn &turn) override;
void ProcessSegment(ExtractionSegment &segment) override;
void
ProcessElements(const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
bool HasLocationDependentData() const override { return !location_dependent_data.empty(); }
void ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
private:
LuaScriptingContext &GetSol2Context();
@@ -106,7 +93,6 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
std::mutex init_mutex;
std::string file_name;
tbb::enumerable_thread_specific<std::unique_ptr<LuaScriptingContext>> script_contexts;
const LocationDependentData location_dependent_data;
};
}
}
+10 -10
View File
@@ -120,22 +120,22 @@ template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader,
detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
{
// read header (separate sizes for both vectors)
reader.ReadElementCount64();
reader.ReadElementCount64();
// read actual data
storage::serialization::read(reader, node_data_container.nodes);
storage::serialization::read(reader, node_data_container.annotation_data);
storage::serialization::read(reader, node_data_container.geometry_ids);
storage::serialization::read(reader, node_data_container.name_ids);
storage::serialization::read(reader, node_data_container.component_ids);
storage::serialization::read(reader, node_data_container.travel_modes);
storage::serialization::read(reader, node_data_container.classes);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
{
writer.WriteElementCount64(node_data_container.NumberOfNodes());
writer.WriteElementCount64(node_data_container.NumberOfAnnotations());
storage::serialization::write(writer, node_data_container.nodes);
storage::serialization::write(writer, node_data_container.annotation_data);
storage::serialization::write(writer, node_data_container.geometry_ids);
storage::serialization::write(writer, node_data_container.name_ids);
storage::serialization::write(writer, node_data_container.component_ids);
storage::serialization::write(writer, node_data_container.travel_modes);
storage::serialization::write(writer, node_data_container.classes);
}
inline void read(storage::io::FileReader &reader, NodeRestriction &restriction)
+1 -1
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2017, Project OSRM contributors
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

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