Compare commits

..

97 Commits

Author SHA1 Message Date
Patrick Niklaus 210fa9d545 Update changelog and version 2017-07-19 16:34:49 +00:00
Daniel J. Hofmann 7eafb48d20 Introduces a construction whitelist in profiles 2017-07-19 16:32:42 +00:00
Daniel J. Hofmann df0f407591 Makes construction=minor ways routable again, see #4258 2017-07-19 16:27:31 +00:00
Patrick Niklaus f9a8bcc75c Bump version to v5.9.0-rc.3 2017-07-18 16:50:51 +00:00
Patrick Niklaus f815daf026 Update the changelog 2017-07-18 16:50:24 +00:00
Patrick Niklaus f393f47d43 Move classes to intersection object and don't emit notifications 2017-07-18 16:48:59 +00:00
Daniel J. Hofmann 1e258ed3fa Changelog entry for openmp 2017-07-17 19:24:27 +02:00
Daniel J. Hofmann de084f201c Only enables -fopenmp in case the user wants stxxl 2017-07-17 19:20:35 +02:00
Patrick Niklaus e34a74d4ac Add changelog entry 2017-07-13 21:50:01 +00:00
Daniel J. Hofmann bd1391f6f7 Exposes EngineConfig system-wide limits in Node.js bindings, resolves #4226 2017-07-13 21:49:27 +00:00
Patrick Niklaus f54631619a Add bug fix to changelog 2017-07-13 09:01:08 +00:00
Moritz Kobitzsch 070fa1a24c only consider allowed entries when continuing on motorways 2017-07-13 09:00:00 +00:00
Moritz Kobitzsch f15285e9ee add test indicating missdetection of continuing on motorways 2017-07-13 09:00:00 +00:00
Patrick Niklaus bae21f0d5d Bump version to RC2 2017-07-12 22:13:56 +00:00
Daniel Patterson 305df1fb6e Include osrm-customize when doing 'make install' 2017-07-12 22:12:14 +00:00
Daniel J. Hofmann 9ab0fca31c Canonicalizes all OSM string list handling in the profiles 2017-07-12 22:09:28 +00:00
Michael Krasnyk e2e398edc5 Remove STXXL from OSM parsing and enable in CMake by default 2017-07-11 08:24:29 +00:00
Michael Krasnyk b87366132b Updated ChangeLog 2017-07-11 08:24:29 +00:00
Michael Krasnyk f4ef4b022e Added STXXL configuration 2017-07-11 08:24:29 +00:00
Michael Krasnyk 81d479304e Don't use stxxl vector in contractor 2017-07-11 08:24:29 +00:00
Michael Krasnyk 92b53e5be0 Switch from stxxl::vector to std::vector in extractor 2017-07-11 08:24:29 +00:00
Michael Krasnyk cc73e753bd Removed external_to_internal_node_id_map container 2017-07-11 08:24:28 +00:00
Daniel J. Hofmann 725dc396c7 Fixes Node.js bindings always enabling alternatives when using boolean overload 2017-07-10 10:45:56 +02:00
Daniel J. Hofmann 890f0d8d7e Discards construction and proposed ways, resolves #4230 2017-07-10 10:38:30 +02:00
Patrick Niklaus c9017090a2 Bump verison to 5.9.0-rc.1 2017-07-07 17:07:52 +00:00
Patrick Niklaus e7061591e3 Enable travis on 5.9 2017-07-07 17:06:47 +00:00
Emil Tin 5ede5577d1 avoid fuzzy ferry test 2017-07-07 16:16:13 +00:00
Emil Tin 0bfbe5ad16 handle startpoint in bicycle profile, add tests 2017-07-07 16:16:13 +00:00
Daniel J. Hofmann 54ceb05420 Implements Alternatives for MLD 2017-07-07 16:12:46 +00:00
Patrick Niklaus fef0344be0 Don't use bool flags on ExternalMemoryNode because they blow up the struct 2017-07-07 13:24:34 +00:00
Lev Dragunov b12fee5c0a Load graph before creating a server 2017-07-06 21:18:24 +00:00
Daniel J. Hofmann 1ef75c7a61 Bundles nan, node-cmake and node-pre-gyp for bootstrapping node-osrm, resolves #4216
Building `node-osrm` from source requires nan, node-cmake and
node-pre-gyp npm packages already \*. In order to bootstrap we
bundle these dev packages in the bundle we publish to npm.

\* See `src/nodejs/CMakeLists.txt`

Check `npm pack` - we now expect to see a `node_modules` directory
with nan, node-cmake, and node-pre-gyp already there.
2017-07-06 14:40:43 +00:00
Daniel J. Hofmann 8c5ac84f0c Lets approaches cuke test run under testbot profile, resolves #4181
🥒 🚗-> 🤖
2017-07-06 14:40:21 +00:00
Patrick Niklaus 44739f2dc3 Allow users to specify a class for each way
This adds the ability to mark ways with a user-defined
class in the profile. This class information will be included
in the response as property of the RouteStep object.
2017-07-06 09:17:49 +00:00
Patrick Niklaus d52d530cbe Fix indentation and dead-code from c&p in cucumber to silence eslint 2017-07-05 07:57:46 +00:00
Patrick Niklaus 5fb00ff7bf [skip ci] Revert back gitattributes, was unrelated to OSX 2017-07-04 22:49:30 +00:00
Moritz Kobitzsch 4c7aa8f1c0 only consider narrow turns onto through streets straight 2017-07-04 22:03:04 +00:00
Moritz Kobitzsch 2522f70f86 add test case illustrating 4205 2017-07-04 22:03:04 +00:00
Mateusz Loskot e47e8ed335 Add .gitattributes
Add the good default options as recommended by GitHub.
Helps to work around issues when using hybrid environments like
the Bash On Windows (see #4228).
2017-07-04 20:59:35 +00:00
Daniel J. Hofmann 2927b491c3 Updates Changelog with Exit Numbers 2017-07-04 20:58:19 +00:00
Daniel J. Hofmann ba2a0b3566 Adds more exits cucumber scenarios 2017-07-04 20:58:19 +00:00
Moritz Kobitzsch 98caa0bcd9 adjust name-table checks for increased name table size 2017-07-04 20:58:19 +00:00
Moritz Kobitzsch 4a2a100569 add exits to unit-test initialisation 2017-07-04 20:58:19 +00:00
Moritz Kobitzsch 3073f4c0d1 don't announce something if we loose exit numbers while on the ramp 2017-07-04 20:58:19 +00:00
Daniel J. Hofmann 7d900e3b5a Implements Exit Numbers + Names (junction:ref way tag for now) 2017-07-04 20:58:19 +00:00
Patrick Niklaus 6d78c11fd2 [skip ci] Bump OSRM version to 5.9 2017-07-03 22:44:56 +00:00
Michael Krasnyk 1bee82e288 Make safety penalties graduation for primary, secondary and tertiary 2017-07-03 21:58:32 +00:00
Michael Krasnyk a41caf0efb Adjustment of bicycle profile to review comments 2017-07-03 21:58:32 +00:00
Michael Krasnyk a3e0eb03db Implement bicycle safety penalty 2017-07-03 21:58:32 +00:00
Patrick Niklaus 34f62b4894 Add test case for safety features on cycleways 2017-07-03 21:58:32 +00:00
Michael Krasnyk b28077a437 Use rate rounding up to tenth in routability tests 2017-07-03 21:58:32 +00:00
Michael Krasnyk 359ab2b56e Use highest different level with source but not parent node 2017-07-03 14:57:52 +00:00
Michael Krasnyk e42c23686b Edge case for MLD matrix plugin 2017-07-03 14:57:52 +00:00
Michael Krasnyk d98f1a2632 Update "Multi level routing" test 2017-07-03 14:57:52 +00:00
Michael Krasnyk aa736dbe3a Generalize directShortestPathSearch interface 2017-07-03 14:57:52 +00:00
Michael Krasnyk 3534203083 Generalize manyToManySearch and remove duplications 2017-07-03 14:57:52 +00:00
Michael Krasnyk 517cb5f094 Matrix plugin with MLD overlay 2017-07-03 14:57:52 +00:00
Michael Krasnyk b910ab9bcb Add duration values to overlay graph 2017-07-03 14:57:52 +00:00
Michael Krasnyk 5a29e29535 Add matrix tests that checks MLD overlay 2017-07-03 14:57:52 +00:00
Michael Krasnyk 0fd71260d3 Enable ManyToManySearch in MLD 2017-07-03 14:57:52 +00:00
Michael Krasnyk 54367bfa98 Reduce memory consumption during partition 2017-07-03 14:57:52 +00:00
Michael Krasnyk 1e9806f872 Some osrm-runner fixes 2017-07-03 14:57:52 +00:00
Mateusz Loskot 1e704aa7f2 Ignore Visual Studio/Visual Studio Code related files 2017-07-03 14:42:51 +00:00
Michael Krasnyk 8a404ea850 Use correctly traffic light penalty for no_turn turns 2017-07-03 13:43:13 +02:00
Harry Wood e2e279bc85 example curl command needs quotes
We need to add quotes around the URL in the curl command (at least in the shell
I'm using). Otherwise it truncates the URL at ';'
2017-06-30 14:04:46 +00:00
Michael Krasnyk c914afdbf1 Fix missing-field-initializers warnings in PackedVector 2017-06-30 14:27:43 +02:00
Daniel J. Hofmann 49a057ebc0 Adds a link to Mapbox's mapping for navigation guide 2017-06-30 12:19:14 +02:00
Moritz Kobitzsch d660c1609c don't collapse u-turns into combined turns 2017-06-30 09:25:03 +00:00
Michael Krasnyk 74bc8966a8 Test case with incorrect u-turn collapsing
http://map.project-osrm.org/?z=18&center=52.169237%2C10.032722&loc=52.168628%2C10.030759&loc=52.168707%2C10.030952&loc=52.168457%2C10.030432&hl=en&alt=0
2017-06-30 09:25:03 +00:00
Michael Krasnyk 9d8a3e3c97 Propagate lane data across traffic lights 2017-06-29 15:10:37 +00:00
Michael Krasnyk a308b86056 Test case for #4189 2017-06-29 15:10:37 +00:00
Michael Krasnyk 1b540fe0ba Correct condition for is_going_straight_and_turns_continue 2017-06-29 15:10:37 +00:00
Michael Krasnyk 929e5a4de6 Review adjustments for driveway handler, #4151 2017-06-29 15:07:32 +00:00
Michael Krasnyk df4f0d043a Added driveway handler 2017-06-29 15:07:32 +00:00
Michael Krasnyk 09df8d47a5 Re-enable edge-weight-updates-over-factor test 2017-06-27 13:02:53 +02:00
Michael Krasnyk c8b75c9046 Use thread-safe lock-free assignment in PackedVector::set_value
PR uses TBB internal atomic's for atomic CAS on non-atomic data

Corresponding PR https://github.com/Project-OSRM/osrm-backend/pull/4199

Other options:

* use sequential update

* use an internal packed vector lock -> makes packed vector non-movable

* use boost.interprocess atomics implementation -> outdated and only 32 bit version

* use glib atomic's -> requires new dependency

*  wait for https://isocpp.org/blog/2014/05/n4013 as_atomic

*  use c11 _Atomic and atomic_compare_exchange_weak -> not possible to mix c++11 and c11

* use builtin functions gcc __sync_bool_compare_and_swap and msvc _InterlockedCompareExchange64 -> possible, but requires proper testing

boolean CompareAndSwapPointer(volatile * void * ptr,
                              void * new_value,
                              void * old_value) {
if defined(_MSC_VER)
   if (InterlockedCompareExchange(ptr, new_value, old_value) == old_value) return false;
   else return true;
elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
   return __sync_bool_compare_and_swap(ptr, old_value, new_value);
else
  error No implementation
endif
}

* use Boost.Atomic -> requires new dependency

        WordT local_lower_word = lower_word, new_lower_word;
        do
        {
            new_lower_word = set_lower_value<WordT, T>(local_lower_word,
                                                       lower_mask[internal_index.element],
                                                       lower_offset[internal_index.element],
                                                       value);
        } while (!boost::atomics::detail::operations<sizeof(WordT), false>::compare_exchange_weak(
            lower_word,
            local_lower_word,
            new_lower_word,
            boost::memory_order_release,
            boost::memory_order_relaxed));
2017-06-27 13:02:53 +02:00
Patrick Niklaus dd8f5ac01d Make EMPTY_ENTRY_CLASS constexpr 2017-06-27 09:58:19 +00:00
Patrick Niklaus 22479ff5d8 Avoid dead-lock if other = this 2017-06-27 09:58:19 +00:00
Patrick Niklaus 688b1f8bef Remove serialization test 2017-06-27 09:58:19 +00:00
Patrick Niklaus e5464526c8 Port isc file 2017-06-27 09:58:19 +00:00
Patrick Niklaus 37b8d3acd4 Refactor turn lane passing 2017-06-27 09:58:19 +00:00
Patrick Niklaus 4f13208ce8 Fix the propfile properties reading/writing 2017-06-27 09:58:19 +00:00
Michael Krasnyk 383640caaf Cleanup temporary test files 2017-06-26 11:03:32 +02:00
Michael Krasnyk 42f3401dd7 Add gdb svg printer for facade 2017-06-23 12:28:50 +02:00
Patrick Niklaus 7fb57c924f Explicitly implement move constructor for DeallocationVector 2017-06-23 09:22:30 +00:00
Patrick Niklaus 97592e5bc3 Refactor file writing in OSRM contract 2017-06-23 09:22:30 +00:00
Emil Tin 9922c0f4f7 adjust tests, cycleway allows cycling on footway 2017-06-22 14:20:42 +00:00
Emil Tin f27434f2fb fixes #4060, incorrect cycling against oneways 2017-06-22 14:20:42 +00:00
Daniel J. Hofmann 32d39b7b49 Adds Node.js docs to readme 2017-06-22 14:02:49 +02:00
Daniel J. Hofmann 5c20c7b295 Explains what a roundtrip is in the api docs 2017-06-22 14:01:45 +02:00
Daniel J. Hofmann df000debe9 Adapts obvious turn classification: no longer take entry_allowed into account, resolves #3987 2017-06-21 18:09:32 +02:00
Daniel J. Hofmann 31511416ed Adds a failing test case for obvious turn at the end of the road, see #3987 2017-06-21 18:09:32 +02:00
Patrick Niklaus 99b02cedfb Refactor tile tests 2017-06-19 15:59:38 +00:00
Daniel Patterson 4136bf2808 Add layer to debug tiles to expose all OSM nodes in that area. 2017-06-19 15:59:38 +00:00
Lev Dragunov 93d6fd05a9 No timestamps SIGSEV fix 2017-06-17 17:33:33 +00:00
Lev Dragunov 73c4bc1411 clang-format 2017-06-17 17:33:33 +00:00
Lev Dragunov dc9b4bcfec Time information for maximum distance in matching 2017-06-17 17:33:33 +00:00
151 changed files with 4883 additions and 1585 deletions
+15
View File
@@ -0,0 +1,15 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.cpp text
*.hpp text
# Declare files that will always have CRLF line endings on checkout.
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
# Declare files that will always have LF line endings on checkout.
*.sh text eol=lf
+5
View File
@@ -61,6 +61,11 @@ Thumbs.db
.cproject
.project
# Visual Studio (Code) related files #
######################################
/.vs*
/*.local.bat
# stxxl related files #
#######################
.stxxl
+18 -9
View File
@@ -17,9 +17,9 @@ notifications:
branches:
only:
- master
- "5.8"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
- "5.9"
cache:
yarn: true
@@ -73,7 +73,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
after_success:
- bash <(curl -s https://codecov.io/bash)
@@ -83,7 +83,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
- os: linux
@@ -91,7 +91,7 @@ matrix:
addons: &clang40
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
@@ -116,7 +116,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
- os: linux
@@ -125,12 +125,20 @@ matrix:
TARGET_ARCH='i686' CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
CFLAGS='-m32 -msse2 -mfpmath=sse' CXXFLAGS='-m32 -msse2 -mfpmath=sse'
- os: linux
compiler: "gcc-6-stxxl"
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On
- os: linux
compiler: "gcc-4.9-release"
addons: &gcc49
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
- os: osx
@@ -147,7 +155,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release'
# Shared Library
@@ -156,7 +164,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Disabled because CI slowness
@@ -165,7 +173,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Node build jobs. These skip running the tests.
@@ -324,6 +332,7 @@ install:
-DENABLE_COVERAGE=${ENABLE_COVERAGE:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
-DBUILD_TOOLS=ON \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
+25 -8
View File
@@ -1,11 +1,28 @@
# 5.8.1
- Changes from 5.8.0:
- Bugfixes:
- Fixes #4152: Superflous turn left instruction, when crossing a service-road.
- Fixes #4189: Fixes missing turn lane information after a traffic light.
- Fixes #4199: Data race-condition when updating segment speeds.
- Fixes #3987: Fixes obvious turn detection at T-intersections with slip-roads.
- Fixes #4161: Don't collapse U-Turns with other steps.
# 5.9.0
- Changes from 5.8:
- Algorithm:
- Multi-Level Dijkstra:
- Plugins supported: `table`
- Adds alternative routes support (see [#4047](https://github.com/Project-OSRM/osrm-backend/pull/4047) and [3905](https://github.com/Project-OSRM/osrm-backend/issues/3905)): provides reasonably looking alternative routes (many, if possible) with reasonable query times.
- API:
- Exposes `alternatives=Number` parameter overload in addition to the boolean flag.
- Support for exits numbers and names. New member `exits` in `RouteStep`, based on `junction:ref` on ways
- `Intersection` now has new parameter `classes` that can be set in the profile on each way.
- Profiles:
- `result.exits` allows you to set a way's exit numbers and names, see [`junction:ref`](http://wiki.openstreetmap.org/wiki/Proposed_features/junction_details)
- `ExtractionWay` now as new property `forward_classes` and `backward_classes` that can set in the `way_function`.
The maximum number of classes is 8.
- We now respect the `construction` tag. If the `construction` tag value is not on our whitelist (`minor`, `widening`, `no`) we will exclude the road.
- Node.js Bindings:
- Exposes `alternatives=Number` parameter overload in addition to the boolean flag
- Expose `EngineConfig` options in the node bindings
- Tools:
- Exposes engine limit on number of alternatives to generate `--max-alternatives` in `osrm-routed` (3 by default)
- Infrastructure
- STXXL is not required to build OSRM and is an optional dependency for back-compatibility (ENABLE_STXXL=On)
- OpenMP is only required when the optional STXXL dependency is used
- Bug fixes:
- #4278: Remove superflous continious instruction on a motorway.
# 5.8.0
- Changes from 5.7
+31 -15
View File
@@ -21,6 +21,7 @@ option(BUILD_PACKAGE "Build OSRM package" OFF)
option(ENABLE_ASSERTIONS "Use assertions in release mode" OFF)
option(ENABLE_COVERAGE "Build with coverage instrumentalisation" OFF)
option(ENABLE_SANITIZER "Use memory sanitizer for Debug build" OFF)
option(ENABLE_STXXL "Use STXXL library" ON)
option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
@@ -54,8 +55,8 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 8)
set(OSRM_VERSION_PATCH 1)
set(OSRM_VERSION_MINOR 9)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
@@ -428,9 +429,12 @@ if(ENABLE_MASON)
mason_use(boost_libsystem VERSION ${MASON_BOOST_VERSION})
set(Boost_SYSTEM_LIBRARY ${MASON_PACKAGE_boost_libsystem_STATIC_LIBS})
mason_use(stxxl VERSION ${MASON_STXXL_VERSION})
add_dependency_includes(${MASON_PACKAGE_stxxl_INCLUDE_DIRS})
set(STXXL_LIBRARY ${MASON_PACKAGE_stxxl_STATIC_LIBS})
if (ENABLE_STXXL)
mason_use(stxxl VERSION ${MASON_STXXL_VERSION})
add_dependency_includes(${MASON_PACKAGE_stxxl_INCLUDE_DIRS})
set(MAYBE_STXXL_LIBRARY ${MASON_PACKAGE_stxxl_STATIC_LIBS})
add_definitions(-DUSE_STXXL_LIBRARY)
endif()
mason_use(expat VERSION ${MASON_EXPAT_VERSION})
add_dependency_includes(${MASON_PACKAGE_expat_INCLUDE_DIRS})
@@ -493,8 +497,16 @@ else()
find_package(EXPAT REQUIRED)
add_dependency_includes(${EXPAT_INCLUDE_DIRS})
find_package(STXXL REQUIRED)
add_dependency_includes(${STXXL_INCLUDE_DIR})
if (ENABLE_STXXL)
find_package(STXXL)
if (STXXL_FOUND)
add_dependency_includes(${STXXL_INCLUDE_DIR})
set(MAYBE_STXXL_LIBRARY ${STXXL_LIBRARY})
add_definitions(-DUSE_STXXL_LIBRARY)
else()
MESSAGE(STATUS "STXXL was requested but not found, default STL will be used")
endif()
endif()
find_package(BZip2 REQUIRED)
add_dependency_includes(${BZIP2_INCLUDE_DIR})
@@ -578,11 +590,13 @@ add_dependency_defines(-DBOOST_SPIRIT_USE_PHOENIX_V3)
add_dependency_defines(-DBOOST_RESULT_OF_USE_DECLTYPE)
add_dependency_defines(-DBOOST_FILESYSTEM_NO_DEPRECATED)
set(OpenMP_FIND_QUIETLY ON)
find_package(OpenMP)
if(OPENMP_FOUND)
message(STATUS "OpenMP support found. Linking just in case for stxxl")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
if (ENABLE_STXXL)
set(OpenMP_FIND_QUIETLY ON)
find_package(OpenMP)
if(OPENMP_FOUND)
message(STATUS "OpenMP support found. Linking just in case for stxxl")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
endif()
add_definitions(${OSRM_DEFINES})
@@ -617,7 +631,7 @@ set(EXTRACTOR_LIBRARIES
${EXPAT_LIBRARIES}
${USED_LUA_LIBRARIES}
${OSMIUM_LIBRARIES}
${STXXL_LIBRARY}
${MAYBE_STXXL_LIBRARY}
${TBB_LIBRARIES}
${ZLIB_LIBRARY}
${MAYBE_COVERAGE_LIBRARIES})
@@ -645,7 +659,7 @@ set(CONTRACTOR_LIBRARIES
${BOOST_BASE_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${USED_LUA_LIBRARIES}
${STXXL_LIBRARY}
${MAYBE_STXXL_LIBRARY}
${TBB_LIBRARIES}
${MAYBE_RT_LIBRARY}
${MAYBE_COVERAGE_LIBRARIES})
@@ -665,7 +679,7 @@ set(STORAGE_LIBRARIES
set(UTIL_LIBRARIES
${BOOST_BASE_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${STXXL_LIBRARY}
${MAYBE_STXXL_LIBRARY}
${TBB_LIBRARIES}
${MAYBE_COVERAGE_LIBRARIES})
@@ -734,12 +748,14 @@ install(FILES ${ParametersGlob} DESTINATION include/osrm/engine/api)
install(FILES ${VariantGlob} DESTINATION include/mapbox)
install(TARGETS osrm-extract DESTINATION bin)
install(TARGETS osrm-partition DESTINATION bin)
install(TARGETS osrm-customize DESTINATION bin)
install(TARGETS osrm-contract DESTINATION bin)
install(TARGETS osrm-datastore DESTINATION bin)
install(TARGETS osrm-routed DESTINATION bin)
install(TARGETS osrm DESTINATION lib)
install(TARGETS osrm_extract DESTINATION lib)
install(TARGETS osrm_partition DESTINATION lib)
install(TARGETS osrm_customize DESTINATION lib)
install(TARGETS osrm_update DESTINATION lib)
install(TARGETS osrm_contract DESTINATION lib)
install(TARGETS osrm_store DESTINATION lib)
+32 -3
View File
@@ -16,8 +16,10 @@ The following services are available via HTTP API, C++ library interface and Nod
To quickly try OSRM use our [demo server](http://map.project-osrm.org) which comes with both the backend and a frontend on top.
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [this guide about mapping for navigation](https://www.mapbox.com/mapping/mapping-for-navigation/).
Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
- [node-osrm](https://github.com/Project-OSRM/node-osrm) - Production-ready NodeJs bindings for the routing engine
- [node-osrm](https://www.npmjs.com/package/osrm) - Production-ready NodeJs bindings for the routing engine
- [osrm-frontend](https://github.com/Project-OSRM/osrm-frontend) - User-facing frontend with map. The demo server runs this on top of the backend
- [osrm-text-instructions](https://github.com/Project-OSRM/osrm-text-instructions) - Text instructions from OSRM route response
- [osrm-backend-docker](https://hub.docker.com/r/osrm/osrm-backend/) - Ready to use Docker images
@@ -119,7 +121,7 @@ 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
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
@@ -128,9 +130,36 @@ Read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Ap
Simple query with instructions and alternatives on Berlin:
```
curl https://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
curl "https://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true"
```
### Using the Node.js Bindings
The Node.js bindings provide read-only access to the routing engine.
We provide API documentation and examples [here](docs/nodejs/api.md).
You will need a modern `libstdc++` toolchain (`>= GLIBCXX_3.4.20`) for binary compatibility if you want to use the pre-built binaries.
For older Ubuntu systems you can upgrade your standard library for example with:
```
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update -y
sudo apt-get install -y libstdc++-5-dev
```
You can install the Node.js bindings via `npm install osrm` or from this repository either via
npm install
which will check and use pre-built binaries if they're available for this release and your Node version, or via
npm install --build-from-source
to always force building the Node.js bindings from source.
For usage details have a look [these API docs](docs/nodejs/api.md).
## References in publications
When using the code in a (scientific) publication, please cite
+1 -1
View File
@@ -3,5 +3,5 @@ module.exports = {
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
all: '--strict --require features/support --require features/step_definitions',
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@matrix --tags ~@trip --require features/support --require features/step_definitions -f progress'
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --require features/support --require features/step_definitions -f progress'
}
+13 -10
View File
@@ -165,21 +165,21 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
Finds the fastest route between coordinates in the supplied order.
```endpoint
GET /route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
GET /route/v1/{profile}/{coordinates}?alternatives={true|false|number}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
```
In addition to the [general options](#general-options) the following options are supported for this service:
|Option |Values |Description |
|------------|---------------------------------------------|-------------------------------------------------------------------------------|
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|steps |`true`, `false` (default) |Return route steps for each route leg |
|alternatives|`true`, `false` (default), or Number |Search for alternative routes. Passing a number `alternatives=n` searches for up to `n` alternative routes.\* |
|steps |`true`, `false` (default) |Returned route steps for each route leg |
|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. |
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
\* Please note that even if alternative routes are requested, a result cannot be guaranteed.
**Response**
@@ -275,7 +275,7 @@ In addition to the [general options](#general-options) the following options are
|Option |Values |Description |
|------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|steps |`true`, `false` (default) |Return route steps for each route |
|steps |`true`, `false` (default) |Returned route steps for each route |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
@@ -328,10 +328,10 @@ In addition to the [general options](#general-options) the following options are
|Option |Values |Description |
|------------|------------------------------------------------|---------------------------------------------------------------------------|
|roundtrip |`true` (default), `false` |Return route is a roundtrip (route returns to first location) |
|source |`any` (default), `first` |Return route starts at `any` or `first` coordinate |
|destination |`any` (default), `last` |Return route ends at `any` or `last` coordinate |
|steps |`true`, `false` (default) |Return route instructions for each trip |
|roundtrip |`true` (default), `false` |Returned route is a roundtrip (route returns to first location) |
|source |`any` (default), `first` |Returned route starts at `any` or `first` coordinate |
|destination |`any` (default), `last` |Returned route ends at `any` or `last` coordinate |
|steps |`true`, `false` (default) |Returned route instructions for each trip |
|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
@@ -581,6 +581,7 @@ step.
- `ref`: A reference number or code for the way. Optionally included, if ref data is available for the given way.
- `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit.
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
- `exits`: The exit numbers or names of the way. Will be `undefined` if there are no exit numbers or names.
- `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver.
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
@@ -659,7 +660,7 @@ step.
| `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. The modifier specifies the direction of entering the roundabout. |
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode or classes. If the road takes a turn itself, the `modifier` describes the direction |
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
between all instructions. They only offer a fallback in case nothing else is to report.
@@ -732,6 +733,7 @@ location of the StepManeuver. Further intersections are listed for every cross-w
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
- `bearings`: A list of bearing values (e.g. [0,90,180,270]) that are available at the intersection. The bearings describe all available roads at the intersection. Values are between 0-359 (0=true north)
- `classes`: An array of strings signifying the classes (as specified in the profile) of the road exiting the intersection.
- `entry`: A list of entry flags, corresponding in a 1:1 relationship to the bearings. A value of `true` indicates that the respective road could be entered on a valid route.
`false` indicates that the turn onto the respective road would violate a restriction.
- `in`: index into bearings/entry array. Used to calculate the bearing just before the turn. Namely, the clockwise angle from true north to the
@@ -750,6 +752,7 @@ location of the StepManeuver. Further intersections are listed for every cross-w
"out":2,
"bearings":[60,150,240,330],
"entry":["false","true","true","true"],
"classes": ["toll", "restricted"],
"lanes":{
"indications": ["left", "straight"],
"valid": "false"
+21 -21
View File
@@ -41,7 +41,7 @@ Returns the fastest route between two or more coordinates while visiting the way
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes and return as well.
_Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`)
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route steps for each route leg. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
@@ -188,7 +188,7 @@ if they can not be matched successfully.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
@@ -229,7 +229,25 @@ The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is
only an approximation.
Note that all input coordinates have to be connected for the trip service to work.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route is a roundtrip (route returns to first location). (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
A requirement for computing trips is that all input coordinates are connected.
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
Right now, the following combinations are possible:
@@ -244,24 +262,6 @@ Right now, the following combinations are possible:
| false | any | last | no |
| false | any | any | no |
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
+14 -10
View File
@@ -27,16 +27,16 @@ As you scroll down the file you'll see local variables, and then local functions
The following global properties can be set in your profile:
Attribute | Type | Notes
------------------------------|----------|----------------------------------------------------------------------------
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
use_turn_restrictions | Boolean | Are turn instructions followed? (default `false`)
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `segment_function` will be called for all segments (default `false`)
Attribute | Type | Notes
-------------------------------------|----------|----------------------------------------------------------------------------
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
use_turn_restrictions | Boolean | Are turn instructions followed? (default `false`)
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `segment_function` will be called for all segments (default `false`)
## way_function
@@ -56,6 +56,8 @@ forward_rate | Float | Routing weight, expressed a
backward_rate | Float | " "
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
backward_mode | Enum | " "
forward_classes | Table | Mark this way as being of a specific class, e.g. `result.classes["toll"] = true`. This will be exposed in the API as `classes` on each `RouteStep`.
backward_classes | Table | " "
duration | Float | Alternative setter for duration of the whole way in both directions
weight | Float | Alternative setter for weight of the whole way in both directions
turn_lanes_forward | String | Directions for individual lanes (normalised OSM `turn:lanes` value)
@@ -67,6 +69,8 @@ roundabout | Boolean | Is this part of a roundabou
circular | Boolean | Is this part of a non-roundabout circular junction?
name | String | Name of the way
ref | String | Road number
destinations | String | The road's destinations
exits | String | The ramp's exit numbers or names
pronunciation | String | Name pronunciation
road_classification.motorway_class | Boolean | Guidance: way is a motorway
road_classification.link_class | Boolean | Guidance: way is a slip/link road
+10 -10
View File
@@ -82,16 +82,16 @@ Feature: Bike - Cycle tracks/lanes
Scenario: Bike - Cycleway on oneways, modes
Then routability should be
| highway | cycleway | oneway | forw | backw |
| motorway | track | yes | cycling | |
| residential | track | yes | cycling | pushing bike |
| cycleway | track | yes | cycling | pushing bike |
| footway | track | yes | pushing bike | pushing bike |
| highway | cycleway | oneway | forw | backw |
| motorway | track | yes | cycling | |
| residential | track | yes | cycling | pushing bike |
| cycleway | track | yes | cycling | pushing bike |
| footway | track | yes | cycling | pushing bike |
Scenario: Bike - Cycleway on oneways, speeds
Then routability should be
| highway | cycleway | oneway | forw | backw |
| motorway | track | yes | 15 km/h | |
| residential | track | yes | 15 km/h | 6 km/h |
| cycleway | track | yes | 15 km/h | 6 km/h |
| footway | track | yes | 6 km/h +-1 | 6 km/h +-1 |
| highway | cycleway | oneway | forw | backw |
| motorway | track | yes | 15 km/h | |
| residential | track | yes | 15 km/h | 6 km/h +-1 |
| cycleway | track | yes | 15 km/h | 6 km/h +-1 |
| footway | track | yes | 15 km/h | 6 km/h +-1 |
+1 -2
View File
@@ -53,8 +53,7 @@ Feature: Bike - Handle ferry routes
Scenario: Bike - Ferry duration, multiple nodes
Given the node map
"""
x y
a b c d
x a b c d y
"""
And the ways
+9
View File
@@ -134,3 +134,12 @@ Feature: Bike - Oneway streets
When I route I should get
| from | to | route |
| a | c | ab,bc,bc |
Scenario: Bike - Left/right cycleways on oneways
Then routability should be
| highway | oneway | cycleway:left | cycleway:right | forw | backw |
| primary | yes | | | cycling | pushing bike |
| primary | yes | | track | cycling | pushing bike |
| primary | yes | track | | cycling | cycling |
| primary | yes | track | track | cycling | cycling |
+105
View File
@@ -0,0 +1,105 @@
@routing @bicycle @safety
Feature: Bicycle - Adds penalties to unsafe roads
Background:
Given the profile file
"""
require 'bicycle'
properties.weight_name = 'cyclability'
"""
Scenario: Bike - Apply penalties to ways without cycleways
Then routability should be
| highway | cycleway | forw | backw | forw_rate | backw_rate |
| motorway | | | | | |
| primary | | 15 km/h | 15 km/h | 2.9 | 2.9 |
| secondary | | 15 km/h | 15 km/h | 3.1 | 3.1 |
| tertiary | | 15 km/h | 15 km/h | 3.3 | 3.3 |
| primary_link | | 15 km/h | 15 km/h | 2.9 | 2.9 |
| secondary_link | | 15 km/h | 15 km/h | 3.1 | 3.1 |
| tertiary_link | | 15 km/h | 15 km/h | 3.3 | 3.3 |
| residential | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | 6 km/h +-1 | 6 km/h +-1 | 1.7 | 1.7 |
Scenario: Bike - Apply no penalties to ways with cycleways
Then routability should be
| highway | cycleway | forw | backw | forw_rate | backw_rate |
| motorway | track | 15 km/h | | 4.2 | |
| primary | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| secondary | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| primary_link | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| secondary_link | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary_link | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| residential | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| motorway | lane | 15 km/h | | 4.2 | |
| primary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| secondary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| primary_link | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| secondary_link | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary_link | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| residential | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| motorway | shared_lane | 15 km/h | | 4.2 | |
| primary | shared_lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
Scenario: Bike - Apply no penalties to ways in direction of cycleways
Then routability should be
| highway | cycleway:right | cycleway:left | forw | backw | forw_rate | backw_rate |
| motorway | track | | 15 km/h | | 4.2 | |
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | track | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 |
| motorway | | track | | 15 km/h | | 4.2 |
| primary | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
| tertiary | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
| primary_link | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary_link | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
| tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
| residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | track | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 |
| motorway | lane | | 15 km/h | | 4.2 | |
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 |
| cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | lane | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 |
| motorway | | lane | | 15 km/h | | 4.2 |
| primary | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 3.1 | 4.2 |
| tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
| primary_link | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary_link | | lane | 15 km/h | 15 km/h | 3.1 | 4.2 |
| tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
| residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | lane | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 |
| motorway | shared_lane | | 15 km/h | | 4.2 | |
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| motorway | | shared_lane | | 15 km/h | | 4.2 |
| primary | | shared_lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
Scenario: Bike - Don't apply penalties for all kind of cycleways
Then routability should be
| highway | cycleway | forw | backw | forw_rate | backw_rate |
| tertiary | shared_lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 4.2 |
+53
View File
@@ -0,0 +1,53 @@
@routing @bicycle @startpoint
Feature: Bike - Allowed start/end modes
Background:
Given the profile "bicycle"
Scenario: Bike - Don't start/stop on ferries
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway | route | bicycle |
| ab | primary | | |
| bc | | ferry | yes |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,ab | cycling,cycling |
| 2 | 1 | ab,ab | cycling,cycling |
Scenario: Bike - Don't start/stop on trains
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway | railway | bicycle |
| ab | primary | | |
| bc | | train | yes |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,ab | cycling,cycling |
| 2 | 1 | ab,ab | cycling,cycling |
Scenario: Bike - OK to start pushing bike
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | steps |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,bc,bc | cycling,pushing bike,pushing bike |
| 2 | 1 | bc,ab,ab | pushing bike,cycling,cycling |
+60 -28
View File
@@ -1,39 +1,71 @@
@routing @bicycle @train
Feature: Bike - Handle ferry routes
# Bringing bikes on trains and subways
# We cannot currently use a 'routability' type test, since the bike
# profile does not allow starting/stopping on trains, and
# it's not possible to modify the bicycle profile table because it's
# defined as local.
Background:
Given the profile "bicycle"
Scenario: Bike - Bringing bikes on trains
Then routability should be
| highway | railway | bicycle | bothw |
| primary | | | cycling |
| (nil) | train | | |
| (nil) | train | no | |
| (nil) | train | yes | train |
| (nil) | railway | | |
| (nil) | railway | no | |
| (nil) | railway | yes | train |
| (nil) | subway | | |
| (nil) | subway | no | |
| (nil) | subway | yes | train |
| (nil) | tram | | |
| (nil) | tram | no | |
| (nil) | tram | yes | train |
| (nil) | light_rail | | |
| (nil) | light_rail | no | |
| (nil) | light_rail | yes | train |
| (nil) | monorail | | |
| (nil) | monorail | no | |
| (nil) | monorail | yes | train |
| (nil) | some_tag | | |
| (nil) | some_tag | no | |
| (nil) | some_tag | yes | cycling |
Given the node map
"""
a 1 b c 2 d e 3 f g 4 h
"""
And the ways
| nodes | highway | railway | bicycle |
| ab | primary | | |
| cd | primary | | |
| ef | primary | | |
| gh | primary | | |
| bc | | train | |
| de | | train | yes |
| fg | | train | no |
When I route I should get
| from | to | route |
| 1 | 2 | |
| 2 | 3 | cd,de,ef,ef |
| 3 | 4 | |
Scenario: Bike - Bringing bikes on trains, invalid railway tag is accepted if access specified
Given the node map
"""
a 1 b c 2 d e 3 f g 4 h
"""
And the ways
| nodes | highway | railway | bicycle |
| ab | primary | | |
| cd | primary | | |
| ef | primary | | |
| gh | primary | | |
| bc | | invalid_tag | |
| de | | invalid_tag | yes |
| fg | | invalid_tag | no |
When I route I should get
| from | to | route |
| 1 | 2 | |
| 2 | 3 | cd,de,ef|
| 3 | 4 | |
@construction
Scenario: Bike - Don't route on railways under construction
Then routability should be
| highway | railway | bicycle | bothw |
| primary | | | cycling |
| (nil) | construction | yes | |
Given the node map
"""
a 1 b c 2 d
"""
And the ways
| nodes | highway | railway | bicycle |
| ab | primary | | |
| cd | primary | | |
| bc | | construction | yes |
When I route I should get
| from | to | route |
| 1 | 2 | |
+20 -20
View File
@@ -183,9 +183,9 @@ Feature: Car - Restricted access
Scenario: Car - designated HOV ways are rated low
Then routability should be
| highway | hov | bothw | forw_rate | backw_rate |
| primary | designated | x | 18 | 18 |
| primary | yes | x | 18 | 18 |
| primary | no | x | 18 | 18 |
| primary | designated | x | 18.2 | 18.2 |
| primary | yes | x | 18.2 | 18.2 |
| primary | no | x | 18.2 | 18.2 |
# Models:
# https://www.openstreetmap.org/way/124891268
@@ -201,24 +201,24 @@ Feature: Car - Restricted access
Scenario: Car - a way with all lanes HOV-designated is highly penalized by default (similar to hov=designated)
Then routability should be
| highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | forw_rate | backw_rate |
| primary | designated | designated | | | x | x | 18 | 18 |
| primary | designated | designated | | | x | x | 18.2 | 18.2 |
# This test is flaky because non-deterministic turn generation sometimes emits a NoTurn here that is marked as restricted. #3769
#| primary | | designated | | | x | x | 18 | 18 |
#| primary | designated | | | | x | x | 18 | 18 |
| primary | designated\|designated | designated\|designated | | | x | x | 18 | 18 |
| primary | designated\|no | designated\|no | | | x | x | 18 | 18 |
| primary | yes\|no | yes\|no | | | x | x | 18 | 18 |
| primary | | | | | x | x | 18 | 18 |
| primary | designated | | | -1 | | x | | 18 |
| primary | | designated | | -1 | | x | | 18 |
| primary | | | designated | yes | x | | 18 | |
| primary | | | designated | -1 | | x | | 18 |
| primary | | | designated\| | yes | x | | 18 | |
| primary | | | designated\| | -1 | | x | | 18 |
| primary | | | designated\|designated | yes | x | | 18 | |
| primary | | | designated\|designated | -1 | | x | | 18 |
| primary | | | designated\|yes | yes | x | | 18 | |
| primary | | | designated\|no | -1 | | x | | 18 |
#| primary | | designated | | | x | x | 18.2 | 18.2 |
#| primary | designated | | | | x | x | 18.2 | 18.2 |
| primary | designated\|designated | designated\|designated | | | x | x | 18.2 | 18.2 |
| primary | designated\|no | designated\|no | | | x | x | 18.2 | 18.2 |
| primary | yes\|no | yes\|no | | | x | x | 18.2 | 18.2 |
| primary | | | | | x | x | 18.2 | 18.2 |
| primary | designated | | | -1 | | x | | 18.2 |
| primary | | designated | | -1 | | x | | 18.2 |
| primary | | | designated | yes | x | | 18.2 | |
| primary | | | designated | -1 | | x | | 18.2 |
| primary | | | designated\| | yes | x | | 18.2 | |
| primary | | | designated\| | -1 | | x | | 18.2 |
| primary | | | designated\|designated | yes | x | | 18.2 | |
| primary | | | designated\|designated | -1 | | x | | 18.2 |
| primary | | | designated\|yes | yes | x | | 18.2 | |
| primary | | | designated\|no | -1 | | x | | 18.2 |
Scenario: Car - these toll roads always work
Then routability should be
+127
View File
@@ -0,0 +1,127 @@
@routing @car @mode
Feature: Car - Mode flag
Background:
Given the profile "car"
Scenario: Car - We tag ferries with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | route |
| ab | primary | |
| bc | | ferry |
| cd | primary | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,bc,cd,cd | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
| d | a | cd,bc,ab,ab | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
| c | a | bc,ab,ab | depart,notification left,arrive | [(ferry)],[()],[()] |
| d | b | cd,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
| a | c | ab,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
| b | d | bc,cd,cd | depart,notification left,arrive | [(ferry)],[()],[()] |
Scenario: Car - We tag motorways with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | motorway|
| cd | primary |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,cd | depart,arrive | [(),(motorway),()],[()] |
| a | c | ab,bc | depart,arrive | [(),(motorway)],[()] |
| b | d | bc,cd | depart,arrive | [(motorway),()],[()] |
Scenario: Car - We tag motorway_link with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | motorway_link |
| cd | primary |
When I route I should get
| from | to | route | turns | classes | # |
| a | d | ab,bc,cd | depart,on ramp right,arrive | [()],[(motorway),()],[()] | on-ramp at class change |
| a | c | ab,bc,bc | depart,on ramp right,arrive | [()],[(motorway)],[()] | " " |
| b | d | bc,cd | depart,arrive | [(motorway),()],[()] | no announcement |
Scenario: Car - We tag restricted with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | access |
| ab | primary | private |
| bc | motorway| private |
| cd | primary | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,cd | depart,arrive| [(restricted),(motorway,restricted),()],[()] |
Scenario: Car - We toll restricted with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | toll |
| ab | primary | yes |
| bc | motorway| yes |
| cd | primary | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,cd | depart,arrive | [(toll),(motorway,toll),()],[()] |
Scenario: Car - From roundabout on toll road
Given the node map
"""
c
/ \
a---b d---f
\ /
e
|
g
"""
And the ways
| nodes | oneway | highway | junction | toll |
| ab | yes | primary | | |
| cb | yes | primary | roundabout | |
| dc | yes | primary | roundabout | |
| be | yes | primary | roundabout | |
| ed | yes | motorway| roundabout | |
| eg | yes | primary | | |
| df | yes | motorway| | yes |
When I route I should get
| from | to | route | turns | classes |
| a | f | ab,df,df | depart,roundabout-exit-2,arrive | [()],[(),(motorway),(toll,motorway)],[()] |
+17
View File
@@ -0,0 +1,17 @@
@routing @car @construction
Feature: Car - all construction tags the OpenStreetMap community could think of and then some
Background:
Given the profile "car"
Scenario: Various ways to tag construction and proposed roads
Then routability should be
| highway | construction | proposed | bothw |
| primary | | | x |
| construction | | | |
| proposed | | | |
| primary | yes | | |
| primary | | yes | |
| primary | no | | x |
| primary | widening | | x |
| primary | minor | | x |
+32 -32
View File
@@ -88,18 +88,18 @@ OSRM will use 4/5 of the projected free-flow speed.
| highway | maxspeed | width | maxspeed:forward | maxspeed:backward | forw | backw | forw_rate | backw_rate |
| primary | | | | | 64 km/h | 64 km/h | 18 | 18 |
| primary | | 3 | | | 64 km/h | 64 km/h | 9 | 9 |
| primary | 60 | | | | 47 km/h | 47 km/h | 13 | 13 |
| primary | 60 | 3 | | | 47 km/h | 47 km/h | 7 | 7 |
| primary | | | 60 | | 47 km/h | 64 km/h | 13 | 18 |
| primary | | 3 | 60 | | 47 km/h | 64 km/h | 7 | 9 |
| primary | | | | 60 | 64 km/h | 47 km/h | 18 | 13 |
| primary | | 3 | | 60 | 64 km/h | 47 km/h | 9 | 7 |
| primary | 15 | | 60 | | 47 km/h | 11 km/h | 13 | 3 |
| primary | 15 | 3 | 60 | | 48 km/h | 12 km/h | 7 | 2 |
| primary | 15 | | | 60 | 12 km/h | 47 km/h | 3 | 13 |
| primary | 15 | 3 | | 60 | 12 km/h | 47 km/h | 2 | 7 |
| primary | 15 | | 30 | 60 | 23 km/h | 47 km/h | 7 | 13 |
| primary | 15 | 3 | 30 | 60 | 23 km/h | 47 km/h | 3 | 7 |
| primary | 60 | | | | 47 km/h | 47 km/h | 13.3 | 13.3 |
| primary | 60 | 3 | | | 47 km/h | 47 km/h | 6.7 | 6.7 |
| primary | | | 60 | | 47 km/h | 64 km/h | 13.3 | 18 |
| primary | | 3 | 60 | | 47 km/h | 64 km/h | 6.7 | 9 |
| primary | | | | 60 | 64 km/h | 47 km/h | 18 | 13.3 |
| primary | | 3 | | 60 | 64 km/h | 47 km/h | 9 | 6.7 |
| primary | 15 | | 60 | | 47 km/h | 11 km/h | 13.3 | 3.3 |
| primary | 15 | 3 | 60 | | 48 km/h | 12 km/h | 6.7 | 1.7 |
| primary | 15 | | | 60 | 12 km/h | 47 km/h | 3.3 | 13.3 |
| primary | 15 | 3 | | 60 | 12 km/h | 47 km/h | 1.7 | 6.7 |
| primary | 15 | | 30 | 60 | 23 km/h | 47 km/h | 6.7 | 13.3 |
| primary | 15 | 3 | 30 | 60 | 23 km/h | 47 km/h | 3.3 | 6.7 |
Scenario: Car - Single lane streets be ignored or incur a penalty
Then routability should be
@@ -107,33 +107,33 @@ OSRM will use 4/5 of the projected free-flow speed.
| highway | maxspeed | lanes | maxspeed:forward | maxspeed:backward | forw | backw | forw_rate | backw_rate |
| primary | | | | | 64 km/h | 64 km/h | 18 | 18 |
| primary | | 1 | | | 64 km/h | 64 km/h | 9 | 9 |
| primary | 60 | | | | 47 km/h | 47 km/h | 13 | 13 |
| primary | 60 | 1 | | | 47 km/h | 47 km/h | 7 | 7 |
| primary | | | 60 | | 47 km/h | 64 km/h | 13 | 18 |
| primary | | 1 | 60 | | 47 km/h | 64 km/h | 7 | 9 |
| primary | | | | 60 | 64 km/h | 47 km/h | 18 | 13 |
| primary | | 1 | | 60 | 64 km/h | 47 km/h | 9 | 7 |
| primary | 15 | | 60 | | 47 km/h | 11 km/h | 13 | 3 |
| primary | 15 | 1 | 60 | | 48 km/h | 12 km/h | 7 | 2 |
| primary | 15 | | | 60 | 12 km/h | 47 km/h | 3 | 13 |
| primary | 15 | 1 | | 60 | 12 km/h | 47 km/h | 2 | 7 |
| primary | 15 | | 30 | 60 | 23 km/h | 47 km/h | 7 | 13 |
| primary | 15 | 1 | 30 | 60 | 23 km/h | 47 km/h | 3 | 7 |
| primary | 60 | | | | 47 km/h | 47 km/h | 13.3 | 13.3 |
| primary | 60 | 1 | | | 47 km/h | 47 km/h | 6.7 | 6.7 |
| primary | | | 60 | | 47 km/h | 64 km/h | 13.3 | 18 |
| primary | | 1 | 60 | | 47 km/h | 64 km/h | 6.7 | 9 |
| primary | | | | 60 | 64 km/h | 47 km/h | 18 | 13.3 |
| primary | | 1 | | 60 | 64 km/h | 47 km/h | 9 | 6.7 |
| primary | 15 | | 60 | | 47 km/h | 11 km/h | 13.3 | 3.3 |
| primary | 15 | 1 | 60 | | 48 km/h | 12 km/h | 6.7 | 1.7 |
| primary | 15 | | | 60 | 12 km/h | 47 km/h | 3.3 | 13.3 |
| primary | 15 | 1 | | 60 | 12 km/h | 47 km/h | 1.7 | 6.7 |
| primary | 15 | | 30 | 60 | 23 km/h | 47 km/h | 6.7 | 13.3 |
| primary | 15 | 1 | 30 | 60 | 23 km/h | 47 km/h | 3.3 | 6.7 |
Scenario: Car - Single lane streets only incur a penalty for two-way streets
Then routability should be
| highway | maxspeed | lanes | oneway | forw | backw | forw_rate | backw_rate |
| primary | 30 | 1 | yes | 23 km/h | | 7 | |
| primary | 30 | 1 | -1 | | 23 km/h | | 7 |
| primary | 30 | 1 | | 23 km/h | 23 km/h | 3 | 3 |
| primary | 30 | 2 | | 23 km/h | 23 km/h | 7 | 7 |
| primary | 30 | 1 | yes | 23 km/h | | 6.7 | |
| primary | 30 | 1 | -1 | | 23 km/h | | 6.7 |
| primary | 30 | 1 | | 23 km/h | 23 km/h | 3.3 | 3.3 |
| primary | 30 | 2 | | 23 km/h | 23 km/h | 6.7 | 6.7 |
Scenario: Car - Forward/backward maxspeed on reverse oneways
Then routability should be
| highway | maxspeed | maxspeed:forward | maxspeed:backward | oneway | forw | backw | forw_rate | backw_rate |
| primary | | | | -1 | | 64 km/h | | 18 |
| primary | 30 | | | -1 | | 23 km/h | | 7 |
| primary | 30 | | | -1 | | 23 km/h | | 6.7 |
| primary | | 30 | | -1 | | 64 km/h | | 18 |
| primary | | | 30 | -1 | | 23 km/h | | 7 |
| primary | 20 | 30 | | -1 | | 15 km/h | | 4 |
| primary | 20 | | 30 | -1 | | 23 km/h | | 7 |
| primary | | | 30 | -1 | | 23 km/h | | 6.7 |
| primary | 20 | 30 | | -1 | | 15 km/h | | 4.4 |
| primary | 20 | | 30 | -1 | | 23 km/h | | 6.7 |
+4 -4
View File
@@ -7,8 +7,8 @@ Feature: Car - Surfaces
Scenario: Car - Ways tagged service should reduce speed
Then routability should be
| highway | service | forw | backw | forw_rate |
| service | alley | 15 km/h +-1 | 15 km/h +-1 | 2 |
| service | alley | 15 km/h +-1 | 15 km/h +-1 | 2.1 |
| service | emergency_access | | | |
| service | driveway | 15 km/h +-1 | 15 km/h +-1 | 2 |
| service | drive-through | 15 km/h +-1 | 15 km/h +-1 | 2 |
| service | parking | 15 km/h +-1 | 15 km/h +-1 | 2 |
| service | driveway | 15 km/h +-1 | 15 km/h +-1 | 2.1 |
| service | drive-through | 15 km/h +-1 | 15 km/h +-1 | 2.1 |
| service | parking | 15 km/h +-1 | 15 km/h +-1 | 2.1 |
+1 -1
View File
@@ -50,4 +50,4 @@ Feature: Car - speeds
Then routability should be
| highway | side_road | forw | backw | forw_rate | backw_rate |
| primary | yes | 64 km/h | 64 km/h | 14 | 14 |
| primary | yes | 64 km/h | 64 km/h | 14.4 | 14.4 |
+37
View File
@@ -0,0 +1,37 @@
@routing @car @startpoint
Feature: Car - Allowed start/end modes
Background:
Given the profile "car"
Scenario: Car - Don't start/stop on ferries
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway | route | bicycle |
| ab | primary | | |
| bc | | ferry | yes |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,ab | driving,driving |
| 2 | 1 | ab,ab | driving,driving |
Scenario: Car - Don't start/stop on trains
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway | railway | bicycle |
| ab | primary | | |
| bc | | train | yes |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,ab | driving,driving |
| 2 | 1 | ab,ab | driving,driving |
+37
View File
@@ -0,0 +1,37 @@
@routing @foot @startpoint
Feature: Foot - Allowed start/end modes
Background:
Given the profile "foot"
Scenario: Foot - Don't start/stop on ferries
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway | route | bicycle |
| ab | primary | | |
| bc | | ferry | yes |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,ab | walking,walking |
| 2 | 1 | ab,ab | walking,walking |
Scenario: Foot - Don't start/stop on trains
Given the node map
"""
a 1 b 2 c
"""
And the ways
| nodes | highway | railway | bicycle |
| ab | primary | | |
| bc | | train | yes |
When I route I should get
| from | to | route | modes |
| 1 | 2 | ab,ab | walking,walking |
| 2 | 1 | ab,ab | walking,walking |
@@ -0,0 +1,98 @@
@routing @guidance
Feature: Exit Numbers and Names
Background:
Given the profile "car"
Given a grid size of 10 meters
Scenario: Exit number on the way after the motorway junction
Given the node map
"""
a . . b . c . . d
` e . . f
"""
And the nodes
| node | highway |
| b | motorway_junction |
And the ways
| nodes | highway | name | junction:ref |
| abcd | motorway | MainRoad | |
| be | motorway_link | ExitRamp | 3 |
| ef | motorway_link | ExitRamp | |
When I route I should get
| waypoints | route | turns | exits |
| a,f | MainRoad,ExitRamp,ExitRamp | depart,off ramp slight right,arrive | ,3, |
Scenario: Exit number on the way, motorway junction node tag missing, multiple numbers
Given the node map
"""
a . . b . c . . d
` e . . f
"""
And the ways
| nodes | highway | name | junction:ref |
| abcd | motorway | MainRoad | |
| be | motorway_link | ExitRamp | 10;12 |
| ef | motorway_link | ExitRamp | |
When I route I should get
| waypoints | route | turns | exits |
| a,f | MainRoad,ExitRamp,ExitRamp | depart,off ramp slight right,arrive | ,10; 12, |
Scenario: Exit number on the ways after the motorway junction, multiple exits
Given the node map
"""
a . . b . c . . d
` e . . f
` g . . h
"""
And the nodes
| node | highway |
| b | motorway_junction |
And the ways
| nodes | highway | name | junction:ref |
| abcd | motorway | MainRoad | |
| be | motorway_link | ExitRamp | 3 |
| ef | motorway_link | ExitRamp | |
| bg | motorway_link | ExitRamp | 3 |
| gh | motorway_link | ExitRamp | |
When I route I should get
| waypoints | route | turns | exits |
| a,f | MainRoad,ExitRamp,ExitRamp | depart,off ramp slight right,arrive | ,3, |
| a,h | MainRoad,ExitRamp,ExitRamp | depart,off ramp right,arrive | ,3, |
# http://www.openstreetmap.org/way/417524818#map=17/37.38663/-121.97972
Scenario: Exit 393 on Bayshore Freeway
Given the node map
"""
a
` b
` c
. ` d
f ` e
"""
And the nodes
| node | highway |
| c | motorway_junction |
And the ways
| nodes | highway | name | junction:ref | oneway | destination |
| abcde | motorway | Bayshore Freeway | | yes | |
| cf | motorway_link | | 393 | yes | Great America Parkway;Bowers Avenue |
When I route I should get
| waypoints | route | turns | exits | destinations |
| a,e | Bayshore Freeway,Bayshore Freeway | depart,arrive | , | , |
| a,f | Bayshore Freeway,, | depart,off ramp slight right,arrive | ,393,393 | ,Great America Parkway, Bowers Avenue,Great America Parkway, Bowers Avenue |
+20
View File
@@ -261,3 +261,23 @@ Feature: Motorway Guidance
When I route I should get
| waypoints | route | turns |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive |
#http://0.0.0.0:9966/?z=18&center=38.893323%2C-77.055117&loc=38.893551%2C-77.054833&loc=38.893112%2C-77.055536&hl=en&alt=0
Scenario: Merging with same name
Given the node map
"""
a - - -
> c - d
b
"""
And the ways
| nodes | name | ref | highway | oneway |
| ac | | US 50 | motorway | yes |
| bc | | I 66 | motorway | yes |
| cd | | US 50; I 66 | motorway | yes |
When I route I should get
| waypoints | route | turns |
| a,d | , | depart,arrive |
| b,d | , | depart,arrive |
+73
View File
@@ -1371,3 +1371,76 @@ Feature: Simple Turns
When I route I should get
| waypoints | route |
| g,e | abcde,abcde |
# 4205
# https://www.openstreetmap.org/node/36153635#map=19/51.97548/7.61795
Scenario: merging onto a through street
Given the node map
"""
e
`
`
`
`
d
c
a - - - - - - - b``
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
f
"""
And the ways
| nodes | oneway | name |
| abc | yes | fww |
| fcde | no | jahn |
When I route I should get
| waypoints | route | turns |
| a,f | fww,jahn,jahn | depart,turn right,arrive |
| a,e | fww,jahn,jahn | depart,turn left,arrive |
@@ -1,5 +1,4 @@
# Broken see issue #4065
@contract @options @edge-weight-updates-over-factor @todo
@contract @options @edge-weight-updates-over-factor
Feature: osrm-contract command line option: edge-weight-updates-over-factor
Background: Log edge weight updates over given factor
@@ -22,6 +21,7 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
Scenario: Logging weight with updates over factor of 2, long segment
When I run "osrm-extract --profile {profile_file} {osm_file}"
And the data has been partitioned
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
Then stderr should not contain "Speed values were used to update 2 segment(s)"
And stderr should contain "Segment: 1,2"
+2 -2
View File
@@ -34,7 +34,7 @@ module.exports = function () {
outputRow[rate] = result[direction].status ?
result[direction].status.toString() : '';
break;
case /^\d+$/.test(want):
case /^\d+(\.\d+){0,1}$/.test(want):
if (result[direction].rate !== undefined && !isNaN(result[direction].rate)) {
outputRow[rate] = result[direction].rate.toString();
} else {
@@ -135,7 +135,7 @@ module.exports = function () {
if (r.route.split(',')[0] === util.format('w%d', i)) {
r.time = r.json.routes[0].duration;
r.distance = r.json.routes[0].distance;
r.rate = Math.round(r.distance / r.json.routes[0].weight);
r.rate = Math.round(r.distance / r.json.routes[0].weight * 10) / 10.;
r.speed = r.time > 0 ? parseInt(3.6 * r.distance / r.time) : null;
// use the mode of the first step of the route
+1 -4
View File
@@ -85,8 +85,7 @@ module.exports = function () {
}
var ok = true,
encodedResult = '',
extendedTarget = '';
encodedResult = '';
if (json.trips) row.trips.split(',').forEach((sub, si) => {
if (si >= subTrips.length) {
@@ -98,11 +97,9 @@ module.exports = function () {
outNode = subTrips[si][ni];
if (this.FuzzyMatch.matchLocation(outNode, node)) {
encodedResult += sub[ni];
extendedTarget += sub[ni];
} else {
ok = false;
encodedResult += util.format('? [%s,%s]', outNode[0], outNode[1]);
extendedTarget += util.format('%s [%d,%d]', sub[ni], node.lat, node.lon);
}
}
}
+3 -3
View File
@@ -238,9 +238,9 @@ module.exports = function () {
// a shallow copy of scenario parameters to avoid data inconsistency
// if a cucumber timeout occurs during deferred jobs
let p = {extractArgs: this.extractArgs, contractArgs: this.contractArgs,
partitionArgs: this.partitionArgs, customizeArgs: this.customizeArgs,
profileFile: this.profileFile, inputCacheFile: this.inputCacheFile,
processedCacheFile: this.processedCacheFile, environment: this.environment};
partitionArgs: this.partitionArgs, customizeArgs: this.customizeArgs,
profileFile: this.profileFile, inputCacheFile: this.inputCacheFile,
processedCacheFile: this.processedCacheFile, environment: this.environment};
let queue = d3.queue(1);
queue.defer(this.extractData.bind(this), p);
queue.defer(this.partitionData.bind(this), p);
+8
View File
@@ -155,6 +155,10 @@ module.exports = function () {
return this.extractInstructionList(instructions, s => s.destinations || '');
};
this.exitsList = (instructions) => {
return this.extractInstructionList(instructions, s => s.exits || '');
};
this.reverseBearing = (bearing) => {
if (bearing >= 180)
return bearing - 180.;
@@ -256,6 +260,10 @@ module.exports = function () {
return this.extractInstructionList(instructions, s => s.mode);
};
this.classesList = (instructions) => {
return this.extractInstructionList(instructions, s => '[' + s.intersections.map(i => '(' + (i.classes ? i.classes.join(',') : '') + ')').join(',') + ']');
};
this.timeList = (instructions) => {
return this.extractInstructionList(instructions, s => s.duration + 's');
};
+6 -2
View File
@@ -34,7 +34,7 @@ module.exports = function () {
var afterRequest = (err, res, body) => {
if (err) return cb(err);
if (body && body.length) {
let destinations, pronunciations, instructions, refs, bearings, turns, modes, times,
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
let json = JSON.parse(body);
@@ -48,10 +48,12 @@ module.exports = function () {
pronunciations = this.pronunciationList(json.routes[0]);
refs = this.refList(json.routes[0]);
destinations = this.destinationsList(json.routes[0]);
exits = this.exitsList(json.routes[0]);
bearings = this.bearingList(json.routes[0]);
turns = this.turnList(json.routes[0]);
intersections = this.intersectionList(json.routes[0]);
modes = this.modeList(json.routes[0]);
classes = this.classesList(json.routes[0]);
times = this.timeList(json.routes[0]);
distances = this.distanceList(json.routes[0]);
lanes = this.lanesList(json.routes[0]);
@@ -173,10 +175,12 @@ module.exports = function () {
putValue('bearing', bearings);
putValue('turns', turns);
putValue('modes', modes);
putValue('classes', classes);
putValue('times', times);
putValue('distances', distances);
putValue('pronunciations', pronunciations);
putValue('destinations', destinations);
putValue('exits', exits);
putValue('weight_name', weight_name);
putValue('weights', weights);
putValue('weight', weight);
@@ -243,7 +247,7 @@ module.exports = function () {
} else if (row.waypoints) {
row.waypoints.split(',').forEach((n) => {
var node = this.findNodeByName(n.trim());
if (!node) return cb(new Error('*** unknown waypoint node "%s"', n.trim()));
if (!node) return cb(new Error(util.format('*** unknown waypoint node "%s"', n.trim())));
waypoints.push(node);
});
got.waypoints = row.waypoints;
@@ -1,8 +1,8 @@
@routing @approach
@routing @approach @testbot
Feature: Approach parameter
Background:
Given the profile "car"
Given the profile "testbot"
And a grid size of 10 meters
Scenario: Start End same approach, option unrestricted for Start and End
+26 -4
View File
@@ -358,8 +358,8 @@ Feature: Basic Map Matching
| trace | matchings | alternatives |
| abcdef | abcde | 0,0,0,0,1,1 |
Scenario: Testbot - Speed greater than speed threshhold
Given a grid size of 10 meters
Scenario: Testbot - Speed greater than speed threshold
Given a grid size of 100 meters
Given the query options
| geometries | geojson |
@@ -379,8 +379,8 @@ Feature: Basic Map Matching
| trace | timestamps | matchings |
| abcd | 0 1 2 3 | ab,cd |
Scenario: Testbot - Speed less than speed threshhold
Given a grid size of 10 meters
Scenario: Testbot - Speed less than speed threshold
Given a grid size of 100 meters
Given the query options
| geometries | geojson |
@@ -397,6 +397,28 @@ Feature: Basic Map Matching
| trace | timestamps | matchings |
| abcd | 0 1 2 3 | abcd |
Scenario: Testbot - Huge gap in the coordinates
Given a grid size of 100 meters
Given the query options
| geometries | geojson |
| gaps | ignore |
Given the node map
"""
a b c d ---- x
|
|
y ---- z ---- efjk
"""
And the ways
| nodes | oneway |
| abcdxyzefjk | no |
When I match I should get
| trace | timestamps | matchings |
| abcdefjk | 0 1 2 3 50 51 52 53 | abcdefjk |
# Regression test 1 for issue 3176
Scenario: Testbot - multiple segments: properly expose OSM IDs
Given the query options
+65 -5
View File
@@ -48,21 +48,40 @@ Feature: Multi level routing
lkpo
"""
And the nodes
| node | highway |
| i | traffic_signals |
| n | traffic_signals |
And the ways
| nodes | highway |
| abcda | primary |
| efghe | primary |
| ijkli | primary |
| nmop | primary |
| mnopm | primary |
| cm | primary |
| hj | primary |
| kp | primary |
When I route I should get
| from | to | route | time |
| a | b | abcda,abcda | 20s |
| a | f | abcda,cm,nmop,kp,ijkli,hj,efghe,efghe | 257.7s |
| c | m | cm,cm | 44.7s |
| from | to | route | time |
| a | b | abcda,abcda | 20s |
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 229.4s |
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 144.7s |
| a | o | abcda,cm,mnopm,mnopm,mnopm | 124.7s |
| f | l | efghe,hj,ijkli,ijkli,ijkli | 124.7s |
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 144.7s |
| l | o | ijkli,kp,mnopm,mnopm | 60s |
| c | m | cm,cm | 44.7s |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| f | 229.4 | 0 | 124.7 | 144.7 |
| l | 144.7 | 124.7 | 0 | 60 |
| o | 124.7 | 144.7 | 60 | 0 |
Scenario: Testbot - Multi level routing: horizontal road
Given the node map
@@ -127,3 +146,44 @@ Feature: Multi level routing
When I route I should get
| from | to | route | time |
| a | k | abcda,ch,hf,fi,ijkli,ijkli | 724.3s |
Scenario: Testbot - Edge case for matrix plugin with
Given the node map
"""
ab
dc
e f
h gi
"""
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 5,16,64"
And the nodes
| node | highway |
| e | traffic_signals |
| g | traffic_signals |
And the ways
| nodes | highway | maxspeed |
| abcda | primary | |
| ac | primary | |
| db | primary | |
| deh | primary | |
| cfg | primary | |
| ef | primary | 1 |
| eg | primary | 1 |
| hf | primary | 1 |
| hg | primary | 1 |
| gi | primary | |
When I route I should get
| from | to | route | time |
| h | i | deh,abcda,cfg,gi,gi | 134s |
When I request a travel time matrix I should get
| | h | i |
| h | 0 | 134 |
| i | 134 | 0 |
+1
View File
@@ -14,6 +14,7 @@ Feature: Testbot - Check assigning nil values
result.name = nil
result.ref = nil
result.destinations = nil
result.exits = nil
result.pronunciation = nil
result.turn_lanes_forward = nil
result.turn_lanes_backward = nil
-7
View File
@@ -65,16 +65,9 @@ class Contractor
std::vector<EdgeWeight> &&node_weights,
std::vector<bool> &is_core_node,
std::vector<float> &inout_node_levels) const;
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
void WriteContractedGraph(unsigned number_of_edge_based_nodes,
util::DeallocatingVector<QueryEdge> contracted_edge_list);
private:
ContractorConfig config;
EdgeID LoadEdgeExpandedGraph(const ContractorConfig &config,
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights);
};
}
}
+21
View File
@@ -14,6 +14,27 @@ namespace contractor
{
namespace files
{
// reads .osrm.core
template <typename CoreVectorT>
void readCoreMarker(const boost::filesystem::path &path, CoreVectorT &is_core_node)
{
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
"is_core_node must be a vector");
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
storage::serialization::read(reader, is_core_node);
}
// writes .osrm.core
template <typename CoreVectorT>
void writeCoreMarker(const boost::filesystem::path &path, const CoreVectorT &is_core_node)
{
static_assert(util::is_view_or_vector<bool, CoreVectorT>::value,
"is_core_node must be a vector");
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
storage::serialization::write(writer, is_core_node);
}
// reads .osrm.hsgr file
template <typename QueryGraphT>
+25 -8
View File
@@ -14,8 +14,6 @@
#include <boost/assert.hpp>
#include <stxxl/vector>
#include <tbb/enumerable_thread_specific.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_sort.h>
@@ -25,6 +23,10 @@
#include <memory>
#include <vector>
#if USE_STXXL_LIBRARY
#include <stxxl/vector>
#endif
namespace osrm
{
namespace contractor
@@ -33,6 +35,12 @@ namespace contractor
class GraphContractor
{
private:
#if USE_STXXL_LIBRARY
template <typename T> using ExternalVector = stxxl::vector<T>;
#else
template <typename T> using ExternalVector = std::vector<T>;
#endif
struct ContractorThreadData
{
ContractorDijkstra dijkstra;
@@ -91,8 +99,8 @@ class GraphContractor
GraphContractor(int nodes,
std::vector<ContractorEdge> edges,
std::vector<float> &&node_levels_,
std::vector<EdgeWeight> &&node_weights_);
std::vector<float> node_levels_,
std::vector<EdgeWeight> node_weights_);
/* Flush all data from the contraction to disc and reorder stuff for better locality */
void FlushDataAndRebuildContractorGraph(ThreadDataContainer &thread_data_list,
@@ -101,12 +109,14 @@ class GraphContractor
void Run(double core_factor = 1.0);
void GetCoreMarker(std::vector<bool> &out_is_core_node);
std::vector<bool> GetCoreMarker();
void GetNodeLevels(std::vector<float> &out_node_levels);
std::vector<float> GetNodeLevels();
template <class Edge> inline void GetEdges(util::DeallocatingVector<Edge> &edges)
template <class Edge> inline util::DeallocatingVector<Edge> GetEdges()
{
util::DeallocatingVector<Edge> edges;
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
util::Percent p(log, contractor_graph->GetNumberOfNodes());
@@ -161,6 +171,13 @@ class GraphContractor
edges.append(external_edge_list.begin(), external_edge_list.end());
external_edge_list.clear();
// sort and remove duplicates
tbb::parallel_sort(edges.begin(), edges.end());
auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin());
return edges;
}
private:
@@ -392,7 +409,7 @@ class GraphContractor
bool Bias(const NodeID a, const NodeID b) const;
std::shared_ptr<ContractorGraph> contractor_graph;
stxxl::vector<QueryEdge> external_edge_list;
ExternalVector<QueryEdge> external_edge_list;
std::vector<NodeID> orig_node_id_from_new_node_id_map;
std::vector<float> node_levels;
+30 -16
View File
@@ -20,6 +20,7 @@ class CellCustomizer
struct HeapData
{
bool from_clique;
EdgeDuration duration;
};
public:
@@ -41,31 +42,41 @@ class CellCustomizer
{
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
heap.Clear();
heap.Insert(source, 0, {false});
heap.Insert(source, 0, {false, 0});
// explore search space
while (!heap.Empty() && !destinations_set.empty())
{
const NodeID node = heap.DeleteMin();
const EdgeWeight weight = heap.GetKey(node);
const EdgeDuration duration = heap.GetData(node).duration;
if (level == 1)
RelaxNode<true>(graph, cells, heap, level, node, weight);
RelaxNode<true>(graph, cells, heap, level, node, weight, duration);
else
RelaxNode<false>(graph, cells, heap, level, node, weight);
RelaxNode<false>(graph, cells, heap, level, node, weight, duration);
destinations_set.erase(node);
}
// fill a map of destination nodes to placeholder pointers
auto destination_iter = destinations.begin();
for (auto &weight : cell.GetOutWeight(source))
auto weights = cell.GetOutWeight(source);
auto durations = cell.GetOutDuration(source);
for (auto &destination : destinations)
{
BOOST_ASSERT(destination_iter != destinations.end());
const auto destination = *destination_iter++;
weight =
heap.WasInserted(destination) ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
BOOST_ASSERT(!weights.empty());
BOOST_ASSERT(!durations.empty());
const bool inserted = heap.WasInserted(destination);
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
durations.front() =
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
weights.advance_begin(1);
durations.advance_begin(1);
}
BOOST_ASSERT(weights.empty());
BOOST_ASSERT(durations.empty());
}
}
@@ -94,7 +105,8 @@ class CellCustomizer
Heap &heap,
LevelID level,
NodeID node,
EdgeWeight weight) const
EdgeWeight weight,
EdgeDuration duration) const
{
BOOST_ASSERT(heap.WasInserted(node));
@@ -113,24 +125,26 @@ class CellCustomizer
auto subcell_id = partition.GetCell(level - 1, node);
auto subcell = cells.GetCell(level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin();
auto subcell_duration = subcell.GetOutDuration(node).begin();
for (auto subcell_weight : subcell.GetOutWeight(node))
{
if (subcell_weight != INVALID_EDGE_WEIGHT)
{
const NodeID to = *subcell_destination;
const EdgeWeight to_weight = subcell_weight + weight;
const EdgeWeight to_weight = weight + subcell_weight;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true});
heap.Insert(to, to_weight, {true, duration + *subcell_duration});
}
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to).from_clique = true;
heap.GetData(to) = {true, duration + *subcell_duration};
}
}
++subcell_destination;
++subcell_duration;
}
}
}
@@ -144,15 +158,15 @@ class CellCustomizer
(first_level ||
partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
{
const EdgeWeight to_weight = data.weight + weight;
const EdgeWeight to_weight = weight + data.weight;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {false});
heap.Insert(to, to_weight, {false, duration + data.duration});
}
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to).from_clique = false;
heap.GetData(to) = {false, duration + data.duration};
}
}
}
+6
View File
@@ -93,6 +93,9 @@ template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
};
// Algorithms supported by Multi-Level Dijkstra
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
{
};
@@ -102,6 +105,9 @@ template <> struct HasShortestPathSearch<mld::Algorithm> final : std::true_type
template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
{
};
+13 -4
View File
@@ -89,8 +89,9 @@ struct RouteParameters : public BaseParameters
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
annotations{false}, annotations_type{AnnotationsType::None}, geometries{geometries_},
overview{overview_}, continue_straight{continue_straight_}
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{false},
annotations_type{AnnotationsType::None}, geometries{geometries_}, overview{overview_},
continue_straight{continue_straight_}
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one below.
{
}
@@ -105,7 +106,7 @@ struct RouteParameters : public BaseParameters
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
annotations{annotations_},
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{annotations_},
annotations_type{annotations_ ? AnnotationsType::All : AnnotationsType::None},
geometries{geometries_}, overview{overview_}, continue_straight{continue_straight_}
{
@@ -121,6 +122,7 @@ struct RouteParameters : public BaseParameters
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u},
annotations{annotations_ == AnnotationsType::None ? false : true},
annotations_type{annotations_}, geometries{geometries_}, overview{overview_},
continue_straight{continue_straight_}
@@ -128,14 +130,21 @@ struct RouteParameters : public BaseParameters
}
bool steps = false;
// TODO: in v6 we should remove the boolean and only keep the number parameter; for compat.
bool alternatives = false;
unsigned number_of_alternatives = 0;
bool annotations = false;
AnnotationsType annotations_type = AnnotationsType::None;
GeometriesType geometries = GeometriesType::Polyline;
OverviewType overview = OverviewType::Simplified;
boost::optional<bool> continue_straight;
bool IsValid() const { return coordinates.size() >= 2 && BaseParameters::IsValid(); }
bool IsValid() const
{
const auto coordinates_ok = coordinates.size() >= 2;
const auto base_params_ok = BaseParameters::IsValid();
return coordinates_ok && base_params_ok;
}
};
inline bool operator&(RouteParameters::AnnotationsType lhs, RouteParameters::AnnotationsType rhs)
-1
View File
@@ -42,7 +42,6 @@ class TableAPI final : public BaseAPI
{
auto number_of_sources = parameters.sources.size();
auto number_of_destinations = parameters.destinations.size();
;
// symmetric case
if (parameters.sources.empty())
@@ -14,6 +14,7 @@
#include "extractor/datasources.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/intersection_bearings_container.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/profile_properties.hpp"
@@ -218,7 +219,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
unsigned m_check_sum;
util::vector_view<util::Coordinate> m_coordinate_list;
extractor::PackedOSMIDsView m_osmnodeid_list;
util::NameTable m_names_table;
util::vector_view<std::uint32_t> m_lane_description_offsets;
util::vector_view<extractor::guidance::TurnLaneType::Mask> m_lane_description_masks;
util::vector_view<TurnPenalty> m_turn_weight_penalties;
@@ -236,19 +236,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
boost::filesystem::path file_index_path;
util::NameTable m_name_table;
// bearing classes by node based node
util::vector_view<BearingClassID> m_bearing_class_id_table;
// entry class IDs
util::vector_view<EntryClassID> m_entry_class_id_list;
extractor::IntersectionBearingsView intersection_bearings_view;
util::NameTable m_name_table;
// the look-up table for entry classes. An entry class lists the possibility of entry for all
// available turns. Such a class id is stored with every edge.
util::vector_view<util::guidance::EntryClass> m_entry_class_table;
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
// at an intersection
std::shared_ptr<util::RangeTable<16, storage::Ownership::View>> m_bearing_ranges_table;
util::vector_view<DiscreteBearing> m_bearing_values_table;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
@@ -325,7 +318,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
char *memory_ptr)
{
auto via_geometry_list_ptr =
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]);
@@ -345,10 +338,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
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(travel_modes),
std::move(classes));
}
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
@@ -502,15 +501,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
memory_block, storage::DataLayout::BEARING_CLASSID);
typename util::vector_view<BearingClassID> bearing_class_id_table(
util::vector_view<BearingClassID> bearing_class_id(
bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]);
m_bearing_class_id_table = std::move(bearing_class_id_table);
auto bearing_class_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
auto bearing_values_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
memory_block, storage::DataLayout::BEARING_VALUES);
typename util::vector_view<DiscreteBearing> bearing_class_table(
bearing_class_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]);
m_bearing_values_table = std::move(bearing_class_table);
util::vector_view<DiscreteBearing> bearing_values(
bearing_values_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]);
auto offsets_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
@@ -521,12 +518,15 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
util::vector_view<IndexBlock> bearing_blocks(
blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]);
m_bearing_ranges_table = std::make_unique<util::RangeTable<16, storage::Ownership::View>>(
bearing_offsets, bearing_blocks, static_cast<unsigned>(m_bearing_values_table.size()));
util::RangeTable<16, storage::Ownership::View> bearing_range_table(
bearing_offsets, bearing_blocks, static_cast<unsigned>(bearing_values.size()));
intersection_bearings_view = extractor::IntersectionBearingsView{
std::move(bearing_values), std::move(bearing_class_id), std::move(bearing_range_table)};
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
memory_block, storage::DataLayout::ENTRY_CLASS);
typename util::vector_view<util::guidance::EntryClass> entry_class_table(
util::vector_view<util::guidance::EntryClass> entry_class_table(
entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]);
m_entry_class_table = std::move(entry_class_table);
}
@@ -789,6 +789,22 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return edge_based_node_data.GetTravelMode(id);
}
extractor::ClassData GetClassData(const NodeID id) const override final
{
return edge_based_node_data.GetClassData(id);
}
std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final
{
auto indexes = extractor::getClassIndexes(class_data);
std::vector<std::string> classes(indexes.size());
std::transform(indexes.begin(), indexes.end(), classes.begin(), [this](const auto index) {
return m_profile_properties->GetClassName(index);
});
return classes;
}
NameID GetNameIndex(const NodeID id) const override final
{
return edge_based_node_data.GetNameID(id);
@@ -814,6 +830,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_name_table.GetDestinationsForID(id);
}
StringView GetExitsForID(const NameID id) const override final
{
return m_name_table.GetExitsForID(id);
}
StringView GetDatasourceName(const DatasourceID id) const override final
{
return m_datasources->GetSourceName(id);
@@ -843,27 +864,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_profile_properties->GetWeightMultiplier();
}
BearingClassID GetBearingClassID(const NodeID id) const override final
util::guidance::BearingClass GetBearingClass(const NodeID node) const override final
{
return m_bearing_class_id_table.at(id);
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const override final
{
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
auto range = m_bearing_ranges_table->GetRange(bearing_class_id);
util::guidance::BearingClass result;
for (auto itr = m_bearing_values_table.begin() + range.front();
itr != m_bearing_values_table.begin() + range.back() + 1;
++itr)
result.add(*itr);
return result;
}
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return turn_data.GetEntryClassID(eid);
return intersection_bearings_view.GetBearingClass(node);
}
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
@@ -875,8 +878,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return turn_data.GetPostTurnBearing(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const override final
{
auto entry_class_id = turn_data.GetEntryClassID(turn_id);
return m_entry_class_table.at(entry_class_id);
}
@@ -987,6 +991,8 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
auto mld_cell_weights_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::MLD_CELL_WEIGHTS);
auto mld_cell_durations_ptr = data_layout.GetBlockPtr<EdgeDuration>(
memory_block, storage::DataLayout::MLD_CELL_DURATIONS);
auto mld_source_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
auto mld_destination_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
@@ -998,6 +1004,8 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
auto weight_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS);
auto duration_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS);
auto source_boundary_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
auto destination_boundary_entries_count =
@@ -1006,7 +1014,11 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
auto cell_level_offsets_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
BOOST_ASSERT(weight_entries_count == duration_entries_count);
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
duration_entries_count);
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
source_boundary_entries_count);
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
@@ -1017,6 +1029,7 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
cell_level_offsets_entries_count);
mld_cell_storage = partition::CellStorageView{std::move(weights),
std::move(durations),
std::move(source_boundary),
std::move(destination_boundary),
std::move(cells),
+16 -10
View File
@@ -3,14 +3,19 @@
// Exposes all data access interfaces to the algorithms via base class ptr
#include "engine/approach.hpp"
#include "engine/phantom_node.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/class_data.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/original_edge_data.hpp"
#include "engine/approach.hpp"
#include "engine/phantom_node.hpp"
#include "extractor/query_node.hpp"
#include "extractor/travel_mode.hpp"
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@@ -87,6 +92,10 @@ class BaseDataFacade
virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0;
virtual extractor::ClassData GetClassData(const NodeID id) const = 0;
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) const = 0;
@@ -158,6 +167,8 @@ class BaseDataFacade
virtual StringView GetDestinationsForID(const NameID id) const = 0;
virtual StringView GetExitsForID(const NameID id) const = 0;
virtual std::string GetTimestamp() const = 0;
virtual bool GetContinueStraightDefault() const = 0;
@@ -170,17 +181,12 @@ class BaseDataFacade
virtual double GetWeightMultiplier() const = 0;
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
virtual util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
virtual util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const = 0;
virtual util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const = 0;
virtual util::guidance::BearingClass GetBearingClass(const NodeID node) const = 0;
virtual EntryClassID GetEntryClassID(const EdgeID eid) const = 0;
virtual util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const = 0;
virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0;
virtual bool IsLeftHandDriving() const = 0;
};
+6 -7
View File
@@ -11,7 +11,6 @@
#include "engine/datafacade/contiguous_block_allocator.hpp"
#include "engine/datafacade_provider.hpp"
#include "engine/engine_config.hpp"
#include "engine/engine_config.hpp"
#include "engine/plugins/match.hpp"
#include "engine/plugins/nearest.hpp"
#include "engine/plugins/table.hpp"
@@ -54,12 +53,12 @@ template <typename Algorithm> class Engine final : public EngineInterface
{
public:
explicit Engine(const EngineConfig &config)
: route_plugin(config.max_locations_viaroute), //
table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), //
match_plugin(config.max_locations_map_matching), //
tile_plugin() //
: 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), //
match_plugin(config.max_locations_map_matching), //
tile_plugin() //
{
if (config.use_shared_memory)
+1
View File
@@ -87,6 +87,7 @@ struct EngineConfig final
int max_locations_distance_table = -1;
int max_locations_map_matching = -1;
int max_results_nearest = -1;
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true;
Algorithm algorithm = Algorithm::CH;
};
+15 -5
View File
@@ -53,6 +53,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
: source_node.forward_segment_id.id;
const auto source_name_id = facade.GetNameIndex(source_node_id);
const auto source_mode = facade.GetTravelMode(source_node_id);
auto source_classes = facade.GetClasses(facade.GetClassData(source_node_id));
const EdgeWeight target_duration =
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
@@ -86,7 +87,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
IntermediateIntersection::NO_INDEX,
0,
util::guidance::LaneTuple(),
{}};
{},
source_classes};
if (leg_data.size() > 0)
{
@@ -114,13 +116,17 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const auto ref = facade.GetRefForID(step_name_id);
const auto pronunciation = facade.GetPronunciationForID(step_name_id);
const auto destinations = facade.GetDestinationsForID(step_name_id);
const auto exits = facade.GetExitsForID(step_name_id);
const auto distance = leg_geometry.segment_distances[segment_index];
// intersections contain the classes of exiting road
intersection.classes = facade.GetClasses(path_point.classes);
steps.push_back(RouteStep{step_name_id,
name.to_string(),
ref.to_string(),
pronunciation.to_string(),
destinations.to_string(),
exits.to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
segment_duration / 10.,
@@ -144,9 +150,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// extract bearings
bearings = std::make_pair<std::uint16_t, std::uint16_t>(
path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get());
const auto entry_class = facade.GetEntryClass(path_point.entry_classid);
const auto bearing_class =
facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node));
const auto bearing_class = facade.GetBearingClass(path_point.turn_via_node);
auto bearing_data = bearing_class.getAvailableBearings();
intersection.in = bearing_class.findMatchingBearing(bearings.first);
intersection.out = bearing_class.findMatchingBearing(bearings.second);
@@ -174,7 +178,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
intersection.entry.clear();
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
{
intersection.entry.push_back(entry_class.allowsEntry(idx));
intersection.entry.push_back(path_point.entry_class.allowsEntry(idx));
}
std::int16_t bearing_in_driving_direction =
util::bearing::reverse(std::round(bearings.first));
@@ -192,12 +196,15 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const auto distance = leg_geometry.segment_distances[segment_index];
const EdgeWeight duration = segment_duration + target_duration;
const EdgeWeight weight = segment_weight + target_weight;
// intersections contain the classes of exiting road
intersection.classes = facade.GetClasses(facade.GetClassData(target_node_id));
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{step_name_id,
facade.GetNameForID(step_name_id).to_string(),
facade.GetRefForID(step_name_id).to_string(),
facade.GetPronunciationForID(step_name_id).to_string(),
facade.GetDestinationsForID(step_name_id).to_string(),
facade.GetExitsForID(step_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
duration / 10.,
@@ -239,6 +246,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
facade.GetRefForID(source_name_id).to_string(),
facade.GetPronunciationForID(source_name_id).to_string(),
facade.GetDestinationsForID(source_name_id).to_string(),
facade.GetExitsForID(source_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
duration / 10.,
@@ -261,6 +269,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
0,
IntermediateIntersection::NO_INDEX,
util::guidance::LaneTuple(),
{},
{}};
// This step has length zero, the only reason we need it is the target location
@@ -277,6 +286,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
facade.GetRefForID(target_name_id).to_string(),
facade.GetPronunciationForID(target_name_id).to_string(),
facade.GetDestinationsForID(target_name_id).to_string(),
facade.GetExitsForID(target_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
ZERO_DURATION,
@@ -130,8 +130,14 @@ inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
// ok, bite the sour grape and check the strings already
else
return !util::guidance::requiresNameAnnounced(
lhs.name, lhs.ref, lhs.pronunciation, rhs.name, rhs.ref, rhs.pronunciation);
return !util::guidance::requiresNameAnnounced(lhs.name,
lhs.ref,
lhs.pronunciation,
lhs.exits,
rhs.name,
rhs.ref,
rhs.pronunciation,
rhs.exits);
}
// alias for readability, both turn right | left
+5
View File
@@ -42,6 +42,7 @@ struct IntermediateIntersection
// turn lane information
util::guidance::LaneTuple lanes;
extractor::guidance::TurnLaneDescription lane_description;
std::vector<std::string> classes;
};
inline IntermediateIntersection getInvalidIntersection()
@@ -52,6 +53,7 @@ inline IntermediateIntersection getInvalidIntersection()
IntermediateIntersection::NO_INDEX,
IntermediateIntersection::NO_INDEX,
util::guidance::LaneTuple(),
{},
{}};
}
@@ -62,6 +64,7 @@ struct RouteStep
std::string ref;
std::string pronunciation;
std::string destinations;
std::string exits;
std::string rotary_name;
std::string rotary_pronunciation;
double duration; // duration in seconds
@@ -114,6 +117,7 @@ inline void RouteStep::Invalidate()
ref.clear();
pronunciation.clear();
destinations.clear();
exits.clear();
rotary_name.clear();
rotary_pronunciation.clear();
duration = 0;
@@ -178,6 +182,7 @@ inline RouteStep &RouteStep::AdaptStepSignage(const RouteStep &origin)
name = origin.name;
pronunciation = origin.pronunciation;
destinations = origin.destinations;
exits = origin.exits;
ref = origin.ref;
return *this;
+16 -1
View File
@@ -5,6 +5,7 @@
#include "extractor/travel_mode.hpp"
#include "engine/phantom_node.hpp"
#include "osrm/coordinate.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
@@ -32,8 +33,10 @@ struct PathData
util::guidance::LaneTupleIdPair lane_data;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// user defined classed of the street that leads to the turn
extractor::ClassData classes;
// entry class of the turn, indicating possibility of turns
EntryClassID entry_classid;
util::guidance::EntryClass entry_class;
// Source of the speed value on this road segment
DatasourceID datasource_id;
@@ -58,6 +61,18 @@ struct InternalRouteResult
{
return (leg != unpacked_path_segments.size() - 1);
}
// Note: includes duration for turns, except for at start and end node.
EdgeWeight duration() const
{
EdgeWeight ret{0};
for (const auto &leg : unpacked_path_segments)
for (const auto &segment : leg)
ret += segment.duration_until_turn;
return ret;
}
};
struct InternalManyRoutesResult
+2 -1
View File
@@ -27,9 +27,10 @@ class ViaRoutePlugin final : public BasePlugin
{
private:
const int max_locations_viaroute;
const int max_alternatives;
public:
explicit ViaRoutePlugin(int max_locations_viaroute);
explicit ViaRoutePlugin(int max_locations_viaroute, int max_alternatives);
Status HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
+13 -26
View File
@@ -20,7 +20,8 @@ class RoutingAlgorithmsInterface
{
public:
virtual InternalManyRoutesResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
AlternativePathSearch(const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives) const = 0;
virtual InternalRouteResult
ShortestPathSearch(const std::vector<PhantomNodes> &phantom_node_pair,
@@ -66,7 +67,8 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
virtual ~RoutingAlgorithms() = default;
InternalManyRoutesResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
AlternativePathSearch(const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives) const final override;
InternalRouteResult ShortestPathSearch(
const std::vector<PhantomNodes> &phantom_node_pair,
@@ -130,9 +132,11 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
template <typename Algorithm>
InternalManyRoutesResult
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives) const
{
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
return routing_algorithms::alternativePathSearch(
heaps, facade, phantom_node_pair, number_of_alternatives);
}
template <typename Algorithm>
@@ -157,7 +161,7 @@ RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &p
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::ch::manyToManySearch(
return routing_algorithms::manyToManySearch(
heaps, facade, phantom_nodes, source_indices, target_indices);
}
@@ -189,7 +193,8 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::G
// CoreCH overrides
template <>
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &,
unsigned) const
{
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
}
@@ -203,25 +208,7 @@ RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
{
throw util::exception("ManyToManySearch is disabled due to performance reasons");
}
// MLD overrides for not implemented
template <>
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
{
throw util::exception("AlternativePathSearch is not implemented");
}
template <>
inline std::vector<EdgeWeight>
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
{
throw util::exception("ManyToManySearch is not implemented");
}
}
}
} // ns engine
} // ns osrm
#endif
@@ -15,13 +15,19 @@ namespace engine
{
namespace routing_algorithms
{
namespace ch
{
InternalManyRoutesResult
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const PhantomNodes &phantom_node_pair);
} // namespace ch
alternativePathSearch(SearchEngineData<ch::Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives);
InternalManyRoutesResult
alternativePathSearch(SearchEngineData<mld::Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives);
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -21,20 +21,11 @@ namespace routing_algorithms
/// by the previous route.
/// This variation is only an optimazation for graphs with slow queries, for example
/// not fully contracted graphs.
InternalRouteResult directShortestPathSearch(
SearchEngineData<ch::Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
const PhantomNodes &phantom_nodes);
InternalRouteResult directShortestPathSearch(
SearchEngineData<corech::Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
const PhantomNodes &phantom_nodes);
InternalRouteResult directShortestPathSearch(
SearchEngineData<mld::Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
const PhantomNodes &phantom_nodes);
template <typename Algorithm>
InternalRouteResult
directShortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const PhantomNodes &phantom_nodes);
} // namespace routing_algorithms
} // namespace engine
@@ -16,15 +16,13 @@ namespace engine
namespace routing_algorithms
{
namespace ch
{
template <typename Algorithm>
std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
} // namespace ch
} // namespace routing_algorithms
} // namespace engine
@@ -6,6 +6,7 @@
#include "engine/algorithm.hpp"
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
#include "engine/search_engine_data.hpp"
#include "util/coordinate_calculation.hpp"
@@ -38,14 +39,10 @@ static constexpr bool REVERSE_DIRECTION = false;
static constexpr bool DO_NOT_FORCE_LOOPS = false;
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
bool needsLoopForward(const PhantomNodes &phantoms);
bool needsLoopBackwards(const PhantomNodes &phantoms);
template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
@@ -81,6 +78,40 @@ void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNod
}
}
template <typename ManyToManyQueryHeap>
void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardSource())
{
heap.Insert(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
}
if (phantom_node.IsValidReverseSource())
{
heap.Insert(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
}
}
template <typename ManyToManyQueryHeap>
void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardTarget())
{
heap.Insert(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
}
if (phantom_node.IsValidReverseTarget())
{
heap.Insert(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
}
}
template <typename FacadeT>
void annotatePath(const FacadeT &facade,
const PhantomNodes &phantom_node_pair,
@@ -112,6 +143,7 @@ void annotatePath(const FacadeT &facade,
const auto name_index = facade.GetNameIndex(node_id);
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
const auto classes = facade.GetClassData(node_id);
const auto geometry_index = facade.GetGeometryIndex(node_id);
std::vector<NodeID> id_vector;
@@ -158,7 +190,8 @@ void annotatePath(const FacadeT &facade,
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
INVALID_ENTRY_CLASSID,
classes,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
@@ -167,7 +200,7 @@ void annotatePath(const FacadeT &facade,
if (facade.HasLaneData(turn_id))
unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
unpacked_path.back().entry_class = facade.GetEntryClass(turn_id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += facade.GetDurationPenaltyForEdgeID(turn_id);
unpacked_path.back().weight_until_turn += facade.GetWeightPenaltyForEdgeID(turn_id);
@@ -233,7 +266,8 @@ void annotatePath(const FacadeT &facade,
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
facade.GetTravelMode(target_node_id),
INVALID_ENTRY_CLASSID,
facade.GetClassData(target_node_id),
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
@@ -338,6 +372,39 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algo
return distance;
}
template <typename AlgorithmT>
InternalRouteResult
extractRoute(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
const EdgeWeight weight,
const PhantomNodes &phantom_nodes,
const std::vector<NodeID> &unpacked_nodes,
const std::vector<EdgeID> &unpacked_edges)
{
InternalRouteResult raw_route_data;
raw_route_data.segment_end_coordinates = {phantom_nodes};
// No path found for both target nodes?
if (INVALID_EDGE_WEIGHT == weight)
{
return raw_route_data;
}
raw_route_data.shortest_path_weight = weight;
raw_route_data.unpacked_path_segments.resize(1);
raw_route_data.source_traversed_in_reverse.push_back(
(unpacked_nodes.front() != phantom_nodes.source_phantom.forward_segment_id.id));
raw_route_data.target_traversed_in_reverse.push_back(
(unpacked_nodes.back() != phantom_nodes.target_phantom.forward_segment_id.id));
annotatePath(facade,
phantom_nodes,
unpacked_nodes,
unpacked_edges,
raw_route_data.unpacked_path_segments.front());
return raw_route_data;
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -10,6 +10,12 @@
#include <boost/assert.hpp>
#include <algorithm>
#include <iterator>
#include <limits>
#include <tuple>
#include <vector>
namespace osrm
{
namespace engine
@@ -24,7 +30,7 @@ namespace
// Unrestricted search (Args is const PhantomNodes &):
// * use partition.GetQueryLevel to find the node query level based on source and target phantoms
// * allow to traverse all cells
inline LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
inline LevelID getNodeQueryLevel(const partition::MultiLevelPartitionView &partition,
NodeID node,
const PhantomNodes &phantom_nodes)
{
@@ -49,7 +55,7 @@ inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return tr
// * use the fixed level for queries
// * check if the node cell is the same as the specified parent onr
inline LevelID
getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
getNodeQueryLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
{
return level;
}
@@ -60,6 +66,70 @@ inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
}
}
// Heaps only record for each node its predecessor ("parent") on the shortest path.
// For re-constructing the actual path we need to trace back all parent "pointers".
// In contrast to the CH code MLD needs to know the edges (with clique arc property).
using PackedEdge = std::tuple</*from*/ NodeID, /*to*/ NodeID, /*from_clique_arc*/ bool>;
using PackedPath = std::vector<PackedEdge>;
template <bool DIRECTION, typename OutIter>
inline void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &heap,
const NodeID middle,
OutIter out)
{
NodeID current = middle;
NodeID parent = heap.GetData(current).parent;
while (current != parent)
{
const auto &data = heap.GetData(current);
if (DIRECTION == FORWARD_DIRECTION)
{
*out = std::make_tuple(parent, current, data.from_clique_arc);
++out;
}
else if (DIRECTION == REVERSE_DIRECTION)
{
*out = std::make_tuple(current, parent, data.from_clique_arc);
++out;
}
current = parent;
parent = heap.GetData(parent).parent;
}
}
template <bool DIRECTION>
inline PackedPath
retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &heap,
const NodeID middle)
{
PackedPath packed_path;
retrievePackedPathFromSingleHeap<DIRECTION>(heap, middle, std::back_inserter(packed_path));
return packed_path;
}
// Trace path from middle to start in the forward search space (in reverse)
// and from middle to end in the reverse search space. Middle connects paths.
inline PackedPath
retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const NodeID middle)
{
// Retrieve start -> middle. Is in reverse order since tracing back starts from middle.
auto packed_path = retrievePackedPathFromSingleHeap<FORWARD_DIRECTION>(forward_heap, middle);
std::reverse(begin(packed_path), end(packed_path));
// Retrieve middle -> end. Is already in correct order, tracing starts from middle.
auto into = std::back_inserter(packed_path);
retrievePackedPathFromSingleHeap<REVERSE_DIRECTION>(reverse_heap, middle, into);
return packed_path;
}
template <bool DIRECTION, typename... Args>
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
@@ -96,7 +166,7 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
}
}
const auto level = getNodeQureyLevel(partition, node, args...);
const auto level = getNodeQueryLevel(partition, node, args...);
if (level >= 1 && !forward_heap.GetData(node).from_clique_arc)
{
@@ -112,6 +182,7 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
{
const EdgeWeight to_weight = weight + shortcut_weight;
BOOST_ASSERT(to_weight >= weight);
if (!forward_heap.WasInserted(to))
{
forward_heap.Insert(to, to_weight, {node, true});
@@ -137,6 +208,7 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
{
const EdgeWeight to_weight = weight + shortcut_weight;
BOOST_ASSERT(to_weight >= weight);
if (!forward_heap.WasInserted(to))
{
forward_heap.Insert(to, to_weight, {node, true});
@@ -179,16 +251,24 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm>
}
}
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
// This gives us a packed path (node ids) from the base graph around s and t,
// and overlay node ids otherwise. We then have to unpack the overlay clique
// edges by recursively descending unpacking the path down to the base graph.
using UnpackedNodes = std::vector<NodeID>;
using UnpackedEdges = std::vector<EdgeID>;
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
template <typename... Args>
std::tuple<EdgeWeight, std::vector<NodeID>, std::vector<EdgeID>>
search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool force_loop_forward,
const bool force_loop_reverse,
EdgeWeight weight_upper_bound,
Args... args)
UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool force_loop_forward,
const bool force_loop_reverse,
EdgeWeight weight_upper_bound,
Args... args)
{
if (forward_heap.Empty() || reverse_heap.Empty())
{
@@ -242,27 +322,12 @@ search(SearchEngineData<Algorithm> &engine_working_data,
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
}
// Get packed path as edges {from node ID, to node ID, edge ID}
std::vector<std::tuple<NodeID, NodeID, bool>> packed_path;
NodeID current_node = middle, parent_node = forward_heap.GetData(middle).parent;
while (parent_node != current_node)
{
const auto &data = forward_heap.GetData(current_node);
packed_path.push_back(std::make_tuple(parent_node, current_node, data.from_clique_arc));
current_node = parent_node;
parent_node = forward_heap.GetData(parent_node).parent;
}
std::reverse(std::begin(packed_path), std::end(packed_path));
const NodeID source_node = current_node;
// Get packed path as edges {from node ID, to node ID, from_clique_arc}
auto packed_path = retrievePackedPathFromHeap(forward_heap, reverse_heap, middle);
current_node = middle, parent_node = reverse_heap.GetData(middle).parent;
while (parent_node != current_node)
{
const auto &data = reverse_heap.GetData(current_node);
packed_path.push_back(std::make_tuple(current_node, parent_node, data.from_clique_arc));
current_node = parent_node;
parent_node = reverse_heap.GetData(parent_node).parent;
}
// Beware the edge case when start, middle, end are all the same.
// In this case we return a single node, no edges. We also don't unpack.
const NodeID source_node = !packed_path.empty() ? std::get<0>(packed_path.front()) : middle;
// Unpack path
std::vector<NodeID> unpacked_nodes;
@@ -271,6 +336,7 @@ search(SearchEngineData<Algorithm> &engine_working_data,
unpacked_edges.reserve(packed_path.size());
unpacked_nodes.push_back(source_node);
for (auto const &packed_edge : packed_path)
{
NodeID source, target;
@@ -283,7 +349,7 @@ search(SearchEngineData<Algorithm> &engine_working_data,
}
else
{ // an overlay graph edge
LevelID level = getNodeQureyLevel(partition, source, args...);
LevelID level = getNodeQueryLevel(partition, source, args...);
CellID parent_cell_id = partition.GetCell(level, source);
BOOST_ASSERT(parent_cell_id == partition.GetCell(level, target));
+24
View File
@@ -78,6 +78,19 @@ struct MultiLayerDijkstraHeapData
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
};
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
{
EdgeWeight duration;
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration)
: MultiLayerDijkstraHeapData(p), duration(duration)
{
}
ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeWeight duration)
: MultiLayerDijkstraHeapData(p, from), duration(duration)
{
}
};
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
{
using QueryHeap = util::QueryHeap<NodeID,
@@ -86,12 +99,23 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
MultiLayerDijkstraHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using ManyToManyQueryHeap = util::QueryHeap<NodeID,
NodeID,
EdgeWeight,
ManyToManyMultiLayerDijkstraHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
static SearchEngineHeapPtr forward_heap_1;
static SearchEngineHeapPtr reverse_heap_1;
static ManyToManyHeapPtr many_to_many_heap;
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
};
}
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef OSRM_EXTRACTOR_CLASSES_DATA_HPP
#define OSRM_EXTRACTOR_CLASSES_DATA_HPP
#include "util/bit_range.hpp"
#include <cstdint>
namespace osrm
{
namespace extractor
{
using ClassData = std::uint8_t;
static const std::uint8_t MAX_CLASS_INDEX = 8 - 1;
inline bool isSubset(const ClassData lhs, const ClassData rhs) { return (lhs & rhs) == lhs; }
inline auto getClassIndexes(const ClassData data) { return util::makeBitRange<ClassData>(data); }
}
}
#endif
@@ -83,8 +83,6 @@ class EdgeBasedGraphFactory
const extractor::PackedOSMIDs &osm_node_ids,
ProfileProperties profile_properties,
const util::NameTable &name_table,
std::vector<std::uint32_t> &turn_lane_offsets,
std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks,
guidance::LaneDescriptionMap &lane_description_map);
void Run(ScriptingEnvironment &scripting_environment,
@@ -150,8 +148,6 @@ class EdgeBasedGraphFactory
ProfileProperties profile_properties;
const util::NameTable &name_table;
std::vector<std::uint32_t> &turn_lane_offsets;
std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks;
guidance::LaneDescriptionMap &lane_description_map;
unsigned RenumberEdges();
@@ -1,60 +0,0 @@
#ifndef EXTERNAL_MEMORY_NODE_HPP_
#define EXTERNAL_MEMORY_NODE_HPP_
#include "extractor/query_node.hpp"
#include "util/typedefs.hpp"
#include <cstdint>
namespace osrm
{
namespace extractor
{
struct ExternalMemoryNode : QueryNode
{
ExternalMemoryNode(const util::FixedLongitude lon_,
const util::FixedLatitude lat_,
OSMNodeID node_id_,
bool barrier_,
bool traffic_lights_)
: QueryNode(lon_, lat_, node_id_), barrier(barrier_), traffic_lights(traffic_lights_)
{
}
ExternalMemoryNode() : barrier(false), traffic_lights(false) {}
static ExternalMemoryNode min_value()
{
return ExternalMemoryNode(
util::FixedLongitude{0}, util::FixedLatitude{0}, MIN_OSM_NODEID, false, false);
}
static ExternalMemoryNode max_value()
{
return ExternalMemoryNode(util::FixedLongitude{std::numeric_limits<std::int32_t>::max()},
util::FixedLatitude{std::numeric_limits<std::int32_t>::max()},
MAX_OSM_NODEID,
false,
false);
}
bool barrier;
bool traffic_lights;
};
struct ExternalMemoryNodeSTXXLCompare
{
using value_type = ExternalMemoryNode;
value_type max_value() { return value_type::max_value(); }
value_type min_value() { return value_type::min_value(); }
bool operator()(const value_type &left, const value_type &right) const
{
return left.node_id < right.node_id;
}
};
}
}
#endif /* EXTERNAL_MEMORY_NODE_HPP_ */
+16 -27
View File
@@ -1,40 +1,28 @@
#ifndef EXTRACTION_CONTAINERS_HPP
#define EXTRACTION_CONTAINERS_HPP
#include "extractor/external_memory_node.hpp"
#include "extractor/first_and_last_segment_of_way.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/internal_extractor_edge.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction.hpp"
#include "extractor/scripting_environment.hpp"
#include "storage/io.hpp"
#include <cstdint>
#include <stxxl/vector>
#include <unordered_map>
namespace osrm
{
namespace extractor
{
/**
* Uses external memory containers from stxxl to store all the data that
* Uses memory containers to store all the data that
* is collected by the extractor callbacks.
*
* The data is the filtered, aggregated and finally written to disk.
*/
class ExtractionContainers
{
#ifndef _MSC_VER
constexpr static unsigned stxxl_memory =
((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max()
: std::numeric_limits<unsigned>::max());
#else
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
void FlushVectors();
void PrepareNodes();
void PrepareRestrictions();
void PrepareEdges(ScriptingEnvironment &scripting_environment);
@@ -45,23 +33,24 @@ class ExtractionContainers
void WriteCharData(const std::string &file_name);
public:
using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
using NodeIDVector = std::vector<OSMNodeID>;
using NodeVector = std::vector<QueryNode>;
using EdgeVector = std::vector<InternalExtractorEdge>;
using RestrictionsVector = std::vector<InputRestrictionContainer>;
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
using STXXLNameCharData = stxxl::vector<unsigned char>;
using STXXLNameOffsets = stxxl::vector<unsigned>;
using WayIDStartEndVector = std::vector<FirstAndLastSegmentOfWay>;
using NameCharData = std::vector<unsigned char>;
using NameOffsets = std::vector<unsigned>;
STXXLNodeIDVector used_node_id_list;
STXXLNodeVector all_nodes_list;
STXXLEdgeVector all_edges_list;
STXXLNameCharData name_char_data;
STXXLNameOffsets name_offsets;
std::vector<OSMNodeID> barrier_nodes;
std::vector<OSMNodeID> traffic_lights;
NodeIDVector used_node_id_list;
NodeVector all_nodes_list;
EdgeVector all_edges_list;
NameCharData name_char_data;
NameOffsets name_offsets;
// an adjacency array containing all turn lane masks
RestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;
WayIDStartEndVector way_start_end_id_list;
unsigned max_internal_node_id;
std::vector<TurnRestriction> unconditional_turn_restrictions;
+8
View File
@@ -53,6 +53,7 @@ struct ExtractionWay
ref.clear();
pronunciation.clear();
destinations.clear();
exits.clear();
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
turn_lanes_forward.clear();
@@ -69,6 +70,8 @@ struct ExtractionWay
const char *GetRef() const { return ref.c_str(); }
void SetDestinations(const char *value) { detail::maybeSetString(destinations, value); }
const char *GetDestinations() const { return destinations.c_str(); }
void SetExits(const char *value) { detail::maybeSetString(exits, value); }
const char *GetExits() const { return exits.c_str(); }
void SetPronunciation(const char *value) { detail::maybeSetString(pronunciation, value); }
const char *GetPronunciation() const { return pronunciation.c_str(); }
void SetTurnLanesForward(const char *value)
@@ -82,6 +85,10 @@ struct ExtractionWay
}
const char *GetTurnLanesBackward() const { return turn_lanes_backward.c_str(); }
// markers for determining user-defined classes for each way
std::unordered_map<std::string, bool> forward_classes;
std::unordered_map<std::string, bool> backward_classes;
// speed in km/h
double forward_speed;
double backward_speed;
@@ -96,6 +103,7 @@ struct ExtractionWay
std::string ref;
std::string pronunciation;
std::string destinations;
std::string exits;
std::string turn_lanes_forward;
std::string turn_lanes_backward;
guidance::RoadClassification road_classification;
+4 -15
View File
@@ -56,8 +56,8 @@ class Extractor
private:
ExtractorConfig config;
std::vector<TurnRestriction> ParseOSMData(ScriptingEnvironment &scripting_environment,
const unsigned number_of_threads);
std::tuple<guidance::LaneDescriptionMap, std::vector<TurnRestriction>>
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
std::pair<std::size_t, EdgeID>
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
@@ -69,9 +69,8 @@ class Extractor
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);
void WriteProfileProperties(const std::string &output_path,
const ProfileProperties &properties) const;
std::vector<TurnRestriction> &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,
@@ -92,20 +91,10 @@ class Extractor
const std::vector<util::guidance::BearingClass> &bearing_classes,
const std::vector<util::guidance::EntryClass> &entry_classes) const;
void WriteTurnLaneData(const std::string &turn_lane_file) const;
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
static void WriteCompressedNodeBasedGraph(const std::string &path,
const util::NodeBasedDynamicGraph &graph,
const std::vector<util::Coordinate> &coordiantes);
// globals persisting during the extraction process and the graph generation process
// during turn lane analysis, we might have to combine lanes for roads that are modelled as two
// but are more or less experienced as one. This can be due to solid lines in between lanes, for
// example, that genereate a small separation between them. As a result, we might have to
// augment the turn lane map during processing, further adding more types.
guidance::LaneDescriptionMap turn_lane_map;
};
}
}
+14 -10
View File
@@ -1,6 +1,7 @@
#ifndef EXTRACTOR_CALLBACKS_HPP
#define EXTRACTOR_CALLBACKS_HPP
#include "extractor/class_data.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/typedefs.hpp"
@@ -18,10 +19,10 @@ class Way;
namespace std
{
template <> struct hash<std::tuple<std::string, std::string, std::string, std::string>>
template <> struct hash<std::tuple<std::string, std::string, std::string, std::string, std::string>>
{
std::size_t
operator()(const std::tuple<std::string, std::string, std::string, std::string> &mk) const
std::size_t operator()(
const std::tuple<std::string, std::string, std::string, std::string, std::string> &mk) const
noexcept
{
std::size_t seed = 0;
@@ -29,6 +30,7 @@ template <> struct hash<std::tuple<std::string, std::string, std::string, std::s
boost::hash_combine(seed, std::get<1>(mk));
boost::hash_combine(seed, std::get<2>(mk));
boost::hash_combine(seed, std::get<3>(mk));
boost::hash_combine(seed, std::get<4>(mk));
return seed;
}
};
@@ -55,18 +57,23 @@ struct ProfileProperties;
class ExtractorCallbacks
{
private:
// used to deduplicate street names, refs, destinations, pronunciation: actually maps to name
// ids
using MapKey = std::tuple<std::string, std::string, std::string, std::string>;
// used to deduplicate street names, refs, destinations, pronunciation, exits:
// actually maps to name ids
using MapKey = std::tuple<std::string, std::string, std::string, std::string, std::string>;
using MapVal = unsigned;
std::unordered_map<MapKey, MapVal> string_map;
guidance::LaneDescriptionMap lane_description_map;
ExtractionContainers &external_memory;
std::unordered_map<std::string, ClassData> &classes_map;
guidance::LaneDescriptionMap &lane_description_map;
bool fallback_to_duration;
bool force_split_edges;
public:
using ClassesMap = std::unordered_map<std::string, ClassData>;
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
std::unordered_map<std::string, ClassData> &classes_map,
guidance::LaneDescriptionMap &lane_description_map,
const ProfileProperties &properties);
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
@@ -80,9 +87,6 @@ class ExtractorCallbacks
// warning: caller needs to take care of synchronization!
void ProcessWay(const osmium::Way &current_way, const ExtractionWay &result_way);
// destroys the internal laneDescriptionMap
guidance::LaneDescriptionMap &&moveOutLaneDescriptionMap();
};
}
}
+56
View File
@@ -4,11 +4,15 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/serialization.hpp"
#include "extractor/turn_data_container.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/packed_vector.hpp"
#include "util/range_table.hpp"
#include "util/serialization.hpp"
#include <boost/assert.hpp>
@@ -20,6 +24,58 @@ namespace extractor
namespace files
{
// writes the .osrm.icd file
template <typename IntersectionBearingsT, typename EntryClassVectorT>
inline void writeIntersections(const boost::filesystem::path &path,
const IntersectionBearingsT &intersection_bearings,
const EntryClassVectorT &entry_classes)
{
static_assert(std::is_same<IntersectionBearingsContainer, IntersectionBearingsT>::value ||
std::is_same<IntersectionBearingsView, IntersectionBearingsT>::value,
"");
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
serialization::write(writer, intersection_bearings);
storage::serialization::write(writer, entry_classes);
}
// read the .osrm.icd file
template <typename IntersectionBearingsT, typename EntryClassVectorT>
inline void readIntersections(const boost::filesystem::path &path,
IntersectionBearingsT &intersection_bearings,
EntryClassVectorT &entry_classes)
{
static_assert(std::is_same<IntersectionBearingsContainer, IntersectionBearingsT>::value ||
std::is_same<IntersectionBearingsView, IntersectionBearingsT>::value,
"");
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
serialization::read(reader, intersection_bearings);
storage::serialization::read(reader, entry_classes);
}
// reads .osrm.properties
inline void readProfileProperties(const boost::filesystem::path &path,
ProfileProperties &properties)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, properties);
}
// writes .osrm.properties
inline void writeProfileProperties(const boost::filesystem::path &path,
const ProfileProperties &properties)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, properties);
}
template <typename EdgeBasedEdgeVector>
void writeEdgeBasedGraph(const boost::filesystem::path &path,
EdgeID const max_edge_id,
@@ -1,7 +1,6 @@
#ifndef FIRST_AND_LAST_SEGMENT_OF_WAY_HPP
#define FIRST_AND_LAST_SEGMENT_OF_WAY_HPP
#include "extractor/external_memory_node.hpp"
#include "util/typedefs.hpp"
#include <limits>
@@ -44,7 +43,7 @@ struct FirstAndLastSegmentOfWay
}
};
struct FirstAndLastSegmentOfWayStxxlCompare
struct FirstAndLastSegmentOfWayCompare
{
using value_type = FirstAndLastSegmentOfWay;
bool operator()(const FirstAndLastSegmentOfWay &a, const FirstAndLastSegmentOfWay &b) const
@@ -73,8 +73,6 @@ class TurnLaneHandler
typedef std::vector<TurnLaneData> LaneDataVector;
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<TurnLaneType::Mask> &turn_lane_masks,
LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis,
util::guidance::LaneDataIdMap &id_map);
@@ -90,8 +88,8 @@ 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 std::vector<std::uint32_t> &turn_lane_offsets;
const std::vector<TurnLaneType::Mask> &turn_lane_masks;
std::vector<std::uint32_t> turn_lane_offsets;
std::vector<TurnLaneType::Mask> turn_lane_masks;
LaneDescriptionMap &lane_description_map;
const TurnAnalysis &turn_analysis;
util::guidance::LaneDataIdMap &id_map;
@@ -4,6 +4,7 @@
#include <bitset>
#include <cstddef>
#include <cstdint>
#include <numeric> //partial_sum
#include <string>
#include <unordered_map>
#include <vector>
@@ -99,6 +100,34 @@ typedef util::ConcurrentIDMap<guidance::TurnLaneDescription,
guidance::TurnLaneDescription_hash>
LaneDescriptionMap;
inline std::tuple<std::vector<std::uint32_t>, std::vector<TurnLaneType::Mask>>
transformTurnLaneMapIntoArrays(const LaneDescriptionMap &turn_lane_map)
{
// could use some additional capacity? To avoid a copy during processing, though small data so
// probably not that important.
//
// From the map, we construct an adjacency array that allows access from all IDs to the list of
// associated Turn Lane Masks.
//
// turn lane offsets points into the locations of the turn_lane_masks array. We use a standard
// adjacency array like structure to store the turn lane masks.
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.data.size() +
2); // empty ID + sentinel
for (auto entry = turn_lane_map.data.begin(); entry != turn_lane_map.data.end(); ++entry)
turn_lane_offsets[entry->second + 1] = entry->first.size();
// inplace prefix sum
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
// allocate the current masks
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
for (auto entry = turn_lane_map.data.begin(); entry != turn_lane_map.data.end(); ++entry)
std::copy(entry->first.begin(),
entry->first.end(),
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
return std::make_tuple(std::move(turn_lane_offsets), std::move(turn_lane_masks));
}
} // guidance
} // extractor
} // osrm
@@ -72,6 +72,7 @@ struct InternalExtractorEdge
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE,
0,
guidance::TurnLaneType::empty,
guidance::RoadClassification()),
weight_data(), duration_data()
@@ -91,6 +92,7 @@ struct InternalExtractorEdge
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
LaneDescriptionID lane_description,
guidance::RoadClassification road_classification,
util::Coordinate source_coordinate)
@@ -107,6 +109,7 @@ struct InternalExtractorEdge
restricted,
is_split,
travel_mode,
classes,
lane_description,
std::move(road_classification)),
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
@@ -139,6 +142,7 @@ struct InternalExtractorEdge
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE,
0,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassification(),
util::Coordinate());
@@ -158,6 +162,7 @@ struct InternalExtractorEdge
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE,
0,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassification(),
util::Coordinate());
@@ -0,0 +1,105 @@
#ifndef OSRM_EXTRACTOR_BEARING_CONTAINER_HPP
#define OSRM_EXTRACTOR_BEARING_CONTAINER_HPP
#include "storage/shared_memory_ownership.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/range_table.hpp"
#include "util/vector_view.hpp"
#include <numeric>
namespace osrm
{
namespace extractor
{
namespace detail
{
template <storage::Ownership Ownership> class IntersectionBearingsContainer;
}
namespace serialization
{
template <storage::Ownership Ownership>
void read(storage::io::FileReader &reader,
detail::IntersectionBearingsContainer<Ownership> &turn_data);
template <storage::Ownership Ownership>
void write(storage::io::FileWriter &writer,
const detail::IntersectionBearingsContainer<Ownership> &turn_data);
}
namespace detail
{
template <storage::Ownership Ownership> class IntersectionBearingsContainer
{
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
template <unsigned size> using RangeTable = util::RangeTable<size, Ownership>;
public:
IntersectionBearingsContainer() = default;
IntersectionBearingsContainer(IntersectionBearingsContainer &&) = default;
IntersectionBearingsContainer(const IntersectionBearingsContainer &) = default;
IntersectionBearingsContainer &operator=(IntersectionBearingsContainer &&) = default;
IntersectionBearingsContainer &operator=(const IntersectionBearingsContainer &) = default;
IntersectionBearingsContainer(std::vector<BearingClassID> node_to_class_id_,
const std::vector<util::guidance::BearingClass> &bearing_classes)
: node_to_class_id(std::move(node_to_class_id_))
{
std::vector<unsigned> bearing_counts(bearing_classes.size());
std::transform(bearing_classes.begin(),
bearing_classes.end(),
bearing_counts.begin(),
[](const auto &bearings) { return bearings.getAvailableBearings().size(); });
auto total_bearings = std::accumulate(bearing_counts.begin(), bearing_counts.end(), 0);
class_id_to_ranges_table = RangeTable<16>{bearing_counts};
values.reserve(total_bearings);
for (const auto &bearing_class : bearing_classes)
{
const auto &bearings = bearing_class.getAvailableBearings();
values.insert(values.end(), bearings.begin(), bearings.end());
}
}
IntersectionBearingsContainer(Vector<DiscreteBearing> values_,
Vector<BearingClassID> node_to_class_id_,
RangeTable<16> class_id_to_ranges_table_)
: values(std::move(values_)), node_to_class_id(std::move(node_to_class_id_)),
class_id_to_ranges_table(std::move(class_id_to_ranges_table_))
{
}
// Returns the bearing class for an intersection node
util::guidance::BearingClass GetBearingClass(const NodeID node) const
{
auto class_id = node_to_class_id[node];
auto range = class_id_to_ranges_table.GetRange(class_id);
util::guidance::BearingClass result;
std::for_each(values.begin() + range.front(),
values.begin() + range.back() + 1,
[&](const DiscreteBearing &bearing) { result.add(bearing); });
return result;
}
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
IntersectionBearingsContainer &turn_data_container);
friend void
serialization::write<Ownership>(storage::io::FileWriter &writer,
const IntersectionBearingsContainer &turn_data_container);
private:
Vector<DiscreteBearing> values;
Vector<BearingClassID> node_to_class_id;
RangeTable<16> class_id_to_ranges_table;
};
}
using IntersectionBearingsContainer =
detail::IntersectionBearingsContainer<storage::Ownership::Container>;
using IntersectionBearingsView = detail::IntersectionBearingsContainer<storage::Ownership::View>;
}
}
#endif
+9 -1
View File
@@ -1,6 +1,7 @@
#ifndef NODE_BASED_EDGE_HPP
#define NODE_BASED_EDGE_HPP
#include "extractor/class_data.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
@@ -28,6 +29,7 @@ struct NodeBasedEdge
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification);
@@ -46,6 +48,7 @@ struct NodeBasedEdge
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
};
@@ -65,6 +68,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification);
@@ -95,12 +99,14 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
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),
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
classes(classes), lane_description_id(lane_description_id),
road_classification(std::move(road_classification))
{
}
@@ -134,6 +140,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
bool restricted,
bool is_split,
TravelMode travel_mode,
ClassData classes,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification)
: NodeBasedEdge(SPECIAL_NODEID,
@@ -149,6 +156,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
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))
+16 -4
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
#include "extractor/class_data.hpp"
#include "extractor/travel_mode.hpp"
#include "storage/io_fwd.hpp"
@@ -41,16 +42,18 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
EdgeBasedNodeDataContainerImpl() = default;
EdgeBasedNodeDataContainerImpl(std::size_t size)
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size)
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size), classes(size)
{
}
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids,
Vector<NameID> name_ids,
Vector<ComponentID> component_ids,
Vector<TravelMode> travel_modes)
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))
component_ids(std::move(component_ids)), travel_modes(std::move(travel_modes)),
classes(std::move(classes))
{
}
@@ -62,13 +65,20 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
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)
void SetData(NodeID node_id,
GeometryID geometry_id,
NameID name_id,
TravelMode travel_mode,
ClassData class_data)
{
geometry_ids[node_id] = geometry_id;
name_ids[node_id] = name_id;
travel_modes[node_id] = travel_mode;
classes[node_id] = class_data;
}
// Used by EdgeBasedGraphFactory to fill data structure
@@ -91,6 +101,7 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
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);
}
private:
@@ -98,6 +109,7 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
Vector<NameID> name_ids;
Vector<ComponentID> component_ids;
Vector<TravelMode> travel_modes;
Vector<ClassData> classes;
};
}
+22 -1
View File
@@ -1,11 +1,14 @@
#ifndef PROFILE_PROPERTIES_HPP
#define PROFILE_PROPERTIES_HPP
#include "extractor/class_data.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <cstdint>
namespace osrm
{
@@ -17,6 +20,7 @@ const constexpr auto DEFAULT_MAX_SPEED = 180 / 3.6; // 180kmph -> m/s
struct ProfileProperties
{
static constexpr int MAX_WEIGHT_NAME_LENGTH = 255;
static constexpr int MAX_CLASS_NAME_LENGTH = 255;
ProfileProperties()
: traffic_signal_penalty(0), u_turn_penalty(0),
@@ -66,6 +70,22 @@ struct ProfileProperties
return std::string(weight_name);
}
void SetClassName(std::size_t index, const std::string &name)
{
char *name_ptr = class_names[index];
auto count = std::min<std::size_t>(name.length(), MAX_CLASS_NAME_LENGTH) + 1;
std::copy_n(name.c_str(), count, name_ptr);
// Make sure this is always zero terminated
BOOST_ASSERT(class_names[index][count - 1] == '\0');
BOOST_ASSERT(class_names[index][MAX_CLASS_NAME_LENGTH] == '\0');
}
std::string GetClassName(std::size_t index) const
{
BOOST_ASSERT(index <= MAX_CLASS_INDEX);
return std::string(class_names[index]);
}
double GetWeightMultiplier() const { return std::pow(10., weight_precision); }
double GetMaxTurnWeight() const
@@ -86,9 +106,10 @@ struct ProfileProperties
bool fallback_to_duration;
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
//! stores the names of each class
std::array<char[MAX_CLASS_NAME_LENGTH + 1], MAX_CLASS_INDEX + 1> class_names;
unsigned weight_precision = 1;
bool force_split_edges = false;
bool call_tagless_node_function = true;
};
}
+34
View File
@@ -2,8 +2,10 @@
#define OSRM_EXTRACTOR_IO_HPP
#include "extractor/datasources.hpp"
#include "extractor/intersection_bearings_container.hpp"
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/restriction.hpp"
#include "extractor/segment_data_container.hpp"
#include "extractor/turn_data_container.hpp"
@@ -20,6 +22,36 @@ namespace extractor
namespace serialization
{
// read/write for bearing data
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader,
detail::IntersectionBearingsContainer<Ownership> &intersection_bearings)
{
storage::serialization::read(reader, intersection_bearings.values);
storage::serialization::read(reader, intersection_bearings.node_to_class_id);
util::serialization::read(reader, intersection_bearings.class_id_to_ranges_table);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::IntersectionBearingsContainer<Ownership> &intersection_bearings)
{
storage::serialization::write(writer, intersection_bearings.values);
storage::serialization::write(writer, intersection_bearings.node_to_class_id);
util::serialization::write(writer, intersection_bearings.class_id_to_ranges_table);
}
// read/write for properties file
inline void read(storage::io::FileReader &reader, ProfileProperties &properties)
{
reader.ReadInto(properties);
}
inline void write(storage::io::FileWriter &writer, const ProfileProperties &properties)
{
writer.WriteFrom(properties);
}
// read/write for datasources file
inline void read(storage::io::FileReader &reader, Datasources &sources)
{
@@ -89,6 +121,7 @@ inline void read(storage::io::FileReader &reader,
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>
@@ -99,6 +132,7 @@ inline void write(storage::io::FileWriter &writer,
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);
}
// read/write for conditional turn restrictions file
+71 -4
View File
@@ -176,6 +176,64 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
return engine_config_ptr();
}
// Set EngineConfig system-wide limits on construction, if requested
auto max_locations_trip = params->Get(Nan::New("max_locations_trip").ToLocalChecked());
auto max_locations_viaroute = params->Get(Nan::New("max_locations_viaroute").ToLocalChecked());
auto max_locations_distance_table =
params->Get(Nan::New("max_locations_distance_table").ToLocalChecked());
auto max_locations_map_matching =
params->Get(Nan::New("max_locations_map_matching").ToLocalChecked());
auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked());
auto max_alternatives = params->Get(Nan::New("max_alternatives").ToLocalChecked());
if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber())
{
Nan::ThrowError("max_locations_trip must be an integral number");
return engine_config_ptr();
}
if (!max_locations_viaroute->IsUndefined() && !max_locations_viaroute->IsNumber())
{
Nan::ThrowError("max_locations_viaroute must be an integral number");
return engine_config_ptr();
}
if (!max_locations_distance_table->IsUndefined() && !max_locations_distance_table->IsNumber())
{
Nan::ThrowError("max_locations_distance_table must be an integral number");
return engine_config_ptr();
}
if (!max_locations_map_matching->IsUndefined() && !max_locations_map_matching->IsNumber())
{
Nan::ThrowError("max_locations_map_matching must be an integral number");
return engine_config_ptr();
}
if (!max_results_nearest->IsUndefined() && !max_results_nearest->IsNumber())
{
Nan::ThrowError("max_results_nearest must be an integral number");
return engine_config_ptr();
}
if (!max_alternatives->IsUndefined() && !max_alternatives->IsNumber())
{
Nan::ThrowError("max_alternatives must be an integral number");
return engine_config_ptr();
}
if (max_locations_trip->IsNumber())
engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue());
if (max_locations_viaroute->IsNumber())
engine_config->max_locations_viaroute =
static_cast<int>(max_locations_viaroute->NumberValue());
if (max_locations_distance_table->IsNumber())
engine_config->max_locations_distance_table =
static_cast<int>(max_locations_distance_table->NumberValue());
if (max_locations_map_matching->IsNumber())
engine_config->max_locations_map_matching =
static_cast<int>(max_locations_map_matching->NumberValue());
if (max_results_nearest->IsNumber())
engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue());
if (max_alternatives->IsNumber())
engine_config->max_alternatives = static_cast<int>(max_alternatives->NumberValue());
return engine_config;
}
@@ -703,7 +761,7 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
if (!value->IsBoolean() && !value->IsNull())
{
Nan::ThrowError("'continue_straight' parama must be boolean or null");
Nan::ThrowError("'continue_straight' param must be boolean or null");
return route_parameters_ptr();
}
if (value->IsBoolean())
@@ -718,12 +776,21 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
if (value.IsEmpty())
return route_parameters_ptr();
if (!value->IsBoolean())
if (value->IsBoolean())
{
Nan::ThrowError("'alternatives' parama must be boolean");
params->alternatives = value->BooleanValue();
params->number_of_alternatives = value->BooleanValue() ? 1u : 0u;
}
else if (value->IsNumber())
{
params->alternatives = value->BooleanValue();
params->number_of_alternatives = static_cast<unsigned>(value->NumberValue());
}
else
{
Nan::ThrowError("'alternatives' param must be boolean or number");
return route_parameters_ptr();
}
params->alternatives = value->BooleanValue();
}
bool parsedSuccessfully = parseCommonParameters(obj, params);
+45 -25
View File
@@ -46,18 +46,18 @@ namespace detail
template <storage::Ownership Ownership> class CellStorageImpl
{
public:
using WeightOffset = std::uint32_t;
using ValueOffset = std::uint32_t;
using BoundaryOffset = std::uint32_t;
using BoundarySize = std::uint32_t;
using SourceIndex = std::uint32_t;
using DestinationIndex = std::uint32_t;
static constexpr auto INVALID_WEIGHT_OFFSET = std::numeric_limits<WeightOffset>::max();
static constexpr auto INVALID_VALUE_OFFSET = std::numeric_limits<ValueOffset>::max();
static constexpr auto INVALID_BOUNDARY_OFFSET = std::numeric_limits<BoundaryOffset>::max();
struct CellData
{
WeightOffset weight_offset = INVALID_WEIGHT_OFFSET;
ValueOffset value_offset = INVALID_VALUE_OFFSET;
BoundaryOffset source_boundary_offset = INVALID_BOUNDARY_OFFSET;
BoundaryOffset destination_boundary_offset = INVALID_BOUNDARY_OFFSET;
BoundarySize num_source_nodes = 0;
@@ -69,15 +69,16 @@ template <storage::Ownership Ownership> class CellStorageImpl
// Implementation of the cell view. We need a template parameter here
// because we need to derive a read-only and read-write view from this.
template <typename WeightValueT> class CellImpl
template <typename WeightValueT, typename DurationValueT> class CellImpl
{
private:
using WeightPtrT = WeightValueT *;
using WeightRefT = WeightValueT &;
using DurationPtrT = DurationValueT *;
BoundarySize num_source_nodes;
BoundarySize num_destination_nodes;
WeightPtrT const weights;
DurationPtrT const durations;
const NodeID *const source_boundary;
const NodeID *const destination_boundary;
@@ -123,20 +124,19 @@ template <storage::Ownership Ownership> class CellStorageImpl
const std::size_t stride;
};
public:
auto GetOutWeight(NodeID node) const
template <typename ValuePtr> auto GetOutRange(const ValuePtr ptr, const NodeID node) const
{
auto iter = std::find(source_boundary, source_boundary + num_source_nodes, node);
if (iter == source_boundary + num_source_nodes)
return boost::make_iterator_range(weights, weights);
return boost::make_iterator_range(ptr, ptr);
auto row = std::distance(source_boundary, iter);
auto begin = weights + num_destination_nodes * row;
auto begin = ptr + num_destination_nodes * row;
auto end = begin + num_destination_nodes;
return boost::make_iterator_range(begin, end);
}
auto GetInWeight(NodeID node) const
template <typename ValuePtr> auto GetInRange(const ValuePtr ptr, const NodeID node) const
{
auto iter =
std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
@@ -144,12 +144,21 @@ template <storage::Ownership Ownership> class CellStorageImpl
return boost::make_iterator_range(ColumnIterator{}, ColumnIterator{});
auto column = std::distance(destination_boundary, iter);
auto begin = ColumnIterator{weights + column, num_destination_nodes};
auto end = ColumnIterator{weights + column + num_source_nodes * num_destination_nodes,
auto begin = ColumnIterator{ptr + column, num_destination_nodes};
auto end = ColumnIterator{ptr + column + num_source_nodes * num_destination_nodes,
num_destination_nodes};
return boost::make_iterator_range(begin, end);
}
public:
auto GetOutWeight(NodeID node) const { return GetOutRange(weights, node); }
auto GetInWeight(NodeID node) const { return GetInRange(weights, node); }
auto GetOutDuration(NodeID node) const { return GetOutRange(durations, node); }
auto GetInDuration(NodeID node) const { return GetInRange(durations, node); }
auto GetSourceNodes() const
{
return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes);
@@ -162,16 +171,19 @@ template <storage::Ownership Ownership> class CellStorageImpl
}
CellImpl(const CellData &data,
WeightPtrT const all_weight,
WeightPtrT const all_weights,
DurationPtrT const all_durations,
const NodeID *const all_sources,
const NodeID *const all_destinations)
: num_source_nodes{data.num_source_nodes},
num_destination_nodes{data.num_destination_nodes},
weights{all_weight + data.weight_offset},
weights{all_weights + data.value_offset},
durations{all_durations + data.value_offset},
source_boundary{all_sources + data.source_boundary_offset},
destination_boundary{all_destinations + data.destination_boundary_offset}
{
BOOST_ASSERT(all_weight != nullptr);
BOOST_ASSERT(all_weights != nullptr);
BOOST_ASSERT(all_durations != nullptr);
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr);
}
@@ -180,8 +192,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
std::size_t LevelIDToIndex(LevelID level) const { return level - 1; }
public:
using Cell = CellImpl<EdgeWeight>;
using ConstCell = CellImpl<const EdgeWeight>;
using Cell = CellImpl<EdgeWeight, EdgeDuration>;
using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration>;
CellStorageImpl() {}
@@ -304,24 +316,27 @@ template <storage::Ownership Ownership> class CellStorageImpl
<< " Number of unconnected nodes is " << number_of_unconneced;
}
// Set weight offsets and calculate total storage size
WeightOffset weight_offset = 0;
// Set cell values offsets and calculate total storage size
ValueOffset value_offset = 0;
for (auto &cell : cells)
{
cell.weight_offset = weight_offset;
weight_offset += cell.num_source_nodes * cell.num_destination_nodes;
cell.value_offset = value_offset;
value_offset += cell.num_source_nodes * cell.num_destination_nodes;
}
weights.resize(weight_offset + 1, INVALID_EDGE_WEIGHT);
weights.resize(value_offset + 1, INVALID_EDGE_WEIGHT);
durations.resize(value_offset + 1, MAXIMAL_EDGE_DURATION);
}
template <typename = std::enable_if<Ownership == storage::Ownership::View>>
CellStorageImpl(Vector<EdgeWeight> weights_,
Vector<EdgeDuration> durations_,
Vector<NodeID> source_boundary_,
Vector<NodeID> destination_boundary_,
Vector<CellData> cells_,
Vector<std::uint64_t> level_to_cell_offset_)
: weights(std::move(weights_)), source_boundary(std::move(source_boundary_)),
: weights(std::move(weights_)), durations(std::move(durations_)),
source_boundary(std::move(source_boundary_)),
destination_boundary(std::move(destination_boundary_)), cells(std::move(cells_)),
level_to_cell_offset(std::move(level_to_cell_offset_))
{
@@ -336,6 +351,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
BOOST_ASSERT(cell_index < cells.size());
return ConstCell{cells[cell_index],
weights.data(),
durations.data(),
source_boundary.empty() ? nullptr : source_boundary.data(),
destination_boundary.empty() ? nullptr : destination_boundary.data()};
}
@@ -348,8 +364,11 @@ template <storage::Ownership Ownership> class CellStorageImpl
const auto offset = level_to_cell_offset[level_index];
const auto cell_index = offset + id;
BOOST_ASSERT(cell_index < cells.size());
return Cell{
cells[cell_index], weights.data(), source_boundary.data(), destination_boundary.data()};
return Cell{cells[cell_index],
weights.data(),
durations.data(),
source_boundary.data(),
destination_boundary.data()};
}
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
@@ -359,6 +378,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
private:
Vector<EdgeWeight> weights;
Vector<EdgeDuration> durations;
Vector<NodeID> source_boundary;
Vector<NodeID> destination_boundary;
Vector<CellData> cells;
+2
View File
@@ -55,6 +55,7 @@ template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, detail::CellStorageImpl<Ownership> &storage)
{
storage::serialization::read(reader, storage.weights);
storage::serialization::read(reader, storage.durations);
storage::serialization::read(reader, storage.source_boundary);
storage::serialization::read(reader, storage.destination_boundary);
storage::serialization::read(reader, storage.cells);
@@ -66,6 +67,7 @@ inline void write(storage::io::FileWriter &writer,
const detail::CellStorageImpl<Ownership> &storage)
{
storage::serialization::write(writer, storage.weights);
storage::serialization::write(writer, storage.durations);
storage::serialization::write(writer, storage.source_boundary);
storage::serialization::write(writer, storage.destination_boundary);
storage::serialization::write(writer, storage.cells);
@@ -30,7 +30,13 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
{
route_rule =
(qi::lit("alternatives=") >
qi::bool_[ph::bind(&engine::api::RouteParameters::alternatives, qi::_r1) = qi::_1]) |
(qi::uint_[ph::bind(&engine::api::RouteParameters::number_of_alternatives, qi::_r1) =
qi::_1,
ph::bind(&engine::api::RouteParameters::alternatives, qi::_r1) =
qi::_1 > 0] |
qi::bool_[ph::bind(&engine::api::RouteParameters::number_of_alternatives, qi::_r1) =
qi::_1,
ph::bind(&engine::api::RouteParameters::alternatives, qi::_r1) = qi::_1])) |
(qi::lit("continue_straight=") >
(qi::lit("default") |
qi::bool_[ph::bind(&engine::api::RouteParameters::continue_straight, qi::_r1) =
-1
View File
@@ -14,7 +14,6 @@
#include <cerrno>
#include <cstring>
#include <cstring>
#include <tuple>
#include <type_traits>
+48 -1
View File
@@ -7,8 +7,13 @@
#include "storage/io.hpp"
#include <cmath>
#include <cstdint>
#if USE_STXXL_LIBRARY
#include <stxxl/vector>
#endif
namespace osrm
{
namespace storage
@@ -58,6 +63,7 @@ inline void write(storage::io::FileWriter &writer, const util::DeallocatingVecto
writer.WriteFrom(vec.bucket_list.back(), last_block_size);
}
#if USE_STXXL_LIBRARY
template <typename T> inline void read(storage::io::FileReader &reader, stxxl::vector<T> &vec)
{
auto size = reader.ReadOne<std::uint64_t>();
@@ -78,6 +84,7 @@ inline void write(storage::io::FileWriter &writer, const stxxl::vector<T> &vec)
writer.WriteOne<T>(vec[idx]);
}
}
#endif
template <typename T> void read(io::FileReader &reader, std::vector<T> &data)
{
@@ -104,7 +111,47 @@ template <typename T> void write(io::FileWriter &writer, const util::vector_view
{
const auto count = data.size();
writer.WriteElementCount64(count);
return writer.WriteFrom(data.data(), count);
writer.WriteFrom(data.data(), count);
}
template <> inline void read<bool>(io::FileReader &reader, util::vector_view<bool> &data)
{
const auto count = reader.ReadElementCount64();
BOOST_ASSERT(data.size() == count);
for (const auto index : util::irange<std::uint64_t>(0, count))
{
data[index] = reader.ReadOne<bool>();
}
}
template <> inline void write<bool>(io::FileWriter &writer, const util::vector_view<bool> &data)
{
const auto count = data.size();
writer.WriteElementCount64(count);
for (const auto index : util::irange<std::uint64_t>(0, count))
{
writer.WriteOne<bool>(data[index]);
}
}
template <> inline void read<bool>(io::FileReader &reader, std::vector<bool> &data)
{
const auto count = reader.ReadElementCount64();
BOOST_ASSERT(data.size() == count);
for (const auto index : util::irange<std::uint64_t>(0, count))
{
data[index] = reader.ReadOne<bool>();
}
}
template <> inline void write<bool>(io::FileWriter &writer, const std::vector<bool> &data)
{
const auto count = data.size();
writer.WriteElementCount64(count);
for (const auto index : util::irange<std::uint64_t>(0, count))
{
writer.WriteOne<bool>(data[index]);
}
}
}
}
+4
View File
@@ -23,6 +23,7 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
"NAME_ID_LIST",
"COMPONENT_ID_LIST",
"TRAVEL_MODE_LIST",
"CLASSES_LIST",
"CH_GRAPH_NODE_LIST",
"CH_GRAPH_EDGE_LIST",
"COORDINATE_LIST",
@@ -61,6 +62,7 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
"MLD_PARTITION",
"MLD_CELL_TO_CHILDREN",
"MLD_CELL_WEIGHTS",
"MLD_CELL_DURATIONS",
"MLD_CELL_SOURCE_BOUNDARY",
"MLD_CELL_DESTINATION_BOUNDARY",
"MLD_CELLS",
@@ -78,6 +80,7 @@ struct DataLayout
NAME_ID_LIST,
COMPONENT_ID_LIST,
TRAVEL_MODE_LIST,
CLASSES_LIST,
CH_GRAPH_NODE_LIST,
CH_GRAPH_EDGE_LIST,
COORDINATE_LIST,
@@ -116,6 +119,7 @@ struct DataLayout
MLD_PARTITION,
MLD_CELL_TO_CHILDREN,
MLD_CELL_WEIGHTS,
MLD_CELL_DURATIONS,
MLD_CELL_SOURCE_BOUNDARY,
MLD_CELL_DESTINATION_BOUNDARY,
MLD_CELLS,
+99
View File
@@ -0,0 +1,99 @@
#ifndef OSRM_UTIL_BIT_RANGE_HPP
#define OSRM_UTIL_BIT_RANGE_HPP
#include "util/msb.hpp"
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>
namespace osrm
{
namespace util
{
namespace detail
{
template <typename T> std::size_t countOnes(T value)
{
static_assert(std::is_unsigned<T>::value, "Only unsigned types allowed");
std::size_t number_of_ones = 0;
while (value > 0)
{
auto index = msb(value);
value = value & ~(T{1} << index);
number_of_ones++;
}
return number_of_ones;
}
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__))
inline std::size_t countOnes(std::uint8_t value)
{
return __builtin_popcount(std::uint32_t{value});
}
inline std::size_t countOnes(std::uint16_t value)
{
return __builtin_popcount(std::uint32_t{value});
}
inline std::size_t countOnes(unsigned int value) { return __builtin_popcount(value); }
inline std::size_t countOnes(unsigned long value) { return __builtin_popcountl(value); }
inline std::size_t countOnes(unsigned long long value) { return __builtin_popcountll(value); }
#endif
}
// Investigate if we can replace this with
// http://www.boost.org/doc/libs/1_64_0/libs/dynamic_bitset/dynamic_bitset.html
template <typename DataT>
class BitIterator : public boost::iterator_facade<BitIterator<DataT>,
const std::size_t,
boost::forward_traversal_tag,
const std::size_t>
{
typedef boost::iterator_facade<BitIterator<DataT>,
const std::size_t,
boost::forward_traversal_tag,
const std::size_t>
base_t;
public:
typedef typename base_t::value_type value_type;
typedef typename base_t::difference_type difference_type;
typedef typename base_t::reference reference;
typedef std::random_access_iterator_tag iterator_category;
explicit BitIterator() : m_value(0) {}
explicit BitIterator(const DataT x) : m_value(std::move(x)) {}
private:
void increment()
{
auto index = msb(m_value);
m_value = m_value & ~(DataT{1} << index);
}
difference_type distance_to(const BitIterator &other) const
{
return detail::countOnes(m_value) - detail::countOnes(other.m_value);
}
bool equal(const BitIterator &other) const { return m_value == other.m_value; }
reference dereference() const
{
BOOST_ASSERT(m_value > 0);
return msb(m_value);
}
friend class ::boost::iterator_core_access;
DataT m_value;
};
// Returns range over all 1 bits of value
template <typename T> auto makeBitRange(const T value)
{
return boost::make_iterator_range(BitIterator<T>{value}, BitIterator<T>{});
}
}
}
#endif
+24 -1
View File
@@ -27,6 +27,29 @@ struct ConcurrentIDMap
std::unordered_map<KeyType, ValueType, HashType> data;
mutable UpgradableMutex mutex;
ConcurrentIDMap() = default;
ConcurrentIDMap(ConcurrentIDMap &&other)
{
if (this != &other)
{
ScopedWriterLock other_lock{other.mutex};
ScopedWriterLock lock{mutex};
data = std::move(other.data);
}
}
ConcurrentIDMap &operator=(ConcurrentIDMap &&other)
{
if (this != &other)
{
ScopedWriterLock other_lock{other.mutex};
ScopedWriterLock lock{mutex};
data = std::move(other.data);
}
return *this;
}
const ValueType ConcurrentFindOrAdd(const KeyType &key)
{
{
@@ -54,4 +77,4 @@ struct ConcurrentIDMap
} // util
} // osrm
#endif // CONCURRENT_ID_MAP_HPP
#endif // CONCURRENT_ID_MAP_HPP
+6 -2
View File
@@ -258,8 +258,12 @@ template <typename ElementT> class DeallocatingVector
DeallocatingVector(DeallocatingVector &other) = delete;
DeallocatingVector &operator=(DeallocatingVector &other) = delete;
// moving is fine
DeallocatingVector(DeallocatingVector &&other) = default;
DeallocatingVector &operator=(DeallocatingVector &&other) = default;
DeallocatingVector(DeallocatingVector &&other) { swap(other); }
DeallocatingVector &operator=(DeallocatingVector &&other)
{
swap(other);
return *this;
}
~DeallocatingVector() { clear(); }
+2 -1
View File
@@ -46,7 +46,8 @@ inline void print(const engine::guidance::RouteStep &step)
std::cout << ")";
}
std::cout << "] name[" << step.name_id << "]: " << step.name << " Ref: " << step.ref
<< " Pronunciation: " << step.pronunciation << "Destination: " << step.destinations;
<< " Pronunciation: " << step.pronunciation << "Destination: " << step.destinations
<< "Exits: " << step.exits;
}
inline void print(const std::vector<engine::guidance::RouteStep> &steps)
@@ -1,7 +1,7 @@
#ifndef OSRM_GEOJSON_DEBUG_POLICY_TOOLKIT_HPP
#define OSRM_GEOJSON_DEBUG_POLICY_TOOLKIT_HPP
#include "extractor/external_memory_node.hpp"
#include "extractor/query_node.hpp"
#include "util/coordinate.hpp"
#include "util/json_container.hpp"
+11 -12
View File
@@ -1,7 +1,6 @@
#ifndef GRAPH_LOADER_HPP
#define GRAPH_LOADER_HPP
#include "extractor/external_memory_node.hpp"
#include "extractor/node_based_edge.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/query_node.hpp"
@@ -50,7 +49,7 @@ NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
coordinates.resize(number_of_nodes);
osm_node_ids.reserve(number_of_nodes);
extractor::ExternalMemoryNode current_node;
extractor::QueryNode current_node;
for (NodeID i = 0; i < number_of_nodes; ++i)
{
file_reader.ReadInto(&current_node, 1);
@@ -58,18 +57,18 @@ NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
coordinates[i].lon = current_node.lon;
coordinates[i].lat = current_node.lat;
osm_node_ids.push_back(current_node.node_id);
}
if (current_node.barrier)
{
*barriers = i;
++barriers;
}
auto num_barriers = file_reader.ReadElementCount64();
for (auto index = 0UL; index < num_barriers; ++index)
{
*barriers++ = file_reader.ReadOne<NodeID>();
}
if (current_node.traffic_lights)
{
*traffic_signals = i;
++traffic_signals;
}
auto num_lights = file_reader.ReadElementCount64();
for (auto index = 0UL; index < num_lights; ++index)
{
*traffic_signals++ = file_reader.ReadOne<NodeID>();
}
return number_of_nodes;
+3 -1
View File
@@ -39,7 +39,7 @@ class EntryClass
using FlagBaseType = std::uint32_t;
public:
EntryClass();
constexpr EntryClass() : enabled_entries_flags(0) {}
// we are hiding the access to the flags behind a protection wall, to make sure the bit logic
// isn't tempered with. zero based indexing
@@ -72,6 +72,8 @@ static_assert(std::is_trivially_copyable<EntryClass>::value,
} // namespace guidance
} // namespace utilr
constexpr const util::guidance::EntryClass EMPTY_ENTRY_CLASS{};
} // namespace osrm
// make Entry Class hasbable
+38 -4
View File
@@ -44,9 +44,11 @@ template <typename SuffixTable>
inline bool requiresNameAnnounced(const std::string &from_name,
const std::string &from_ref,
const std::string &from_pronunciation,
const std::string &from_exits,
const std::string &to_name,
const std::string &to_ref,
const std::string &to_pronunciation,
const std::string &to_exits,
const SuffixTable &suffix_table)
{
// first is empty and the second is not
@@ -129,16 +131,34 @@ inline bool requiresNameAnnounced(const std::string &from_name,
const auto pronunciation_changes = from_pronunciation != to_pronunciation;
return !obvious_change || needs_announce || pronunciation_changes;
// when exiting onto ramps, we need to be careful about exit numbers. These can often be only
// assigned to the first part of the ramp
//
// a . . b . c . . d
// ` e . . f
//
// could assign the exit number to `be` when exiting `abcd` instead of the full ramp.
//
// Issuing a new-name instruction here would result in the turn assuming the short segment to be
// irrelevant and remove the exit number in a collapse scenario. We don't want to issue any
// instruction from be-ef, since we only loose the exit number. So we want to make sure that we
// don't just loose an exit number, when exits change
const auto exits_change = from_exits != to_exits;
const auto looses_exit = (names_are_equal && !from_exits.empty() && to_exits.empty());
return !obvious_change || needs_announce || pronunciation_changes ||
(exits_change && !looses_exit);
}
// Overload without suffix checking
inline bool requiresNameAnnounced(const std::string &from_name,
const std::string &from_ref,
const std::string &from_pronunciation,
const std::string &from_exits,
const std::string &to_name,
const std::string &to_ref,
const std::string &to_pronunciation)
const std::string &to_pronunciation,
const std::string &to_exits)
{
// Dummy since we need to provide a SuffixTable but do not have the data for it.
// (Guidance Post-Processing does not keep the suffix table around at the moment)
@@ -148,8 +168,15 @@ inline bool requiresNameAnnounced(const std::string &from_name,
bool isSuffix(const std::string &) const { return false; }
} static const table;
return requiresNameAnnounced(
from_name, from_ref, from_pronunciation, to_name, to_ref, to_pronunciation, table);
return requiresNameAnnounced(from_name,
from_ref,
from_pronunciation,
from_exits,
to_name,
to_ref,
to_pronunciation,
to_exits,
table);
}
inline bool requiresNameAnnounced(const NameID from_name_id,
@@ -163,9 +190,13 @@ inline bool requiresNameAnnounced(const NameID from_name_id,
return requiresNameAnnounced(name_table.GetNameForID(from_name_id).to_string(),
name_table.GetRefForID(from_name_id).to_string(),
name_table.GetPronunciationForID(from_name_id).to_string(),
name_table.GetExitsForID(from_name_id).to_string(),
//
name_table.GetNameForID(to_name_id).to_string(),
name_table.GetRefForID(to_name_id).to_string(),
name_table.GetPronunciationForID(to_name_id).to_string(),
name_table.GetExitsForID(to_name_id).to_string(),
//
suffix_table);
// FIXME: converts StringViews to strings since the name change heuristics mutates in place
}
@@ -180,8 +211,11 @@ inline bool requiresNameAnnounced(const NameID from_name_id,
return requiresNameAnnounced(name_table.GetNameForID(from_name_id).to_string(),
name_table.GetRefForID(from_name_id).to_string(),
name_table.GetPronunciationForID(from_name_id).to_string(),
name_table.GetExitsForID(from_name_id).to_string(),
//
name_table.GetNameForID(to_name_id).to_string(),
name_table.GetRefForID(to_name_id).to_string(),
name_table.GetExitsForID(to_name_id).to_string(),
name_table.GetPronunciationForID(to_name_id).to_string());
// FIXME: converts StringViews to strings since the name change heuristics mutates in place
}
+6 -1
View File
@@ -3,11 +3,14 @@
#include "util/log.hpp"
#include <stxxl/mng>
#ifndef _WIN32
#include <sys/resource.h>
#endif
#if USE_STXXL_LIBRARY
#include <stxxl/mng>
#endif
namespace osrm
{
namespace util
@@ -15,6 +18,7 @@ namespace util
inline void DumpSTXXLStats()
{
#if USE_STXXL_LIBRARY
#if STXXL_VERSION_MAJOR > 1 || (STXXL_VERSION_MAJOR == 1 && STXXL_VERSION_MINOR >= 4)
auto manager = stxxl::block_manager::get_instance();
util::Log() << "STXXL: peak bytes used: " << manager->get_maximum_allocation();
@@ -23,6 +27,7 @@ inline void DumpSTXXLStats()
#warning STXXL 1.4+ recommended - STXXL memory summary will not be available
util::Log() << "STXXL: memory summary not available, needs STXXL 1.4 or higher";
#endif
#endif
}
inline void DumpMemoryStats()
+14 -5
View File
@@ -3,6 +3,7 @@
#include <boost/assert.hpp>
#include <climits>
#include <cstdint>
#include <utility>
@@ -26,16 +27,24 @@ template <typename T> std::size_t msb(T value)
return msb - 1;
}
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)) && __x86_64__
inline std::size_t msb(std::uint64_t v)
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__))
inline std::size_t msb(unsigned long long v)
{
BOOST_ASSERT(v > 0);
return 63UL - __builtin_clzl(v);
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned long long) - 1;
return MSB_INDEX - __builtin_clzll(v);
}
inline std::size_t msb(std::uint32_t v)
inline std::size_t msb(unsigned long v)
{
BOOST_ASSERT(v > 0);
return 31UL - __builtin_clz(v);
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned long) - 1;
return MSB_INDEX - __builtin_clzl(v);
}
inline std::size_t msb(unsigned int v)
{
BOOST_ASSERT(v > 0);
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned int) - 1;
return MSB_INDEX - __builtin_clz(v);
}
#endif
}
+1 -1
View File
@@ -33,9 +33,9 @@ class NameTable
// This class provides a limited view over all the string data we serialize out.
// The following functions are a subset of what is available.
// See the data facades for they provide full access to this serialized string data.
// (at time of writing this: get{Name,Ref,Pronunciation,Destinations}ForID(name_id);)
util::StringView GetNameForID(const NameID id) const;
util::StringView GetDestinationsForID(const NameID id) const;
util::StringView GetExitsForID(const NameID id) const;
util::StringView GetRefForID(const NameID id) const;
util::StringView GetPronunciationForID(const NameID id) const;
+7 -2
View File
@@ -1,6 +1,7 @@
#ifndef NODE_BASED_GRAPH_HPP
#define NODE_BASED_GRAPH_HPP
#include "extractor/class_data.hpp"
#include "extractor/guidance/road_classification.hpp"
#include "extractor/node_based_edge.hpp"
#include "util/dynamic_graph.hpp"
@@ -35,10 +36,12 @@ struct NodeBasedEdgeData
bool startpoint,
bool restricted,
extractor::TravelMode travel_mode,
extractor::ClassData classes,
const LaneDescriptionID lane_description_id)
: weight(weight), duration(duration), edge_id(edge_id), name_id(name_id),
reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint),
restricted(restricted), travel_mode(travel_mode), lane_description_id(lane_description_id)
restricted(restricted), travel_mode(travel_mode), classes(classes),
lane_description_id(lane_description_id)
{
}
@@ -52,6 +55,7 @@ struct NodeBasedEdgeData
bool startpoint : 1;
bool restricted : 1;
extractor::TravelMode travel_mode : 4;
extractor::ClassData classes;
LaneDescriptionID lane_description_id;
extractor::guidance::RoadClassification road_classification;
@@ -59,7 +63,7 @@ struct NodeBasedEdgeData
{
return (reversed == other.reversed) && (roundabout == other.roundabout) &&
(circular == other.circular) && (startpoint == other.startpoint) &&
(travel_mode == other.travel_mode) &&
(travel_mode == other.travel_mode) && (classes == other.classes) &&
(road_classification == other.road_classification) &&
(restricted == other.restricted);
}
@@ -89,6 +93,7 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
output_edge.data.circular = input_edge.circular;
output_edge.data.name_id = input_edge.name_id;
output_edge.data.travel_mode = input_edge.travel_mode;
output_edge.data.classes = input_edge.classes;
output_edge.data.startpoint = input_edge.startpoint;
output_edge.data.restricted = input_edge.restricted;
output_edge.data.road_classification = input_edge.road_classification;
+5 -5
View File
@@ -108,7 +108,7 @@ template <typename T, std::size_t Bits, storage::Ownership Ownership> class Pack
// C++14 does not allow operator[] to be constexpr, this is fixed in C++17.
static /* constexpr */ std::array<WordT, BLOCK_ELEMENTS> initialize_lower_mask()
{
std::array<WordT, BLOCK_ELEMENTS> lower_mask{};
std::array<WordT, BLOCK_ELEMENTS> lower_mask;
const WordT mask = (1ULL << Bits) - 1;
auto offset = 0;
@@ -124,7 +124,7 @@ template <typename T, std::size_t Bits, storage::Ownership Ownership> class Pack
static /* constexpr */ std::array<WordT, BLOCK_ELEMENTS> initialize_upper_mask()
{
std::array<WordT, BLOCK_ELEMENTS> upper_mask{};
std::array<WordT, BLOCK_ELEMENTS> upper_mask;
const WordT mask = (1ULL << Bits) - 1;
auto offset = 0;
@@ -148,7 +148,7 @@ template <typename T, std::size_t Bits, storage::Ownership Ownership> class Pack
static /* constexpr */ std::array<std::uint8_t, BLOCK_ELEMENTS> initialize_lower_offset()
{
std::array<std::uint8_t, WORD_BITS> lower_offset{};
std::array<std::uint8_t, WORD_BITS> lower_offset;
auto offset = 0;
for (auto element_index = 0u; element_index < BLOCK_ELEMENTS; element_index++)
@@ -163,7 +163,7 @@ template <typename T, std::size_t Bits, storage::Ownership Ownership> class Pack
static /* constexpr */ std::array<std::uint8_t, BLOCK_ELEMENTS> initialize_upper_offset()
{
std::array<std::uint8_t, BLOCK_ELEMENTS> upper_offset{};
std::array<std::uint8_t, BLOCK_ELEMENTS> upper_offset;
auto offset = 0;
for (auto element_index = 0u; element_index < BLOCK_ELEMENTS; element_index++)
@@ -186,7 +186,7 @@ template <typename T, std::size_t Bits, storage::Ownership Ownership> class Pack
static /* constexpr */ std::array<std::uint8_t, BLOCK_ELEMENTS> initialize_word_offset()
{
std::array<std::uint8_t, BLOCK_ELEMENTS> word_offset{};
std::array<std::uint8_t, BLOCK_ELEMENTS> word_offset;
auto offset = 0;
for (auto element_index = 0u; element_index < BLOCK_ELEMENTS; element_index++)
+12 -69
View File
@@ -22,11 +22,14 @@ namespace util
template <unsigned BLOCK_SIZE = 16, storage::Ownership Ownership = storage::Ownership::Container>
class RangeTable;
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, Ownership> &table);
namespace serialization
{
template <unsigned BlockSize, storage::Ownership Ownership>
void write(storage::io::FileWriter &writer, const util::RangeTable<BlockSize, Ownership> &table);
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, Ownership> &table);
template <unsigned BlockSize, storage::Ownership Ownership>
void read(storage::io::FileReader &reader, util::RangeTable<BlockSize, Ownership> &table);
}
/**
* Stores adjacent ranges in a compressed format.
@@ -45,9 +48,6 @@ template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
using OffsetContainerT = util::ViewOrVector<unsigned, Ownership>;
using RangeT = range<unsigned>;
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
friend std::istream &operator>><>(std::istream &in, RangeTable &table);
RangeTable() : sum_lengths(0) {}
// for loading from shared memory
@@ -141,33 +141,6 @@ template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
sum_lengths = lengths_prefix_sum;
}
void Write(storage::io::FileWriter &filewriter)
{
auto number_of_blocks = diff_blocks.size();
filewriter.WriteElementCount64(number_of_blocks);
filewriter.WriteOne(sum_lengths);
filewriter.WriteFrom(block_offsets.data(), number_of_blocks);
filewriter.WriteFrom(diff_blocks.data(), number_of_blocks);
}
void Read(storage::io::FileReader &filereader)
{
auto number_of_blocks = filereader.ReadElementCount64();
// read total length
filereader.ReadInto(&sum_lengths, 1);
block_offsets.resize(number_of_blocks);
diff_blocks.resize(number_of_blocks);
// read block offsets
filereader.ReadInto(block_offsets.data(), number_of_blocks);
// read blocks
filereader.ReadInto(diff_blocks.data(), number_of_blocks);
}
inline RangeT GetRange(const unsigned id) const
{
BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
@@ -204,6 +177,11 @@ template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
return irange(begin_idx, end_idx);
}
friend void serialization::write<BLOCK_SIZE, Ownership>(storage::io::FileWriter &writer,
const RangeTable &table);
friend void serialization::read<BLOCK_SIZE, Ownership>(storage::io::FileReader &reader,
RangeTable &table);
private:
inline unsigned PrefixSumAtIndex(int index, const BlockT &block) const;
@@ -227,41 +205,6 @@ unsigned RangeTable<BLOCK_SIZE, Ownership>::PrefixSumAtIndex(int index, const Bl
return sum;
}
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, Ownership> &table)
{
// write number of block
const unsigned number_of_blocks = table.diff_blocks.size();
out.write((char *)&number_of_blocks, sizeof(unsigned));
// write total length
out.write((char *)&table.sum_lengths, sizeof(unsigned));
// write block offsets
out.write((char *)table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
// write blocks
out.write((char *)table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
return out;
}
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, Ownership> &table)
{
// read number of block
unsigned number_of_blocks;
in.read((char *)&number_of_blocks, sizeof(unsigned));
// read total length
in.read((char *)&table.sum_lengths, sizeof(unsigned));
table.block_offsets.resize(number_of_blocks);
table.diff_blocks.resize(number_of_blocks);
// read block offsets
in.read((char *)table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
// read blocks
in.read((char *)table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
return in;
}
}
}
+17
View File
@@ -3,6 +3,7 @@
#include "util/dynamic_graph.hpp"
#include "util/packed_vector.hpp"
#include "util/range_table.hpp"
#include "util/static_graph.hpp"
#include "storage/io.hpp"
@@ -14,6 +15,22 @@ namespace util
{
namespace serialization
{
template <unsigned BlockSize, storage::Ownership Ownership>
void write(storage::io::FileWriter &writer, const util::RangeTable<BlockSize, Ownership> &table)
{
writer.WriteOne(table.sum_lengths);
storage::serialization::write(writer, table.block_offsets);
storage::serialization::write(writer, table.diff_blocks);
}
template <unsigned BlockSize, storage::Ownership Ownership>
void read(storage::io::FileReader &reader, util::RangeTable<BlockSize, Ownership> &table)
{
table.sum_lengths = reader.ReadOne<unsigned>();
storage::serialization::read(reader, table.block_offsets);
storage::serialization::read(reader, table.diff_blocks);
}
template <typename T, std::size_t Bits, storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Bits, Ownership> &vec)
{
+26
View File
@@ -0,0 +1,26 @@
#ifndef OSRM_STATIC_ASSERT_HPP
#define OSRM_STATIC_ASSERT_HPP
#include <type_traits>
namespace osrm
{
namespace util
{
template <typename It, typename Value> inline void static_assert_iter_value()
{
using IterValueType = typename std::iterator_traits<It>::value_type;
static_assert(std::is_same<IterValueType, Value>::value, "");
}
template <typename It, typename Category> inline void static_assert_iter_category()
{
using IterCategoryType = typename std::iterator_traits<It>::iterator_category;
static_assert(std::is_base_of<Category, IterCategoryType>::value, "");
}
} // ns util
} // ns osrm
#endif // OSRM_STATIC_ASSERT_HPP

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