Compare commits

...

163 Commits

Author SHA1 Message Date
Patrick Niklaus 6f745b40d0 Fix fingerprint for names file on 5.7 2017-05-29 17:11:59 +00:00
Patrick Niklaus 8789b4bee9 Update changelog and bump version 2017-05-29 15:15:28 +00:00
Patrick Niklaus 7000cfa472 Don't copy the object on WriteOne 2017-05-29 15:12:52 +00:00
Patrick Niklaus b29cbd3711 Fix unit-test 2017-05-29 15:12:52 +00:00
Daniel Patterson 1454d6d7d0 Use FileWriter for better error handling when writing name data. 2017-05-29 15:12:50 +00:00
Daniel Patterson 3cf8835552 Use FileWriter for writing LeafNode data to improve error handling. 2017-05-29 15:11:29 +00:00
Patrick Niklaus c7293f2024 Bump version to 5.7.2 2017-05-24 16:49:03 +00:00
Patrick Niklaus ddc8aed25d Fix formating 2017-05-24 16:47:14 +00:00
Michael Krasnyk 5f7410057c Fix OSRM_ASSERT_MSG compilation fail in Release mode 2017-05-24 16:36:21 +00:00
Patrick Niklaus d55d46e64e Add missing header after cherry-pick 2017-05-24 16:14:06 +00:00
Michael Krasnyk a83150d311 Place reverse entering_via_edge in the front of intersection_view 2017-05-24 15:52:00 +00:00
Michael Krasnyk b073bf36f3 Added example for roundabout overlapping 2017-05-24 15:47:58 +00:00
Daniel J. Hofmann aaea94f776 Asserts Valid Iterators in Roundabout Exit Invalidation, see #4024 2017-05-24 15:44:28 +00:00
Patrick Niklaus 055079192c Bump version to 5.7.1 2017-05-23 17:20:02 +00:00
Patrick Niklaus c542fc2087 Fix formating after cherry-pick 2017-05-23 16:25:26 +00:00
Patrick Niklaus 64b9b6e888 Accidentally included a un-releated test case from master 2017-05-23 16:24:58 +00:00
Michael Krasnyk c58052ca04 Adjust CHANGELOG and the test description 2017-05-23 16:02:00 +00:00
Michael Krasnyk df4d1cb9e6 Change order of guidance post-processing, fix #4030 2017-05-23 16:00:38 +00:00
Daniel J. Hofmann 3349964b96 Updates Changelog 2017-05-19 12:27:32 +02:00
Daniel J. Hofmann 443ebc2551 Applies max turn weight for turns onto restricted weights: no need for custom penalty 2017-05-19 12:22:31 +02:00
Daniel J. Hofmann e6b1e3564a Prevents possible overflow in applying a turn penalty onto restricted roads 2017-05-19 12:22:31 +02:00
Moritz Kobitzsch 3aeb39ba95 fix continue_straight interaction with bearing specification 2017-05-19 12:22:31 +02:00
Daniel J. Hofmann 51fbb4fcbd Fixes Table not checking for valid phantom nodes
We failed to check if we could actually find phantom nodes for all
coordinates in the table plugin, leading to corrupt internal state.

```
curl 'http://localhost:5000/table/v1/car/7.4151,43.7305;7.4222,43.7368?radiuses=0;'
```

```
[assert][140505627227904] /tmp/osrm-backend/include/engine/routing_algorithms/routing_base.hpp:68
in: void osrm::engine::routing_algorithms::insertNodesInHeap(osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>::ManyToManyQueryHeap&, const osrm::engine::PhantomNode&) [with bool DIRECTION = false; osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>::ManyToManyQueryHeap = osrm::util::BinaryHeap<unsigned int, unsigned int, int, osrm::engine::ManyToManyHeapData, osrm::util::UnorderedMapStorage<unsigned int, int> >]: phantom_node.IsValid()
terminate called without an active exception
```
2017-05-19 12:22:31 +02:00
Michael Krasnyk f618531cbb Add response code to test result values 2017-05-19 12:22:31 +02:00
Patrick Niklaus 3f737fce46 Update changelog 2017-05-16 16:21:36 +00:00
Patrick Niklaus 11df411da7 Fix weight value for alley 2017-05-16 16:20:46 +00:00
Patrick Niklaus 5f208b913c Add regression test 2017-05-16 16:20:46 +00:00
Patrick Niklaus 3131bffe11 Fix bicycle turn penalties 2017-05-16 16:20:46 +00:00
Michael Krasnyk 4f3a7c1ec3 Adjust method and function names 2017-05-11 09:36:04 +00:00
Michael Krasnyk 321d1988a0 Disable nodes with invalid segments 2017-05-11 09:36:02 +00:00
Michael Krasnyk b707fcdadc Add response codes of trip and routability queries 2017-05-11 09:16:01 +00:00
Patrick Niklaus 4285660c72 Update changelog 2017-05-05 22:14:50 +00:00
Michael Krasnyk 111e689b09 Added test with an empty CSV file 2017-05-05 22:13:57 +00:00
Michael Krasnyk ebbb497af2 Hide qi namespace alias 2017-05-05 22:13:57 +00:00
Michael Krasnyk dd9ad9fa08 Remove generate-edge-lookup argument in feature tests 2017-05-05 22:13:57 +00:00
Michael Krasnyk dc55edbeb1 Add zero file size check 2017-05-05 22:13:57 +00:00
Michael Krasnyk 1c59563c9c Print diagnostic information to avoid boost cryptic errors 2017-05-05 22:13:57 +00:00
Michael Krasnyk f4e1f6a752 Use mapped_file_source for CSV files 2017-05-05 22:13:57 +00:00
Patrick Niklaus 8c1e014d42 For the cyclability profile add alley penalties 2017-05-05 17:05:37 +00:00
Patrick Niklaus b27fa42b0a Add failing test case for alleys 2017-05-05 17:05:28 +00:00
Patrick Niklaus 73e008e1b0 Regenerate docs 2017-05-05 08:50:22 +00:00
Patrick Niklaus 45fe4b80dd Fix docs for radius 2017-05-05 08:50:07 +00:00
Patrick Niklaus 65732db266 Fix overloaded parameter docs 2017-05-05 08:49:51 +00:00
Patrick Niklaus 55a7e1082f Disable TOC 2017-05-05 08:49:42 +00:00
Patrick Niklaus 34d5ba8fdd Update changelog 2017-05-04 21:08:28 +00:00
Michael Krasnyk ec26756084 Updated assertions to catch negative duration values for weights > 0
but still clamping negative duration values at 0 without checking weights
2017-05-04 21:02:28 +00:00
Michael Krasnyk 0f55f24bfe Use rectified linear unit to prevent negative duration values 2017-05-04 21:02:17 +00:00
Patrick Niklaus 07f2c8fd4c Regenerate API docs 2017-05-03 15:22:28 +00:00
Patrick Niklaus 3289d53617 Update nodejs docs to document the constructor better 2017-05-03 15:22:11 +00:00
Michael Krasnyk 1ea5e44094 Adjusted to PR comments 2017-05-03 15:21:47 +00:00
Michael Krasnyk ee208cd450 Fix incorrect exit turn invalidation 2017-05-03 15:21:36 +00:00
Patrick Niklaus 4370fd126d Final version bump 2017-04-21 08:49:00 +00:00
Patrick Niklaus 15a2fdd1f8 Update changelog 2017-04-20 13:58:29 +00:00
Patrick Niklaus 0eedcf69bc Fix checking columns if route is not specified 2017-04-20 13:52:23 +00:00
Patrick Niklaus 62abea30f5 Apply traffic light penalty also for non-turns 2017-04-20 13:52:11 +00:00
Michael Krasnyk 3364be1860 Fix incorrect weight fallback for distance-based weights 2017-04-20 13:51:59 +00:00
Patrick Niklaus a5eeca9b51 Bump version to RC3 2017-04-18 17:09:49 +00:00
Michael Krasnyk 1a09ff6005 Don't remove the last original coordinate during tiding 2017-04-18 13:36:28 +00:00
Patrick Niklaus 2794a52902 Remove boost::make_unique to fix travis node builds 2017-04-13 21:18:08 +00:00
Patrick Niklaus cb796e4cfc Use .gitignore default instead of .npmignore 2017-04-13 21:17:58 +00:00
Patrick Niklaus 522ec4fc2e Restructure travis build 2017-04-13 21:17:45 +00:00
Michael Krasnyk 15dc5899b0 Use total angle for turn instruction if entry step has large distance 2017-04-12 23:32:12 +00:00
Patrick Niklaus 7e932ffbc3 Bump package version 2017-04-12 22:58:58 +00:00
Patrick Niklaus 810596bb83 Install node version as well 2017-04-12 20:28:19 +00:00
Patrick Niklaus acabf0075c Only use three jobs for node builds 2017-04-12 20:28:05 +00:00
Patrick Niklaus 1ed72db210 Use nvm instead of travis node_js key
This fixes issues on container builds that would always use
node 6 even when 4 was specified.
2017-04-12 20:27:53 +00:00
Patrick Niklaus 6bdf95dfb4 Change version to RC1 2017-04-12 14:58:51 +00:00
Patrick Niklaus 785ae89cd8 Update changelog 2017-04-12 14:58:25 +00:00
Patrick Niklaus 16680191de Enable 5.7 branch in travis 2017-04-12 14:28:37 +00:00
Michael Krasnyk 59b70c4d11 Make CoreCH SearchEngineData inherited from CH one
this allows to keep a single Algorithm template parameter in internal
interfaces as

template <typename Algorithm>
search(SearchEngineData<Algorithm> &,
       const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &, ...)
2017-04-12 10:54:09 +00:00
Michael Krasnyk f96bae40ac Remove unused {forward,reverse}_heap_2 in MLD engine data 2017-04-12 10:54:09 +00:00
Michael Krasnyk ba974c73bf Remove CoreCH heaps 2017-04-12 10:54:09 +00:00
Michael Krasnyk e498ad3ee7 Make explicit fallback to CH heaps in CoreCH algorithms 2017-04-12 10:54:09 +00:00
Michael Krasnyk 1de031ed06 Remove {forward,reverse}_core_heap arguments from search interface 2017-04-12 10:54:09 +00:00
Patrick Niklaus d6ac924b94 Use Date.now() 2017-04-11 22:33:38 +00:00
Patrick Niklaus ee24473cbb Always print node version 2017-04-11 22:33:38 +00:00
Patrick Niklaus c19a3cec1c Fix build syntax 2017-04-11 22:33:38 +00:00
Patrick Niklaus f3694be1a0 Override install and after_sucess 2017-04-11 22:33:38 +00:00
Patrick Niklaus 306d86ce58 Add missing semi-colon 2017-04-11 22:33:38 +00:00
Patrick Niklaus 2c001b63a5 Port timer script to JS 2017-04-11 22:33:38 +00:00
Patrick Niklaus e162dda836 Don't use bc 2017-04-11 22:33:38 +00:00
Patrick Niklaus 10c532bd4c Revert "Skip cucumber tests for publish builds"
This reverts commit 3f8160c156.
2017-04-11 22:33:38 +00:00
Patrick Niklaus c8a7bc1d6a Revert "Don't build unit tests for publishing job"
This reverts commit eb0bd378ae.
2017-04-11 22:33:38 +00:00
Patrick Niklaus 9ca3c69b49 Don't build unit tests for publishing job 2017-04-11 22:33:38 +00:00
Patrick Niklaus d1cf8c1fd5 Skip cucumber tests for publish builds 2017-04-11 22:33:38 +00:00
Patrick Niklaus 018742f50f Constrain the number of jobs on container builds 2017-04-11 22:33:38 +00:00
Patrick Niklaus b82d21f856 Install yarn when not there 2017-04-11 22:33:38 +00:00
Patrick Niklaus cfaadf198f Attempt sudo:false build matrix for node 2017-04-11 22:33:38 +00:00
Michael Krasnyk 6698b5e07e Use fallbacks counter to print a single warning message 2017-04-11 14:55:56 +00:00
Michael Krasnyk 37794a5e8a Change traffic CSV field value from weight to rate
and make the value required.

If the weight name is 'duration' than the rate value
can be computed as speed / 3.6

Issue: https://github.com/Project-OSRM/osrm-backend/issues/3823
2017-04-11 14:55:56 +00:00
Patrick Niklaus a88fef2937 Implement distance pruning for MLD as well 2017-04-10 17:25:55 +00:00
Patrick Niklaus da474a16a9 Fix formating 2017-04-10 17:25:02 +00:00
Patrick Niklaus 59bbfeb67f Buffer turn data on disk to save memory 2017-04-10 17:25:02 +00:00
Patrick Niklaus 4e9e2ed5bd Emit a notification when turning on a ferry and don't merge step 2017-04-07 15:29:53 +00:00
Moritz Kobitzsch e0593c7ca2 add failing test for 3762 2017-04-07 15:29:53 +00:00
Daniel J. Hofmann 1f69df0d89 We need bash for the install script 2017-04-07 14:48:57 +02:00
Patrick Niklaus 05706879a0 Less is more: Don't force any specific build configuration 2017-04-07 14:48:57 +02:00
Patrick Niklaus 7e49b36198 Add script to fall back to source build 2017-04-07 14:48:57 +02:00
Patrick Niklaus 56bcb491d3 Bump package version to latest.6 2017-04-07 10:08:36 +00:00
Patrick Niklaus f4e2bd848d Fixed breaking publishing due to node-cmake upgrade 2017-04-07 08:54:52 +00:00
Daniel J. Hofmann 0cf96314a3 Documents frontend quick start in Readme 2017-04-07 06:56:01 +00:00
Patrick Niklaus 91e24cab9e Bump package version to latest.5 2017-04-06 20:54:24 +00:00
Patrick Niklaus 288155ead0 Fix formating 2017-04-06 15:42:38 +00:00
Patrick Niklaus 85454857d3 Use default move function 2017-04-06 15:42:38 +00:00
Patrick Niklaus fe50f6590a Fix formating 2017-04-06 15:42:38 +00:00
Patrick Niklaus 2da5da3f16 Don't leak ownership in partition/files 2017-04-06 15:42:38 +00:00
Patrick Niklaus 446c865415 Dont leak ownership in extractor::files 2017-04-06 15:42:38 +00:00
Patrick Niklaus 0072bf0c59 Move to forward declare header 2017-04-06 15:42:38 +00:00
Patrick Niklaus 4ec7ca29f1 Fix formating 2017-04-06 15:42:38 +00:00
Patrick Niklaus d94017dfae No shared_memory_wrapper, (De)SerializeVector 2017-04-06 15:42:38 +00:00
Patrick Niklaus dce0ce0e17 Fix readGraph to not use UseSharedMemory 2017-04-06 15:42:38 +00:00
Patrick Niklaus d61102e255 Fix compilation of rtree benchmark 2017-04-06 15:42:38 +00:00
Patrick Niklaus 7f6e0c478b Split QueryNode into coordinates and osm id 2017-04-06 15:42:38 +00:00
Patrick Niklaus 786a3d8919 Read multi level graph to view 2017-04-06 15:42:38 +00:00
Patrick Niklaus ef3fcdc6e6 Refactor graph writing code in contractor 2017-04-06 15:42:38 +00:00
Patrick Niklaus 90c194fc81 Refactor turn description into own file 2017-04-06 15:42:38 +00:00
Patrick Niklaus 5ed686a17b Add generic graph serialization 2017-04-06 15:42:38 +00:00
Patrick Niklaus 4e3009260c Load data directly into CellStorageView 2017-04-06 15:42:38 +00:00
Patrick Niklaus c87ce2dede Load data directly into MLPView 2017-04-06 15:42:38 +00:00
Patrick Niklaus 99a87b4c83 Change serialisation of .geometries file. 2017-04-06 15:42:38 +00:00
Patrick Niklaus 3f5fc1e897 Read segment data directly into shm 2017-04-06 15:42:38 +00:00
Patrick Niklaus 97d1de1beb Pull turn data up into server 2017-04-06 15:42:38 +00:00
Patrick Niklaus d7e1c9c09c Refactor turn data into own class 2017-04-06 15:42:38 +00:00
Patrick Niklaus 865111bca9 Split partition serialization logic 2017-04-06 15:42:38 +00:00
Patrick Niklaus 08d62cd5e3 Separate serialization and files in extractor 2017-04-06 15:42:38 +00:00
Daniel J. Hofmann 603e2ee7de Adapts bindings to node-cmake v2, resolves #3879 2017-04-06 15:26:54 +02:00
Michael Krasnyk 98948989d0 implement MLD map matching 2017-04-06 11:17:23 +00:00
Michael Krasnyk 1aa8cc3b65 make getPathDistance algorithm-independent 2017-04-06 11:17:23 +00:00
Michael Krasnyk c487d1307e enable map matching in MLD 2017-04-06 11:17:23 +00:00
Michael Krasnyk 604f4957f7 correctly fail on unimplemented map matching feature 2017-04-06 11:17:23 +00:00
Michael Krasnyk 7726576bb7 use ADL and explicit instantiation for map matching 2017-04-06 11:17:23 +00:00
Michael Krasnyk cf17a3a4c3 PR review adjustments 2017-04-06 10:36:40 +02:00
Michael Krasnyk 0972ec9115 remove CH-related part of loops forcing 2017-04-06 10:36:40 +02:00
Michael Krasnyk f660ae30dc use explicit instantiation of shortestPathSearch 2017-04-06 10:36:40 +02:00
Michael Krasnyk 2766c24b42 prefer smaller legs for equal weights in shortest path plugin 2017-04-06 10:36:40 +02:00
Michael Krasnyk cab83555e1 add loops forcing to MLD search 2017-04-06 10:36:40 +02:00
Michael Krasnyk 48a098a9c7 implement MLD shortest path plugin 2017-04-06 10:36:40 +02:00
Michael Krasnyk a1fa1c610c enable "via" MLD tests 2017-04-06 10:36:40 +02:00
Michael Krasnyk 905ca69301 add Algorithm parameter to SearchEngineData 2017-04-06 10:36:40 +02:00
Michael Krasnyk d66cc125aa make first heaps algorithm-aware 2017-04-06 10:36:40 +02:00
Michael Krasnyk 3fc0fc65f9 don't disable algorithms explicitly 2017-04-06 10:36:40 +02:00
Michael Krasnyk 8c64b01d67 itroduce ADL via algorithm specific ch, corech and mld namespaces 2017-04-06 10:36:40 +02:00
Michael Krasnyk 2566f64c34 fix unused variable warning 2017-04-06 10:36:40 +02:00
Patrick Niklaus 8cd40b9e90 Bump backed version to latest.4 2017-04-05 11:38:49 +00:00
Patrick Niklaus 45df8568b6 Fix formating 2017-04-05 11:22:39 +00:00
Patrick Niklaus 0da041477b Adjust generation counted array for PR comments 2017-04-05 11:22:39 +00:00
Patrick Niklaus 272ea9b92e Fix test compilation 2017-04-05 11:22:39 +00:00
Patrick Niklaus 571681d019 Use array heap 2017-04-05 11:22:39 +00:00
Patrick Niklaus 9b614c6057 Add generation counted storage 2017-04-05 11:22:39 +00:00
Patrick Niklaus 721f319909 Don't scan back clique arcs 2017-04-05 11:22:39 +00:00
Patrick Niklaus a3621f3655 [skip ci] Bump package version to latest.3 2017-04-04 23:03:04 +00:00
Pepijn Schoen 789311abd6 Remove osrm namespace indication where possible, wrap out shared_memory_ownership 2017-04-04 17:00:36 +00:00
Pepijn Schoen 091a495632 clang-format 2017-04-04 17:00:36 +00:00
Pepijn Schoen 16665aeb00 Renaming of MemorySetting > Ownership 2017-04-04 17:00:36 +00:00
Pepijn Schoen d6e56c38d5 Rename SharedMemoryWrapper to vector_view 2017-04-04 17:00:36 +00:00
Pepijn Schoen 87874006c7 rename to vector_view, replace some missing ShM occurences 2017-04-04 17:00:36 +00:00
Pepijn Schoen 703588b684 clang-format 2017-04-04 17:00:36 +00:00
Pepijn Schoen b21ee1b63b Fixed regression 2017-04-04 17:00:36 +00:00
Pepijn Schoen 427437d49b Use a one-time defined generic signature for SharedMemoryVectors 2017-04-04 17:00:36 +00:00
Pepijn Schoen 01deefc3bc First pass at adjustment for comments 2017-04-04 17:00:36 +00:00
Pepijn Schoen 157ca9161f clang-format 2017-04-04 17:00:36 +00:00
Pepijn Schoen 266e65e6d2 Replace bool for using shared memory with MemorySetting enum 2017-04-04 17:00:36 +00:00
Daniel J. Hofmann 70b3962c35 NodeJS Binding Tests
Does not run the nodejs tests in sanitized builds. We'd have to

    export LD_PRELOAD='/usr/lib/x86_64-linux-gnu/libasan.so.2'

the asan lib. But it seems like our Clang from mason does not like the
system's libasan. Also we'd need a suppression file for v8 and node.
2017-04-04 16:57:44 +00:00
183 changed files with 5419 additions and 4343 deletions
+2
View File
@@ -7,6 +7,8 @@
#############################
osrm-deps
.ycm_extra_conf.py
# Compiled source #
###################
*.com
-10
View File
@@ -1,10 +0,0 @@
*
!README.md
!CHANGELOG.md
!CONTRIBUTING.MD
!LICENCE.TXT
!package.json
!example
!lib/*.js
!profiles/*
!profiles/lib/*
+132 -23
View File
@@ -7,8 +7,9 @@ git:
sudo: required
dist: trusty
nodejs:
node_js:
- "4"
- "6"
notifications:
email: false
@@ -16,6 +17,7 @@ notifications:
branches:
only:
- master
- "5.7"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@@ -36,6 +38,8 @@ env:
- CCACHE_VERSION=3.3.1
- CMAKE_VERSION=3.7.2
- MASON="$(pwd)/scripts/mason.sh"
- ENABLE_NODE_BINDINGS=On
- NODE="4"
matrix:
fast_finish: true
@@ -45,12 +49,14 @@ matrix:
# Debug Builds
- os: linux
compiler: "gcc-6-debug"
compiler: "gcc-6-debug-cov-asan"
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
after_success:
- bash <(curl -s https://codecov.io/bash)
- os: linux
compiler: "clang-4.0-debug"
@@ -61,12 +67,12 @@ matrix:
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
compiler: "mason-linux-debug-santize"
compiler: "mason-linux-debug-asan"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON ENABLE_NODE_BINDINGS=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
# Release Builds
- os: linux
@@ -75,7 +81,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
- os: linux
compiler: "gcc-6-release"
@@ -104,6 +110,8 @@ matrix:
compiler: "mason-osx-release"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON
after_success:
- ./scripts/travis/publish.sh
# Disabled because of CI slowness
#- os: linux
@@ -132,11 +140,112 @@ matrix:
#- 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']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Node build jobs. These skip running the tests.
- os: linux
sudo: false
compiler: "node-4-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-4-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-6-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-6-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON PUBLISH_NODE_BINDINGS=On JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
before_install:
- source $NVM_DIR/nvm.sh
- nvm install $NODE
- nvm use $NODE
- node --version
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
export JOBS=$((`nproc` + 1))
if [[ -z $JOBS ]]; then
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
export JOBS=$((`nproc` + 1))
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
export JOBS=$((`sysctl -n hw.ncpu` + 1))
fi
fi
- |
if [ -n "${RUN_CLANG_FORMAT}" ]; then
@@ -144,8 +253,10 @@ before_install:
fi
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
export JOBS=$((`sysctl -n hw.ncpu` + 1))
sudo mdutil -i off /
fi
- |
if [[ ! -f $(which yarn) ]]; then
npm install -g yarn
fi
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
@@ -173,15 +284,17 @@ before_install:
fi
fi
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
- export OSRM_INSTALL_DIR="$(pwd)/install-osrm"
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- mkdir ${OSRM_BUILD_DIR}
install:
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
./scripts/check_taginfo.py taginfo.json profiles/car.lua
fi
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
@@ -191,7 +304,8 @@ install:
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
-DBUILD_TOOLS=ON \
-DENABLE_CCACHE=ON
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- echo "travis_fold:start:MAKE"
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
@@ -201,10 +315,11 @@ install:
- sudo make install
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
sudo ldconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${OSRM_INSTALL_DIR}/lib
fi
- popd
- mkdir example/build && pushd example/build
- export PKG_CONFIG_PATH=${OSRM_INSTALL_DIR}/lib/pkgconfig
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
- make --jobs=${JOBS}
- popd
@@ -223,16 +338,10 @@ script:
- ./unit_tests/util-tests
- ./unit_tests/server-tests
- ./unit_tests/partition-tests
- |
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
npm run nodejs-tests
fi
- popd
- yarn test
after_success:
- |
if [ -n "${ENABLE_COVERAGE}" ]; then
bash <(curl -s https://codecov.io/bash)
fi
- |
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
./scripts/travis/publish.sh
fi
+39 -1
View File
@@ -1,17 +1,55 @@
- Track preprocessing flag in the map matching plugin.
# 5.7.3
- Changes from 5.7.2:
- Bug fixes:
- Fixes 4097: .ramIndex files was able to be truncated siliently
# 5.7.2
- Changes from 5.7.1:
- Bug fixes:
- Fixes segmentation fault caused by the fix for 3977
# 5.7.1
- Changes from 5.7.0:
- Bug fixes:
- Fixes 3995: Negative duration caused by rounding issues.
- Fixes 3977: Fixes exit number in roundabout if starting inside the roundabout
- Fixes 3981: The NodeJS documentation was outdated and incomplete.
- Fixes 4010: Performance regression while parsing CSV files. Now 5x faster.
- Fixes 3919: Turn penalties on the cyclabilty metric were disabled.
- Fixes 3992: Table plugin not checking for valid phantom nodes
- Fixes 4013: `continue_straight` interaction with bearing constraints
- Fixes 4063: Potential overflow in custom profiles for restricted ways
- Fixes 4030: Roundabout edge-case crashes post-processing
# 5.7.0
- Changes from 5.6
- Bug fixes:
- Fixed 505: Invalid distance value for distance as routing weight.
- Fixed 3958: Fix traffic light penalties for non-turns
- Fixed 3933: crash when collapsing instructions
- Algorithm:
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
- Allows for fast metric updates in below a minute on continental sized networks (osrm-customize)
- Plugins supported: `match` and `route`
- Quickstart: `osrm-extract data.osm.pbf`, `osrm-partition data.osrm`, `osrm-customize data.osrm`, `osrm-routed --algorithm=MLD data.osrm`
- NodeJs Bindings
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
- `OSRM` object has new option `algorihtm="CH","CoreCH","MLD"`
- Internals
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
- Files
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
- `osrm-extract` creates new file `.osrm.cnbg` and `.cnbg_to_ebg`
- `osrm-partition` creates new file `.osrm.partition` and `.osrm.cells`
- `osrm-customize` creates new file `.osrm.mldgr`
- Profiles
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
- Map Matching:
- new option `gaps=split|ignore` to enable/disbale track splitting
- new option `tidy=true|false` to simplify traces automatically
# 5.6.3
- Changes from 5.6.0
+3 -1
View File
@@ -55,7 +55,7 @@ endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 7)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION_PATCH 3)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
@@ -303,6 +303,8 @@ endif()
if (ENABLE_SANITIZER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
endif()
# Configuring compilers
+20 -12
View File
@@ -37,27 +37,35 @@ Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
## Quick Start
The easiest and quickest way to setup your own routing engine backend is to use Docker images we provide.
The easiest and quickest way to setup your own routing engine is to use Docker images we provide.
### Using Docker
We base [our Docker images](https://hub.docker.com/r/osrm/osrm-backend/) on Alpine Linux and make sure they are as lightweight as possible.
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
```
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
```
Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
Make requests against the HTTP server
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
Optionally start a user-friendly frontend on port 9966, and open it up in your browser
docker run -p 9966:9966 osrm/osrm-frontend
xdg-open 'http://127.0.0.1:9966'
In case Docker complains about not being able to connect to the Docker daemon make sure you are in the `docker` group.
```
sudo usermod -aG docker $USER
```
sudo usermod -aG docker $USER
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
+627
View File
@@ -0,0 +1,627 @@
# Vendored NodeJs.cmake to bootstrap our C++ build without
# having the user to install Node modules via `npm install`.
#
# Update via: ../node_modules/.bin/ncmake update
# Defaults for standard Node.js builds
set(NODEJS_DEFAULT_URL https://nodejs.org/download/release)
set(NODEJS_DEFAULT_VERSION installed)
set(NODEJS_VERSION_FALLBACK latest)
set(NODEJS_DEFAULT_NAME node)
set(NODEJS_DEFAULT_CHECKSUM SHASUMS256.txt)
set(NODEJS_DEFAULT_CHECKTYPE SHA256)
include(CMakeParseArguments)
# Find a path by walking upward from a base directory until the path is
# found. Sets the variable ${PATH} to False if the path can't
# be determined
function(find_path_parent NAME BASE PATH)
set(ROOT ${BASE})
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
set(DRIVE "^[A-Za-z]?:?/$")
while(NOT ROOT MATCHES ${DRIVE} AND NOT EXISTS ${ROOT}/${NAME})
get_filename_component(ROOT ${ROOT} DIRECTORY)
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
endwhile()
if(ROOT MATCHES ${DRIVE})
set(${PATH} False PARENT_SCOPE)
endif()
endfunction()
# Shortcut for finding standard node module locations
macro(find_nodejs_module NAME BASE PATH)
find_path_parent(node_modules/${NAME} ${BASE} ${PATH})
endmacro()
# Download with a bit of nice output (without spewing progress)
function(download_file URL)
message(STATUS "Downloading: ${URL}")
file(DOWNLOAD
${URL}
${ARGN}
)
endfunction()
# Embedded win_delay_load_hook file so that this file can be copied
# into projects directly (recommended practice)
function(nodejs_generate_delayload_hook OUTPUT)
file(WRITE ${OUTPUT} "")
file(APPEND ${OUTPUT} "/*\n")
file(APPEND ${OUTPUT} " * When this file is linked to a DLL, it sets up a delay-load hook that\n")
file(APPEND ${OUTPUT} " * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe'\n")
file(APPEND ${OUTPUT} " * dynamically. Instead of trying to locate the .exe file it'll just return\n")
file(APPEND ${OUTPUT} " * a handle to the process image.\n")
file(APPEND ${OUTPUT} " *\n")
file(APPEND ${OUTPUT} " * This allows compiled addons to work when node.exe or iojs.exe is renamed.\n")
file(APPEND ${OUTPUT} " */\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "#ifdef _MSC_VER\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "#ifndef DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
file(APPEND ${OUTPUT} "#define DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
file(APPEND ${OUTPUT} "#endif\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "#ifndef WIN32_LEAN_AND_MEAN\n")
file(APPEND ${OUTPUT} "#define WIN32_LEAN_AND_MEAN\n")
file(APPEND ${OUTPUT} "#endif\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "#include <windows.h>\n")
file(APPEND ${OUTPUT} "#include <Shlwapi.h>\n")
file(APPEND ${OUTPUT} "#include <delayimp.h>\n")
file(APPEND ${OUTPUT} "#include <string.h>\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) {\n")
file(APPEND ${OUTPUT} " if (event != dliNotePreLoadLibrary) return NULL;\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " if (_stricmp(info->szDll, \"iojs.exe\") != 0 &&\n")
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.exe\") != 0 &&\n")
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.dll\") != 0)\n")
file(APPEND ${OUTPUT} " return NULL;\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " // Get a handle to the current process executable.\n")
file(APPEND ${OUTPUT} " HMODULE processModule = GetModuleHandle(NULL);\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " // Get the path to the executable.\n")
file(APPEND ${OUTPUT} " TCHAR processPath[_MAX_PATH];\n")
file(APPEND ${OUTPUT} " GetModuleFileName(processModule, processPath, _MAX_PATH);\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " // Get the name of the current executable.\n")
file(APPEND ${OUTPUT} " LPSTR processName = PathFindFileName(processPath);\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " // If the current process is node or iojs, then just return the proccess \n")
file(APPEND ${OUTPUT} " // module.\n")
file(APPEND ${OUTPUT} " if (_stricmp(processName, \"node.exe\") == 0 ||\n")
file(APPEND ${OUTPUT} " _stricmp(processName, \"iojs.exe\") == 0) {\n")
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
file(APPEND ${OUTPUT} " }\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " // If it is another process, attempt to load 'node.dll' from the same \n")
file(APPEND ${OUTPUT} " // directory.\n")
file(APPEND ${OUTPUT} " PathRemoveFileSpec(processPath);\n")
file(APPEND ${OUTPUT} " PathAppend(processPath, \"node.dll\");\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " HMODULE nodeDllModule = GetModuleHandle(processPath);\n")
file(APPEND ${OUTPUT} " if(nodeDllModule != NULL) {\n")
file(APPEND ${OUTPUT} " // This application has a node.dll in the same directory as the executable,\n")
file(APPEND ${OUTPUT} " // use that.\n")
file(APPEND ${OUTPUT} " return (FARPROC) nodeDllModule;\n")
file(APPEND ${OUTPUT} " }\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} " // Fallback to the current executable, which must statically link to \n")
file(APPEND ${OUTPUT} " // node.lib\n")
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
file(APPEND ${OUTPUT} "}\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "PfnDliHook __pfnDliNotifyHook2 = load_exe_hook;\n")
file(APPEND ${OUTPUT} "\n")
file(APPEND ${OUTPUT} "#endif\n")
endfunction()
# Sets up a project to build Node.js native modules
# - Downloads required dependencies and unpacks them to the build directory.
# Internet access is required the first invocation but not after (
# provided the download is successful)
# - Sets up several variables for building against the downloaded
# dependencies
# - Guarded to prevent multiple executions, so a single project hierarchy
# will only call this once
function(nodejs_init)
# Prevents this function from executing more than once
if(NODEJS_INIT)
return()
endif()
# Regex patterns used by the init function for component extraction
set(HEADERS_MATCH "^([A-Fa-f0-9]+)[ \t]+([^-]+)-(headers|v?[0-9.]+)-(headers|v?[0-9.]+)([.]tar[.]gz)$")
set(LIB32_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-x86)?(/)?([^/]*)(.lib)$")
set(LIB64_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-)?(x64/)(.*)(.lib)$")
# Parse function arguments
cmake_parse_arguments(nodejs_init
"" "URL;NAME;VERSION;CHECKSUM;CHECKTYPE" "" ${ARGN}
)
# Allow the download URL to be overridden by command line argument
# NODEJS_URL
if(NODEJS_URL)
set(URL ${NODEJS_URL})
else()
# Use the argument if specified, falling back to the default
set(URL ${NODEJS_DEFAULT_URL})
if(nodejs_init_URL)
set(URL ${nodejs_init_URL})
endif()
endif()
# Allow name to be overridden by command line argument NODEJS_NAME
if(NODEJS_NAME)
set(NAME ${NODEJS_NAME})
else()
# Use the argument if specified, falling back to the default
set(NAME ${NODEJS_DEFAULT_NAME})
if(nodejs_init_NAME)
set(NAME ${nodejs_init_NAME})
endif()
endif()
# Allow the checksum file to be overridden by command line argument
# NODEJS_CHECKSUM
if(NODEJS_CHECKSUM)
set(CHECKSUM ${NODEJS_CHECKSUM})
else()
# Use the argument if specified, falling back to the default
set(CHECKSUM ${NODEJS_DEFAULT_CHECKSUM})
if(nodejs_init_CHECKSUM)
set(CHECKSUM ${nodejs_init_CHECKSUM})
endif()
endif()
# Allow the checksum type to be overriden by the command line argument
# NODEJS_CHECKTYPE
if(NODEJS_CHECKTYPE)
set(CHECKTYPE ${NODEJS_CHECKTYPE})
else()
# Use the argument if specified, falling back to the default
set(CHECKTYPE ${NODEJS_DEFAULT_CHECKTYPE})
if(nodejs_init_CHECKTYPE)
set(CHECKTYPE ${nodejs_init_CHECKTYPE})
endif()
endif()
# Allow the version to be overridden by the command line argument
# NODEJS_VERSION
if(NODEJS_VERSION)
set(VERSION ${NODEJS_VERSION})
else()
# Use the argument if specified, falling back to the default
set(VERSION ${NODEJS_DEFAULT_VERSION})
if(nodejs_init_VERSION)
set(VERSION ${nodejs_init_VERSION})
endif()
endif()
# "installed" is a special version that tries to use the currently
# installed version (determined by running node)
set(NODEJS_INSTALLED False CACHE BOOL "Node.js install status" FORCE)
if(VERSION STREQUAL "installed")
if(NOT NAME STREQUAL ${NODEJS_DEFAULT_NAME})
message(FATAL_ERROR
"'Installed' version identifier can only be used with"
"the core Node.js library"
)
endif()
# Fall back to the "latest" version if node isn't installed
set(VERSION ${NODEJS_VERSION_FALLBACK})
find_program(NODEJS_BINARY NAMES node nodejs)
if(NODEJS_BINARY)
execute_process(
COMMAND ${NODEJS_BINARY} --version
RESULT_VARIABLE INSTALLED_VERSION_RESULT
OUTPUT_VARIABLE INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(INSTALLED_VERSION_RESULT STREQUAL "0")
set(NODEJS_INSTALLED True CACHE BOOL
"Node.js install status" FORCE
)
set(VERSION ${INSTALLED_VERSION})
endif()
endif()
endif()
# Create a temporary download directory
set(TEMP ${CMAKE_CURRENT_BINARY_DIR}/temp)
if(EXISTS ${TEMP})
file(REMOVE_RECURSE ${TEMP})
endif()
file(MAKE_DIRECTORY ${TEMP})
# Unless the target is special version "latest", the parameters
# necessary to construct the root path are known
if(NOT VERSION STREQUAL "latest")
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
# Extract checksums from the existing checksum file
set(CHECKSUM_TARGET ${ROOT}/CHECKSUM)
endif()
# If we're trying to determine the version or we haven't saved the
# checksum file for this version, download it from the specified server
if(VERSION STREQUAL "latest" OR
(DEFINED ROOT AND NOT EXISTS ${ROOT}/CHECKSUM))
if(DEFINED ROOT)
# Clear away the old checksum in case the new one is different
# and/or it fails to download
file(REMOVE ${ROOT}/CHECKSUM)
endif()
file(REMOVE ${TEMP}/CHECKSUM)
download_file(
${URL}/${VERSION}/${CHECKSUM}
${TEMP}/CHECKSUM
INACTIVITY_TIMEOUT 10
STATUS CHECKSUM_STATUS
)
list(GET CHECKSUM_STATUS 0 CHECKSUM_STATUS)
if(CHECKSUM_STATUS GREATER 0)
file(REMOVE ${TEMP}/CHECKSUM)
message(FATAL_ERROR
"Unable to download checksum file"
)
endif()
# Extract checksums from the temporary file
set(CHECKSUM_TARGET ${TEMP}/CHECKSUM)
endif()
# Extract the version, name, header archive and archive checksum
# from the file. This first extract is what defines / specifies the
# actual version number and name.
file(STRINGS
${CHECKSUM_TARGET} HEADERS_CHECKSUM
REGEX ${HEADERS_MATCH}
LIMIT_COUNT 1
)
if(NOT HEADERS_CHECKSUM)
file(REMOVE ${TEMP}/CHECKSUM)
if(DEFINED ROOT)
file(REMOVE ${ROOT}/CHECKSUM)
endif()
message(FATAL_ERROR "Unable to extract header archive checksum")
endif()
string(REGEX MATCH ${HEADERS_MATCH} HEADERS_CHECKSUM ${HEADERS_CHECKSUM})
set(HEADERS_CHECKSUM ${CMAKE_MATCH_1})
set(NAME ${CMAKE_MATCH_2})
if(CMAKE_MATCH_3 STREQUAL "headers")
set(VERSION ${CMAKE_MATCH_4})
else()
set(VERSION ${CMAKE_MATCH_3})
endif()
set(HEADERS_ARCHIVE
${CMAKE_MATCH_2}-${CMAKE_MATCH_3}-${CMAKE_MATCH_4}${CMAKE_MATCH_5}
)
# Make sure that the root directory exists, and that the checksum
# file has been moved over from temp
if(DEFINED ROOT)
set(OLD_ROOT ${ROOT})
endif()
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
if(DEFINED OLD_ROOT AND NOT ROOT STREQUAL "${OLD_ROOT}")
file(REMOVE ${TEMP}/CHECKSUM)
file(REMOVE ${ROOT}/CHECKSUM)
message(FATAL_ERROR "Version/Name mismatch")
endif()
file(MAKE_DIRECTORY ${ROOT})
if(EXISTS ${TEMP}/CHECKSUM)
file(REMOVE ${ROOT}/CHECKSUM)
file(RENAME ${TEMP}/CHECKSUM ${ROOT}/CHECKSUM)
endif()
# Now that its fully resolved, report the name and version of Node.js being
# used
message(STATUS "NodeJS: Using ${NAME}, version ${VERSION}")
# Download the headers for the version being used
# Theoretically, these could be found by searching the installed
# system, but in practice, this can be error prone. They're provided
# on the download servers, so just use the ones there.
if(NOT EXISTS ${ROOT}/include)
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
download_file(
${URL}/${VERSION}/${HEADERS_ARCHIVE}
${TEMP}/${HEADERS_ARCHIVE}
INACTIVITY_TIMEOUT 10
EXPECTED_HASH ${CHECKTYPE}=${HEADERS_CHECKSUM}
STATUS HEADERS_STATUS
)
list(GET HEADERS_STATUS 0 HEADERS_STATUS)
if(HEADER_STATUS GREATER 0)
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
message(FATAL_ERROR "Unable to download Node.js headers")
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xfz ${TEMP}/${HEADERS_ARCHIVE}
WORKING_DIRECTORY ${TEMP}
)
# This adapts the header extraction to support a number of different
# header archive contents in addition to the one used by the
# default Node.js library
unset(NODEJS_HEADERS_PATH CACHE)
find_path(NODEJS_HEADERS_PATH
NAMES src include
PATHS
${TEMP}/${NAME}-${VERSION}-headers
${TEMP}/${NAME}-${VERSION}
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}-headers
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}
${TEMP}/${NODEJS_DEFAULT_NAME}
${TEMP}
NO_DEFAULT_PATH
)
if(NOT NODEJS_HEADERS_PATH)
message(FATAL_ERROR "Unable to find extracted headers folder")
endif()
# Move the headers into a standard location with a standard layout
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
file(REMOVE_RECURSE ${ROOT}/include)
if(EXISTS ${NODEJS_HEADERS_PATH}/include/node)
file(RENAME ${NODEJS_HEADERS_PATH}/include/node ${ROOT}/include)
elseif(EXISTS ${NODEJS_HEADERS_PATH}/src)
file(MAKE_DIRECTORY ${ROOT}/include)
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/src)
file(REMOVE_RECURSE ${ROOT}/include)
message(FATAL_ERROR "Unable to find core headers")
endif()
file(COPY ${NODEJS_HEADERS_PATH}/src/
DESTINATION ${ROOT}/include
)
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/uv/include)
file(REMOVE_RECURSE ${ROOT}/include)
message(FATAL_ERROR "Unable to find libuv headers")
endif()
file(COPY ${NODEJS_HEADERS_PATH}/deps/uv/include/
DESTINATION ${ROOT}/include
)
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/v8/include)
file(REMOVE_RECURSE ${ROOT}/include)
message(FATAL_ERROR "Unable to find v8 headers")
endif()
file(COPY ${NODEJS_HEADERS_PATH}/deps/v8/include/
DESTINATION ${ROOT}/include
)
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/zlib)
file(REMOVE_RECURSE ${ROOT}/include)
message(FATAL_ERROR "Unable to find zlib headers")
endif()
file(COPY ${NODEJS_HEADERS_PATH}/deps/zlib/
DESTINATION ${ROOT}/include
)
endif()
file(REMOVE_RECURSE ${NODEJS_HEADERS_PATH})
unset(NODEJS_HEADERS_PATH CACHE)
endif()
# Only download the libraries on windows, since its the only place
# its necessary. Note, this requires rerunning CMake if moving
# a module from one platform to another (should happen automatically
# with most generators)
if(WIN32)
# Download the win32 library for linking
file(STRINGS
${ROOT}/CHECKSUM LIB32_CHECKSUM
LIMIT_COUNT 1
REGEX ${LIB32_MATCH}
)
if(NOT LIB32_CHECKSUM)
message(FATAL_ERROR "Unable to extract x86 library checksum")
endif()
string(REGEX MATCH ${LIB32_MATCH} LIB32_CHECKSUM ${LIB32_CHECKSUM})
set(LIB32_CHECKSUM ${CMAKE_MATCH_1})
set(LIB32_PATH win-x86)
set(LIB32_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
set(LIB32_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB32_NAME})
if(NOT EXISTS ${ROOT}/${LIB32_PATH})
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
download_file(
${URL}/${VERSION}/${LIB32_TARGET}
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
INACTIVITY_TIMEOUT 10
EXPECTED_HASH ${CHECKTYPE}=${LIB32_CHECKSUM}
STATUS LIB32_STATUS
)
list(GET LIB32_STATUS 0 LIB32_STATUS)
if(LIB32_STATUS GREATER 0)
message(FATAL_ERROR
"Unable to download Node.js windows library (32-bit)"
)
endif()
file(REMOVE_RECURSE ${ROOT}/${LIB32_PATH})
file(MAKE_DIRECTORY ${ROOT}/${LIB32_PATH})
file(RENAME
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
${ROOT}/${LIB32_PATH}/${LIB32_NAME}
)
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
endif()
# Download the win64 library for linking
file(STRINGS
${ROOT}/CHECKSUM LIB64_CHECKSUM
LIMIT_COUNT 1
REGEX ${LIB64_MATCH}
)
if(NOT LIB64_CHECKSUM)
message(FATAL_ERROR "Unable to extract x64 library checksum")
endif()
string(REGEX MATCH ${LIB64_MATCH} LIB64_CHECKSUM ${LIB64_CHECKSUM})
set(LIB64_CHECKSUM ${CMAKE_MATCH_1})
set(LIB64_PATH win-x64)
set(LIB64_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
set(LIB64_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB64_NAME})
if(NOT EXISTS ${ROOT}/${LIB64_PATH})
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
download_file(
${URL}/${VERSION}/${LIB64_TARGET}
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
INACTIVITY_TIMEOUT 10
EXPECTED_HASH ${CHECKTYPE}=${LIB64_CHECKSUM}
STATUS LIB64_STATUS
)
list(GET LIB64_STATUS 0 LIB64_STATUS)
if(LIB64_STATUS GREATER 0)
message(FATAL_ERROR
"Unable to download Node.js windows library (64-bit)"
)
endif()
file(REMOVE_RECURSE ${ROOT}/${LIB64_PATH})
file(MAKE_DIRECTORY ${ROOT}/${LIB64_PATH})
file(RENAME
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
${ROOT}/${LIB64_PATH}/${LIB64_NAME}
)
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
endif()
endif()
# The downloaded headers should always be set for inclusion
list(APPEND INCLUDE_DIRS ${ROOT}/include)
# Look for the NAN module, and add it to the includes
find_nodejs_module(
nan
${CMAKE_CURRENT_SOURCE_DIR}
NODEJS_NAN_DIR
)
if(NODEJS_NAN_DIR)
list(APPEND INCLUDE_DIRS ${NODEJS_NAN_DIR})
endif()
# Under windows, we need a bunch of libraries (due to the way
# dynamic linking works)
if(WIN32)
# Generate and use a delay load hook to allow the node binary
# name to be changed while still loading native modules
set(DELAY_LOAD_HOOK ${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c)
nodejs_generate_delayload_hook(${DELAY_LOAD_HOOK})
set(SOURCES ${DELAY_LOAD_HOOK})
# Necessary flags to get delayload working correctly
list(APPEND LINK_FLAGS
"-IGNORE:4199"
"-DELAYLOAD:iojs.exe"
"-DELAYLOAD:node.exe"
"-DELAYLOAD:node.dll"
)
# Core system libraries used by node
list(APPEND LIBRARIES
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
odbc32.lib Shlwapi.lib DelayImp.lib
)
# Also link to the node stub itself (downloaded above)
if(CMAKE_CL_64)
list(APPEND LIBRARIES ${ROOT}/${LIB64_PATH}/${LIB64_NAME})
else()
list(APPEND LIBRARIES ${ROOT}/${LIB32_PATH}/${LIB32_NAME})
endif()
else()
# Non-windows platforms should use these flags
list(APPEND DEFINITIONS _LARGEFILE_SOURCE _FILE_OFFSET_BITS=64)
endif()
# Special handling for OSX / clang to allow undefined symbols
# Define is required by node on OSX
if(APPLE)
list(APPEND LINK_FLAGS "-undefined dynamic_lookup")
list(APPEND DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
endif()
# Export all settings for use as arguments in the rest of the build
set(NODEJS_VERSION ${VERSION} PARENT_SCOPE)
set(NODEJS_SOURCES ${SOURCES} PARENT_SCOPE)
set(NODEJS_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
set(NODEJS_LIBRARIES ${LIBRARIES} PARENT_SCOPE)
set(NODEJS_LINK_FLAGS ${LINK_FLAGS} PARENT_SCOPE)
set(NODEJS_DEFINITIONS ${DEFINITIONS} PARENT_SCOPE)
# Prevents this function from executing more than once
set(NODEJS_INIT TRUE PARENT_SCOPE)
endfunction()
# Helper function for defining a node module
# After nodejs_init, all of the settings and dependencies necessary to do
# this yourself are defined, but this helps make sure everything is configured
# correctly. Feel free to use it as a model to do this by hand (or to
# tweak this configuration if you need something custom).
function(add_nodejs_module NAME)
# Validate name parameter (must be a valid C identifier)
string(MAKE_C_IDENTIFIER ${NAME} ${NAME}_SYMBOL_CHECK)
if(NOT "${NAME}" STREQUAL "${${NAME}_SYMBOL_CHECK}")
message(FATAL_ERROR
"Module name must be a valid C identifier. "
"Suggested alternative: '${${NAME}_SYMBOL_CHECK}'"
)
endif()
# Make sure node is initialized (variables set) before defining the module
if(NOT NODEJS_INIT)
message(FATAL_ERROR
"Node.js has not been initialized. "
"Call nodejs_init before adding any modules"
)
endif()
# In order to match node-gyp, we need to build into type specific folders
# ncmake takes care of this, but be sure to set CMAKE_BUILD_TYPE yourself
# if invoking CMake directly
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
message(FATAL_ERROR
"Configuration type must be specified. "
"Set CMAKE_BUILD_TYPE or use a different generator"
)
endif()
# A node module is a shared library
add_library(${NAME} SHARED ${NODEJS_SOURCES} ${ARGN})
# Add compiler defines for the module
# Two helpful ones:
# MODULE_NAME must match the name of the build library, define that here
# ${NAME}_BUILD is for symbol visibility under windows
string(TOUPPER "${NAME}_BUILD" ${NAME}_BUILD_DEF)
target_compile_definitions(${NAME}
PRIVATE MODULE_NAME=${NAME}
PRIVATE ${${NAME}_BUILD_DEF}
PUBLIC ${NODEJS_DEFINITIONS}
)
# This properly defines includes for the module
target_include_directories(${NAME} PUBLIC ${NODEJS_INCLUDE_DIRS})
# Add link flags to the module
target_link_libraries(${NAME} ${NODEJS_LIBRARIES})
# Set required properties for the module to build properly
# Correct naming, symbol visiblity and C++ standard
set_target_properties(${NAME} PROPERTIES
OUTPUT_NAME ${NAME}
PREFIX ""
SUFFIX ".node"
MACOSX_RPATH ON
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE TRUE
CMAKE_CXX_STANDARD_REQUIRED TRUE
CXX_STANDARD 11
LINK_FLAGS "${NODEJS_LINK_FLAGS}"
)
# Make sure we're buiilding in a build specific output directory
# Only necessary on single-target generators (Make, Ninja)
# Multi-target generators do this automatically
# This (luckily) mirrors node-gyp conventions
if(NOT CMAKE_CONFIGURATION_TYPES)
set_property(TARGET ${NAME} PROPERTY
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BUILD_TYPE}
)
endif()
endfunction()
-587
View File
@@ -1,587 +0,0 @@
# Copyright (c) 2015, Colin Taylor
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# FindNodeJS.cmake CMake module vendored from the node-cmake project (v1.2).
# This script uses CMake 3.1+ features
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0)
message(FATAL_ERROR "FindNodeJS.cmake uses CMake 3.1+ features")
endif()
# Force a build type to be set (ignored on config based generators)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
endif()
# Capture module information
set(NodeJS_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
get_filename_component(NodeJS_MODULE_NAME ${NodeJS_MODULE_PATH} NAME)
# Allow users to specify the installed location of the Node.js package
set(NodeJS_ROOT_DIR "" CACHE PATH
"The root directory of the node.js installed package")
# Allow users to specify that downloaded sources should be used
option(NodeJS_DOWNLOAD "Download the required source files" Off)
# Allow users to force downloading of node packages
option(NodeJS_FORCE_DOWNLOAD "Download the source files every time" Off)
# Allow users to force archive extraction
option(NodeJS_FORCE_EXTRACT "Extract the archive every time" Off)
# Make libc++ the default when compiling with clang
option(NodeJS_USE_CLANG_STDLIB "Use libc++ when compiling with clang" On)
if(APPLE)
set(NodeJS_USE_CLANG_STDLIB On CACHE BOOL "" FORCE)
endif()
if(WIN32)
# Allow users to specify that the executable should be downloaded
option(NodeJS_DOWNLOAD_EXECUTABLE
"Download matching executable if available" Off
)
endif()
# Try to find the node.js executable
# The node executable under linux may not be the correct program
find_program(NodeJS_EXECUTABLE
NAMES node
PATHS ${NodeJS_ROOT_DIR}
PATH_SUFFIXES nodejs node
)
set(NodeJS_VALIDATE_EXECUTABLE 1)
if(NodeJS_EXECUTABLE)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} --version
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} -p "process.platform"
OUTPUT_VARIABLE NodeJS_INSTALLED_PLATFORM
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} -p "process.arch"
OUTPUT_VARIABLE NodeJS_INSTALLED_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
# If node isn't the node.js binary, try the nodejs binary
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
find_program(NodeJS_EXECUTABLE
NAMES nodejs
PATHS ${NodeJS_ROOT_DIR}
PATH_SUFFIXES nodejs node
)
set(NodeJS_VALIDATE_EXECUTABLE 1)
if(NodeJS_EXECUTABLE)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} --version
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
message(WARNING "Node.js executable could not be found. \
Set NodeJS_ROOT_DIR to the installed location of the executable or \
install Node.js to its default location.")
endif()
endif()
# Determine if a variant is set in the components
list(APPEND NodeJS_OTHER_COMPONENTS
X64 IA32 ARM WIN32 LINUX DARWIN
)
set(NodeJS_COMPONENTS_CONTAINS_VARIANT False)
foreach(NodeJS_COMPONENT ${NodeJS_FIND_COMPONENTS})
list(FIND NodeJS_OTHER_COMPONENTS ${NodeJS_COMPONENT} NodeJS_OTHER_INDEX)
if(NodeJS_OTHER_INDEX EQUAL -1)
set(NodeJS_COMPONENTS_CONTAINS_VARIANT True)
break()
endif()
endforeach()
# Get the targeted version of Node.js (or one of its derivatives)
if(NOT NodeJS_VERSION)
if(NodeJS_FIND_VERSION)
set(NodeJS_VERSION ${NodeJS_FIND_VERSION})
elseif(NodeJS_INSTALLED_VERSION AND NOT NodeJS_COMPONENTS_CONTAINS_VARIANT)
string(SUBSTRING ${NodeJS_INSTALLED_VERSION} 1 -1 NodeJS_VERSION)
else()
message(FATAL_ERROR "Node.js version is not set. Set the VERSION \
property of the find_package command to the required version of the \
Node.js sources")
endif()
endif()
# Determine the target platform for the compiled module
# Uses several mechanisms in order:
#
# 1. CMake cache (allows overriding on the command line)
# 2. Node architecture when binary is available
# 3. CMake architecture
#
set(NodeJS_PLATFORM "" CACHE STRING "Target node.js platform for module")
if(NOT NodeJS_PLATFORM)
if(NodeJS_EXECUTABLE)
set(NodeJS_PLATFORM ${NodeJS_INSTALLED_PLATFORM})
elseif(WIN32)
set(NodeJS_PLATFORM "win32")
elseif(UNIX)
if(APPLE)
set(NodeJS_PLATFORM "darwin")
else()
set(NodeJS_PLATFORM "linux")
endif()
else()
message(FATAL_ERROR "Node.js platform is not set. Add the platform \
to the find_package components section or set NodeJS_PLATFORM in the \
cache.")
endif()
endif()
# Convenience variables for the platform type
if(NodeJS_PLATFORM STREQUAL "win32")
set(NodeJS_PLATFORM_WIN32 True)
set(NodeJS_PLATFORM_LINUX False)
set(NodeJS_PLATFORM_DARWIN False)
elseif(NodeJS_PLATFORM STREQUAL "linux")
set(NodeJS_PLATFORM_WIN32 False)
set(NodeJS_PLATFORM_LINUX True)
set(NodeJS_PLATFORM_DARWIN False)
elseif(NodeJS_PLATFORM STREQUAL "darwin")
set(NodeJS_PLATFORM_WIN32 False)
set(NodeJS_PLATFORM_LINUX False)
set(NodeJS_PLATFORM_DARWIN True)
endif()
# Determine the target architecture for the compiled module
# Uses several mechanisms in order:
#
# 1. CMake cache (allows overriding on the command line)
# 2. Node architecture when binary is available
# 3. Compiler architecture under MSVC
#
set(NodeJS_ARCH "" CACHE STRING "Target node.js architecture for module")
if(NOT NodeJS_ARCH)
if(NodeJS_EXECUTABLE)
set(NodeJS_ARCH ${NodeJS_INSTALLED_ARCH})
elseif(MSVC)
if(CMAKE_CL_64)
set(NodeJS_ARCH "x64")
else()
set(NodeJS_ARCH "ia32")
endif()
else()
message(FATAL_ERROR "Node.js architecture is not set. Add the \
architecture to the find_package components section or set NodeJS_ARCH \
in the cache.")
endif()
endif()
# Convenience variables for the architecture
if(NodeJS_ARCH STREQUAL "x64")
set(NodeJS_ARCH_X64 True)
set(NodeJS_ARCH_IA32 False)
set(NodeJS_ARCH_ARM False)
elseif(NodeJS_ARCH STREQUAL "ia32")
set(NodeJS_ARCH_X64 False)
set(NodeJS_ARCH_IA32 True)
set(NodeJS_ARCH_ARM False)
elseif(NodeJS_ARCH STREQUAL "arm")
set(NodeJS_ARCH_X64 False)
set(NodeJS_ARCH_IA32 False)
set(NodeJS_ARCH_ARM True)
endif()
# Include helper functions
include(util/NodeJSUtil)
# Default variant name
# Used by the installed header comparison below
set(NodeJS_DEFAULT_VARIANT_NAME "node.js")
# Variables for Node.js artifacts across variants
# Specify all of these variables for each new variant
set(NodeJS_VARIANT_NAME "") # The printable name of the variant
set(NodeJS_VARIANT_BASE "") # A file name safe version of the variant
set(NodeJS_URL "") # The URL for the artifacts
set(NodeJS_SOURCE_PATH "") # The URL path of the source archive
set(NodeJS_CHECKSUM_PATH "") # The URL path of the checksum file
set(NodeJS_CHECKSUM_TYPE "") # The checksum type (algorithm)
set(NodeJS_WIN32_LIBRARY_PATH "") # The URL path of the windows library
set(NodeJS_WIN32_BINARY_PATH "") # The URL path of the windows executable
set(NodeJS_WIN32_LIBRARY_NAME "") # The name of the windows library
set(NodeJS_WIN32_BINARY_NAME "") # The name of the windows executable
set(NodeJS_DEFAULT_INCLUDE True) # Enable default include behavior
set(NodeJS_DEFAULT_LIBS True) # Include the default libraries
set(NodeJS_HAS_WIN32_PREFIX True) # Does the variant use library prefixes
set(NodeJS_HAS_WIN32_BINARY True) # Does the variant have win32 executables
set(NodeJS_HAS_OPENSSL True) # Does the variant include openssl headers
set(NodeJS_HEADER_VERSION 0.12.7) # Version after header-only archives start
set(NodeJS_SHA256_VERSION 0.7.0) # Version after sha256 checksums start
set(NodeJS_PREFIX_VERSION 0.12.7) # Version after windows prefixing starts
set(NodeJS_CXX11R_VERSION 0.12.7) # Version after c++11 is required
set(NodeJS_SOURCE_INCLUDE True) # Use the include paths from a source archive
set(NodeJS_HEADER_INCLUDE False) # Use the include paths from a header archive
set(NodeJS_INCLUDE_PATHS "") # Set of header dirs inside the source archive
set(NodeJS_LIBRARIES "") # The set of libraries to link with addon
set(NodeJS_WIN32_DELAYLOAD "") # Set of executables to delayload on windows
# NodeJS variants
# Selects download target based on configured component
# Include NodeJS last to provide default configurations when omitted
file(
GLOB NodeJS_SUPPORTED_VARIANTS
RELATIVE ${CMAKE_CURRENT_LIST_DIR}/variants
${CMAKE_CURRENT_LIST_DIR}/variants/*
)
foreach(NodeJS_SUPPORTED_VARIANT ${NodeJS_SUPPORTED_VARIANTS})
get_filename_component(NodeJS_SUPPORTED_VARIANT_NAME
${NodeJS_SUPPORTED_VARIANT} NAME_WE
)
if(NOT NodeJS_SUPPORTED_VARIANT_NAME STREQUAL "NodeJS")
include(variants/${NodeJS_SUPPORTED_VARIANT_NAME})
endif()
endforeach()
include(variants/NodeJS)
# Populate version variables, including version components
set(NodeJS_VERSION_STRING "v${NodeJS_VERSION}")
# Populate the remaining version variables
string(REPLACE "." ";" NodeJS_VERSION_PARTS ${NodeJS_VERSION})
list(GET NodeJS_VERSION_PARTS 0 NodeJS_VERSION_MAJOR)
list(GET NodeJS_VERSION_PARTS 1 NodeJS_VERSION_MINOR)
list(GET NodeJS_VERSION_PARTS 2 NodeJS_VERSION_PATCH)
# If the version we're looking for is the version that is installed,
# try finding the required headers. Don't do this under windows (where
# headers are not part of the installed content), when the user has
# specified that headers should be downloaded or when using a variant other
# than the default
if((NOT NodeJS_PLATFORM_WIN32) AND (NOT NodeJS_DOWNLOAD) AND
NodeJS_VARIANT_NAME STREQUAL NodeJS_DEFAULT_VARIANT_NAME AND
NodeJS_INSTALLED_VERSION STREQUAL NodeJS_VERSION_STRING AND
NodeJS_INSTALLED_PLATFORM STREQUAL NodeJS_PLATFORM AND
NodeJS_INSTALLED_ARCH STREQUAL NodeJS_ARCH)
# node.h is really generic and too easy for cmake to find the wrong
# file, so use the directory as a guard, and then just tack it on to
# the actual path
#
# Specifically ran into this under OSX, where python contains a node.h
# that gets found instead
find_path(NodeJS_INCLUDE_PARENT node/node.h)
set(NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_PARENT}/node)
# Under all systems that support this, there are no libraries required
# for linking (symbols are resolved via the main executable at runtime)
set(NodeJS_LIBRARIES "")
# Otherwise, headers and required libraries must be downloaded to the project
# to supplement what is installed
else()
# Create a folder for downloaded artifacts
set(NodeJS_DOWNLOAD_PATH
${CMAKE_CURRENT_BINARY_DIR}/${NodeJS_VARIANT_BASE}
)
set(NodeJS_DOWNLOAD_PATH ${NodeJS_DOWNLOAD_PATH}-${NodeJS_VERSION_STRING})
file(MAKE_DIRECTORY ${NodeJS_DOWNLOAD_PATH})
# Download the checksum file for validating all other downloads
# Conveniently, if this doesn't download correctly, the setup fails
# due to checksum failures
set(NodeJS_CHECKSUM_FILE ${NodeJS_DOWNLOAD_PATH}/CHECKSUM)
nodejs_download(
${NodeJS_URL}/${NodeJS_CHECKSUM_PATH}
${NodeJS_CHECKSUM_FILE}
${NodeJS_FORCE_DOWNLOAD}
)
file(READ ${NodeJS_CHECKSUM_FILE} NodeJS_CHECKSUM_DATA)
# Download and extract the main source archive
set(NodeJS_SOURCE_FILE ${NodeJS_DOWNLOAD_PATH}/headers.tar.gz)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_SOURCE_PATH} NodeJS_SOURCE_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_SOURCE_PATH}
${NodeJS_SOURCE_FILE}
${NodeJS_SOURCE_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
set(NodeJS_HEADER_PATH ${NodeJS_DOWNLOAD_PATH}/src)
nodejs_extract(
${NodeJS_SOURCE_FILE}
${NodeJS_HEADER_PATH}
${NodeJS_FORCE_EXTRACT}
)
# Populate include directories from the extracted source archive
foreach(NodeJS_HEADER_BASE ${NodeJS_INCLUDE_PATHS})
set(NodeJS_INCLUDE_DIR ${NodeJS_HEADER_PATH}/${NodeJS_HEADER_BASE})
if(NOT EXISTS ${NodeJS_INCLUDE_DIR})
message(FATAL_ERROR "Include does not exist: ${NodeJS_INCLUDE_DIR}")
endif()
list(APPEND NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_DIR})
endforeach()
# Download required library files when targeting windows
if(NodeJS_PLATFORM_WIN32)
# Download the windows library
set(NodeJS_WIN32_LIBRARY_FILE
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
)
set(NodeJS_WIN32_LIBRARY_FILE
${NodeJS_WIN32_LIBRARY_FILE}/${NodeJS_WIN32_LIBRARY_NAME}
)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_LIBRARY_PATH}
NodeJS_WIN32_LIBRARY_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_WIN32_LIBRARY_PATH}
${NodeJS_WIN32_LIBRARY_FILE}
${NodeJS_WIN32_LIBRARY_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
list(APPEND NodeJS_LIBRARIES ${NodeJS_WIN32_LIBRARY_FILE})
# If provided, download the windows executable
if(NodeJS_WIN32_BINARY_PATH AND
NodeJS_DOWNLOAD_EXECUTABLE)
set(NodeJS_WIN32_BINARY_FILE
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
)
set(NodeJS_WIN32_BINARY_FILE
${NodeJS_WIN32_BINARY_FILE}/${NodeJS_WIN32_BINARY_NAME}
)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_BINARY_PATH}
NodeJS_WIN32_BINARY_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_WIN32_BINARY_PATH}
${NodeJS_WIN32_BINARY_FILE}
${NodeJS_WIN32_BINARY_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
endif()
endif()
endif()
# Support windows delay loading
if(NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_LINK_FLAGS /IGNORE:4199)
set(NodeJS_WIN32_DELAYLOAD_CONDITION "")
foreach(NodeJS_WIN32_DELAYLOAD_BINARY ${NodeJS_WIN32_DELAYLOAD})
list(APPEND NodeJS_LINK_FLAGS
/DELAYLOAD:${NodeJS_WIN32_DELAYLOAD_BINARY}
)
list(APPEND NodeJS_WIN32_DELAYLOAD_CONDITION
"_stricmp(info->szDll, \"${NodeJS_WIN32_DELAYLOAD_BINARY}\") != 0"
)
endforeach()
string(REPLACE ";" " &&\n "
NodeJS_WIN32_DELAYLOAD_CONDITION
"${NodeJS_WIN32_DELAYLOAD_CONDITION}"
)
configure_file(
${NodeJS_MODULE_PATH}/src/win_delay_load_hook.c
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c @ONLY
)
list(APPEND NodeJS_ADDITIONAL_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c
)
endif()
# Allow undefined symbols on OSX
if(NodeJS_PLATFORM_DARWIN)
list(APPEND NodeJS_LINK_FLAGS "-undefined dynamic_lookup")
endif()
# Use libc++ when clang is the compiler by default
if(NodeJS_USE_CLANG_STDLIB AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*")
list(APPEND NodeJS_COMPILE_OPTIONS -stdlib=libc++)
endif()
# Require c++11 support after a specific point, but only if the user hasn't
# specified an override
if(NOT NodeJS_CXX_STANDARD)
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION)
set(NodeJS_CXX_STANDARD 11)
else()
set(NodeJS_CXX_STANDARD 98)
endif()
endif()
# Set required definitions
list(APPEND NodeJS_DEFINITIONS BUILDING_NODE_EXTENSION)
if(NodeJS_PLATFORM_DARWIN)
list(APPEND NodeJS_DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
endif()
if(NOT NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_DEFINITIONS
_LARGEFILE_SOURCE
_FILE_OFFSET_BITS=64
)
endif()
function(add_nodejs_module NAME)
# Build a shared library for the module
add_library(${NAME} SHARED ${ARGN} ${NodeJS_ADDITIONAL_SOURCES})
# Include required headers
# Find and include Nan as well (always available as its a
# dependency of this module)
nodejs_find_module_fallback(nan ${CMAKE_CURRENT_SOURCE_DIR} NAN_PATH)
target_include_directories(${NAME}
PUBLIC ${NodeJS_INCLUDE_DIRS}
PUBLIC ${NAN_PATH}
)
# Set module properties
# This ensures proper naming of the module library across all platforms
get_target_property(COMPILE_OPTIONS ${NAME} COMPILE_OPTIONS)
if(NOT COMPILE_OPTIONS)
set(COMPILE_OPTIONS "")
endif()
set(COMPILE_OPTIONS ${COMPILE_OPTIONS} ${NodeJS_COMPILE_OPTIONS})
get_target_property(LINK_FLAGS ${NAME} LINK_FLAGS)
if(NOT LINK_FLAGS)
set(LINK_FLAGS "")
endif()
foreach(NodeJS_LINK_FLAG ${NodeJS_LINK_FLAGS})
set(LINK_FLAGS "${LINK_FLAGS} ${NodeJS_LINK_FLAG}")
endforeach()
set_target_properties(${NAME} PROPERTIES
PREFIX ""
SUFFIX ".node"
MACOSX_RPATH ON
POSITION_INDEPENDENT_CODE TRUE
COMPILE_OPTIONS "${COMPILE_OPTIONS}"
LINK_FLAGS "${LINK_FLAGS}"
CXX_STANDARD_REQUIRED TRUE
CXX_STANDARD ${NodeJS_CXX_STANDARD}
)
# Output the module in a per build type directory
# This makes builds consistent with visual studio and other generators
# that build by configuration
if(NOT CMAKE_CONFIGURATION_TYPES)
set_property(TARGET ${NAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BUILD_TYPE}
)
endif()
# Set any required complier flags
# Mostly used under windows
target_compile_definitions(${NAME} PRIVATE ${NodeJS_DEFINITIONS})
# Link against required NodeJS libraries
target_link_libraries(${NAME} ${NodeJS_LIBRARIES})
endfunction()
# Write out the configuration for node scripts
configure_file(
${NodeJS_MODULE_PATH}/build.json.in
${CMAKE_CURRENT_BINARY_DIR}/build.json @ONLY
)
# Make sure we haven't violated the version-to-standard mapping
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION AND
NodeJS_CXX_STANDARD EQUAL 98)
message(FATAL_ERROR "${NodeJS_VARIANT_NAME} ${NodeJS_VERSION} \
requires C++11 or newer to build")
endif()
# This is a find_package file, handle the standard invocation
include(FindPackageHandleStandardArgs)
set(NodeJS_TARGET "${NodeJS_VARIANT_NAME} ${NodeJS_PLATFORM}/${NodeJS_ARCH}")
find_package_handle_standard_args(NodeJS
FOUND_VAR NodeJS_FOUND
REQUIRED_VARS NodeJS_TARGET NodeJS_INCLUDE_DIRS
VERSION_VAR NodeJS_VERSION
)
# Mark variables that users shouldn't modify
mark_as_advanced(
NodeJS_VALIDATE_EXECUTABLE
NodeJS_OTHER_COMPONENTS
NodeJS_COMPONENTS_CONTAINS_VARIANT
NodeJS_COMPONENT
NodeJS_OTHER_INDEX
NodeJS_VERSION_STRING
NodeJS_VERSION_MAJOR
NodeJS_VERSION_MINOR
NodeJS_VERSION_PATCH
NodeJS_VERSION_TWEAK
NodeJS_PLATFORM
NodeJS_PLATFORM_WIN32
NodeJS_PLATFORM_LINUX
NodeJS_PLATFORM_DARWIN
NodeJS_ARCH
NodeJS_ARCH_X64
NodeJS_ARCH_IA32
NodeJS_ARCH_ARM
NodeJS_DEFAULT_VARIANT_NAME
NodeJS_VARIANT_BASE
NodeJS_VARIANT_NAME
NodeJS_URL
NodeJS_SOURCE_PATH
NodeJS_CHECKSUM_PATH
NodeJS_CHECKSUM_TYPE
NodeJS_WIN32_LIBRARY_PATH
NodeJS_WIN32_BINARY_PATH
NodeJS_WIN32_LIBRARY_NAME
NodeJS_WIN32_BINARY_NAME
NodeJS_DEFAULT_INCLUDE
NodeJS_DEFAULT_LIBS
NodeJS_HAS_WIN32_BINARY
NodeJS_HEADER_VERSION
NodeJS_SHA256_VERISON
NodeJS_PREFIX_VERSION
NodeJS_SOURCE_INCLUDE
NodeJS_HEADER_INCLUDE
NodeJS_INCLUDE_PATHS
NodeJS_WIN32_DELAYLOAD
NodeJS_DOWNLOAD_PATH
NodeJS_CHECKSUM_FILE
NodeJS_CHECKSUM_DATA
NodeJS_SOURCE_FILE
NodeJS_SOURCE_CHECKSUM
NodeJS_HEADER_PATH
NodeJS_HEADER_BASE
NodeJS_INCLUDE_DIR
NodeJS_WIN32_LIBRARY_FILE
NodeJS_WIN32_LIBRARY_CHECKSUM
NodeJS_WIN32_BINARY_FILE
NodeJS_WIN32_BINARY_CHECKSUM
NodeJS_NAN_PATH
NodeJS_LINK_FLAGS
NodeJS_COMPILE_OPTIONS
NodeJS_ADDITIONAL_SOURCES
NodeJS_WIN32_DELAYLOAD_CONDITION
NodeJS_WIN32_DELAYLOAD_BINARY
NodeJS_TARGET
)
-10
View File
@@ -1,10 +0,0 @@
{
"build_type": "@CMAKE_BUILD_TYPE@",
"generator": "@CMAKE_GENERATOR@",
"toolset": "@CMAKE_GENERATOR_TOOLSET@",
"platform": "@CMAKE_GENERATOR_PLATFORM@",
"variant": "@NodeJS_VARIANT_BASE@",
"version": "@NodeJS_VERSION@",
"download": "@NodeJS_DOWNLOAD@",
"standard": "@NodeJS_CXX_STANDARD@"
}
-28
View File
@@ -1,28 +0,0 @@
set(GITHUB_API_TOKEN $ENV{GITHUB_API_TOKEN})
set(GITHUB_AUTH "")
if(GITHUB_API_TOKEN)
set(GITHUB_AUTH "?access_token=${GITHUB_API_TOKEN}")
endif()
set(GITHUB_API_URL "https://api.github.com")
function(github_get_rate_limit VAR)
set(RATE_LIMIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/GITHUBRATE)
set(RATE_LIMIT_URL ${GITHUB_API_URL}/rate_limit${GITHUB_AUTH})
nodejs_download(
${RATE_LIMIT_URL}
${RATE_LIMIT_FILE}
ON
)
file(READ ${RATE_LIMIT_FILE} RATE_LIMIT_DATA)
string(REGEX MATCH "\"remaining\": ([0-9]+),"
RATE_LIMIT_MATCH ${RATE_LIMIT_DATA})
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()
mark_as_advanced(
GITHUB_AUTH
GITHUB_API_TOKEN
GITHUB_API_URL
)
-166
View File
@@ -1,166 +0,0 @@
function(nodejs_check_file FILE)
set(MESSAGE "File ${FILE} does not exist or is empty")
if(ARGC GREATER 1)
set(MESSAGE ${ARGV1})
endif()
# Make sure the file has contents
file(READ ${FILE} FILE_CONTENT LIMIT 1 HEX)
if(NOT FILE_CONTENT)
file(REMOVE ${FILE})
message(FATAL_ERROR ${MESSAGE})
endif()
endfunction()
function(nodejs_download URL FILE)
# Function optionally takes a checksum and a checksum type, and
# a force value
# Either can be specified without the other, but checksum must come first
if(ARGC GREATER 2)
set(CHECKSUM ${ARGV2})
if(CHECKSUM STREQUAL "On" OR CHECKSUM STREQUAL "ON" OR
CHECKSUM STREQUAL "True" OR CHECKSUM STREQUAL "TRUE" OR
CHECKSUM STREQUAL "Off" OR CHECKSUM STREQUAL "OFF" OR
CHECKSUM STREQUAL "False" OR CHECKSUM STREQUAL "FALSE")
set(FORCE ${CHECKSUM})
unset(CHECKSUM)
elseif(ARGC GREATER 3)
set(TYPE ${ARGV3})
else()
message(FATAL_ERROR "Checksum type must be specified")
endif()
elseif(ARGC GREATER 4)
set(CHECKSUM ${ARGV2})
set(TYPE ${ARGV3})
set(FORCE ${ARGV4})
endif()
# If the file exists, no need to download it again unless its being forced
if(NOT FORCE AND EXISTS ${FILE})
return()
endif()
# Download the file
message(STATUS "Downloading: ${URL}")
file(DOWNLOAD
${URL}
${FILE}
SHOW_PROGRESS
)
# Make sure the file has contents
nodejs_check_file(${FILE} "Unable to download ${URL}")
# If a checksum is provided, validate the downloaded file
if(CHECKSUM)
message(STATUS "Validating: ${FILE}")
file(${TYPE} ${FILE} DOWNLOAD_CHECKSUM)
message(STATUS "Checksum: ${CHECKSUM}")
message(STATUS "Download: ${DOWNLOAD_CHECKSUM}")
if(NOT CHECKSUM STREQUAL DOWNLOAD_CHECKSUM)
file(REMOVE ${FILE})
message(FATAL_ERROR "Validation failure: ${FILE}")
endif()
endif()
endfunction()
function(nodejs_checksum DATA FILE VAR)
string(REGEX MATCH "([A-Fa-f0-9]+)[\t ]+${FILE}" CHECKSUM_MATCH ${DATA})
if(CMAKE_MATCH_1)
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
else()
message(FATAL_ERROR "Unable to extract file checksum")
endif()
endfunction()
function(nodejs_extract FILE DIR)
# Function optionally takes a force value
if(ARGC GREATER 2)
set(FORCE ${ARGV2})
endif()
# If the archvie has been extracted, no need to extract again unless it
# is being forced
if(NOT FORCE AND EXISTS ${DIR})
return()
endif()
# Make a temporary directory for extracting the output
set(EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/extract)
if(EXISTS ${EXTRACT_DIR})
file(REMOVE_RECURSE ${EXTRACT_DIR})
endif()
file(MAKE_DIRECTORY ${EXTRACT_DIR})
# Extract the archive
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xfz ${FILE}
WORKING_DIRECTORY ${EXTRACT_DIR}
)
# If only one element is extracted, the archive contained a nested
# folder; use the inner folder as the extracted folder
file(GLOB EXTRACT_CHILDREN ${EXTRACT_DIR}/*)
list(LENGTH EXTRACT_CHILDREN NUM_CHILDREN)
set(TARGET_DIR ${EXTRACT_DIR})
if(NUM_CHILDREN EQUAL 1)
list(GET EXTRACT_CHILDREN 0 TARGET_DIR)
endif()
# Move the folder to the target path
if(EXISTS ${DIR})
file(REMOVE_RECURSE ${DIR})
endif()
file(RENAME ${TARGET_DIR} ${DIR})
# Make sure to clean up the extraction folder when the inner folder
# is used
file(REMOVE_RECURSE ${EXTRACT_DIR})
endfunction()
function(nodejs_find_module NAME BASE PATH)
# Find a node module using the same search path that require uses
# without needing a node binary
set(ROOT ${BASE})
set(DRIVE "^[A-Za-z]?:?/$")
# Walk up the directory tree until at the root
while(NOT ROOT MATCHES ${DRIVE} AND NOT
EXISTS ${ROOT}/node_modules/${NAME})
get_filename_component(ROOT ${ROOT} DIRECTORY)
endwhile()
# Operate like the CMake find_* functions, returning NOTFOUND if the
# module can't be found
if(ROOT MATCHES ${DRIVE})
set(${PATH} ${NAME}-NOTFOUND PARENT_SCOPE)
else()
set(${PATH} ${ROOT}/node_modules/${NAME} PARENT_SCOPE)
endif()
endfunction()
macro(nodejs_find_module_fallback NAME BASE PATH)
# Look in the provided path first
# If the module isn't found, try searching from the module
nodejs_find_module(${NAME} ${BASE} ${PATH})
if(NOT ${PATH})
nodejs_find_module(${NAME} ${NodeJS_MODULE_PATH} ${PATH})
endif()
endmacro()
function(nodejs_get_version URL VAR)
set(NWJS_LATEST_RELEASE_URL
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
set(VERSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/VERSION)
nodejs_download(
${URL}
${VERSION_FILE}
ON
)
nodejs_check_file(${VERSION_FILE})
file(READ ${VERSION_FILE} VERSION_DATA)
string(REGEX MATCH "v([0-9]+\.[0-9]+\.[0-9]+)"
VERSION_MATCH ${VERSION_DATA}
)
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()
-81
View File
@@ -1,81 +0,0 @@
set(ELECTRON_VARIANT_BASE "electron")
set(ELECTRON_WIN32_BINARY_NAME "${ELECTRON_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${ELECTRON_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_ELECTRON OR
NodeJS_VARIANT STREQUAL ${ELECTRON_VARIANT_BASE})
if(NodeJS_VERSION STREQUAL "latest")
include(util/Github)
github_get_rate_limit(GITHUB_RATE_LIMIT)
# Handle determining the latest release
# Very complicated, due to electron not following the "latest"
# convention of other variants
set(ELECTRON_LATEST_RELEASE_FILE ${CMAKE_CURRENT_BINARY_DIR}/ELECTRON)
set(ELECTRON_LATEST_RELEASE_URL
${GITHUB_API_URL}/repos/atom/electron/releases/latest${GITHUB_AUTH}
)
if(GITHUB_RATE_LIMIT GREATER 0)
nodejs_download(
${ELECTRON_LATEST_RELEASE_URL}
${ELECTRON_LATEST_RELEASE_FILE}
ON
)
endif()
nodejs_check_file(
${ELECTRON_LATEST_RELEASE_FILE}
"Releases file could not be downloaded, likely \
because github rate limit was exceeded. Wait until the limit \
passes or set GITHUB_API_TOKEN in your environment to a valid \
github developer token."
)
file(READ ${ELECTRON_LATEST_RELEASE_FILE} ELECTRON_LATEST_RELEASE_DATA)
string(REGEX MATCH "\"tag_name\"\: \"v([0-9]+\.[0-9]+\.[0-9]+)\""
ELECTRON_LATEST_RELEASE_MATCH ${ELECTRON_LATEST_RELEASE_DATA})
set(NodeJS_VERSION ${CMAKE_MATCH_1})
endif()
set(NodeJS_VARIANT_NAME "Electron.js")
# SHASUMS of any kind is inaccessible prior to 0.16.0
if(NodeJS_VERSION VERSION_LESS 0.16.0)
message(FATAL_ERROR "Electron is only supported for versions >= 0.16.0")
endif()
# Electron switched to IOJS after 0.25.0
# Probably needs to be bounded on the upper side if/when they switch
# back to node mainline due to iojs-node merge
set(NodeJS_VARIANT_BASE "node")
if(NodeJS_VERSION VERSION_GREATER 0.25.0)
set(NodeJS_VARIANT_BASE "iojs")
endif()
# Url is hard to get, because it will immediately resolve to a CDN
# Extracted from the electron website
set(NodeJS_URL
"https://atom.io/download/atom-shell/v${NodeJS_VERSION}"
)
# Headers become available for IOJS base ONLY!
# Variant base switch above handles this
set(NodeJS_HEADER_VERSION 0.30.1)
# Header only archive uses source style paths
set(NodeJS_DEFAULT_INCLUDE False)
# Hard to determine, but versions seem to start at 16, and SHA256 is
# available
set(NodeJS_SHA256_VERSION 0.15.9)
# C++11 and Prefixing start after the IOJS switch
# Will carry forward after node mainline so no need for upper bound (whew)
set(NodeJS_PREFIX_VERSION 0.25.0)
set(NodeJS_CXX11R_VERSION 0.25.0)
# The executable is not provided on the CDN
# In theory, I could support a BINARY_URL to get this from github
set(NodeJS_HAS_WIN32_BINARY False)
# OpenSSL isn't included in the headers
set(NodeJS_HAS_OPENSSL False)
endif()
-25
View File
@@ -1,25 +0,0 @@
set(IOJS_URL_BASE "https://iojs.org/dist")
set(IOJS_VARIANT_BASE "iojs")
set(IOJS_WIN32_BINARY_NAME "${IOJS_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${IOJS_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_IOJS OR NodeJS_VARIANT STREQUAL ${IOJS_VARIANT_BASE})
if(NodeJS_VERSION STREQUAL "latest")
set(IOJS_LATEST_RELEASE_URL
"${IOJS_URL_BASE}/latest/SHASUMS256.txt")
nodejs_get_version(${IOJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
set(NodeJS_VARIANT_NAME "io.js")
set(NodeJS_VARIANT_BASE ${IOJS_VARIANT_BASE})
set(NodeJS_URL "${IOJS_URL_BASE}/v${NodeJS_VERSION}")
set(NodeJS_HEADER_VERSION 2.3.1)
set(NodeJS_WIN32_BINARY_NAME "${IOJS_WIN32_BINARY_NAME}")
endif()
mark_as_advanced(
IOJS_URL_BASE
IOJS_VARIANT_BASE
IOJS_WIN32_BINARY_NAME
IOJS_LATEST_RELEASE_URL
)
-30
View File
@@ -1,30 +0,0 @@
set(NWJS_URL_BASE "http://dl.nwjs.io")
set(NWJS_VARIANT_BASE "nw")
set(NWJS_WIN32_BINARY_NAME "${NWJS_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${NWJS_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_NWJS OR NodeJS_VARIANT STREQUAL ${NWJS_VARIANT_BASE})
set(NodeJS_CHECKSUM_PATH "MD5SUMS")
set(NodeJS_CHECKSUM_TYPE "MD5")
if(NodeJS_VERSION STREQUAL "latest")
set(NWJS_LATEST_RELEASE_URL
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
nodejs_get_version(${NWJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
set(NodeJS_VARIANT_NAME "nw.js")
set(NodeJS_VARIANT_BASE ${NWJS_VARIANT_BASE})
set(NodeJS_URL "${NWJS_URL_BASE}/v${NodeJS_VERSION}")
set(NodeJS_SOURCE_PATH "nw-headers-v${NodeJS_VERSION}.tar.gz")
set(NodeJS_DEFAULT_INCLUDE False)
set(NodeJS_HAS_WIN32_PREFIX False)
set(NodeJS_HAS_WIN32_BINARY False)
endif()
mark_as_advanced(
NWJS_URL_BASE
NWJS_VARIANT_BASE
NWJS_WIN32_BINARY_NAME
NWJS_LATEST_RELEASE_URL
)
-131
View File
@@ -1,131 +0,0 @@
set(NodeJS_URL_BASE http://nodejs.org/dist)
set(NodeJS_DEFAULT_VARIANT_BASE "node")
set(NodeJS_DEFAULT_WIN32_BINARY_NAME "${NodeJS_DEFAULT_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${NodeJS_DEFAULT_WIN32_BINARY_NAME})
if(NodeJS_VERSION STREQUAL "latest")
set(NodeJS_LATEST_RELEASE_URL
"${NodeJS_URL_BASE}/latest/SHASUMS256.txt")
nodejs_get_version(${NodeJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
if(NOT NodeJS_VARIANT_NAME)
set(NodeJS_VARIANT_NAME ${NodeJS_DEFAULT_VARIANT_NAME})
endif()
if(NOT NodeJS_VARIANT_BASE)
set(NodeJS_VARIANT_BASE ${NodeJS_DEFAULT_VARIANT_BASE})
endif()
if(NOT NodeJS_URL)
set(NodeJS_URL "${NodeJS_URL_BASE}/v${NodeJS_VERSION}")
endif()
if(NOT NodeJS_SOURCE_PATH)
set(NodeJS_SOURCE_PATH "${NodeJS_VARIANT_BASE}-v${NodeJS_VERSION}")
# Use the headers archive when its available
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}-headers")
endif()
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}.tar.gz")
endif()
if(NodeJS_DEFAULT_INCLUDE AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
set(NodeJS_SOURCE_INCLUDE False)
set(NodeJS_HEADER_INCLUDE True)
endif()
if(NodeJS_SOURCE_INCLUDE)
list(APPEND NodeJS_INCLUDE_PATHS
src
deps/uv/include
deps/v8/include
deps/zlib
)
# OpenSSL is an optional header
if(NodeJS_HAS_OPENSSL)
list(APPEND NodeJS_INCLUDE_PATHS
deps/openssl/openssl/include
)
endif()
endif()
if(NodeJS_HEADER_INCLUDE)
set(NodeJS_INCLUDE_PATHS include/node)
endif()
if(NOT NodeJS_CHECKSUM_TYPE)
# Use SHA256 when available
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_SHA256_VERSION})
set(NodeJS_CHECKSUM_TYPE "SHA256")
else()
set(NodeJS_CHECKSUM_TYPE "SHA1")
endif()
endif()
if(NOT NodeJS_CHECKSUM_PATH)
set(NodeJS_CHECKSUM_PATH "SHASUMS")
if(NodeJS_CHECKSUM_TYPE STREQUAL "SHA256")
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}256")
endif()
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}.txt")
endif()
# Library and binary are based on variant base
if(NOT NodeJS_WIN32_LIBRARY_NAME)
set(NodeJS_WIN32_LIBRARY_NAME ${NodeJS_VARIANT_BASE}.lib)
endif()
if(NOT NodeJS_WIN32_BINARY_NAME)
set(NodeJS_WIN32_BINARY_NAME ${NodeJS_VARIANT_BASE}.exe)
endif()
if(NOT NodeJS_WIN32_LIBRARY_PATH)
# The library location is prefixed after a specific version
if(NodeJS_HAS_WIN32_PREFIX AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
set(NodeJS_WIN32_LIBRARY_PATH "win-")
if(NodeJS_ARCH_IA32)
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x86/")
endif()
endif()
# 64-bit versions are prefixed
if(NodeJS_ARCH_X64)
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x64/")
endif()
set(NodeJS_WIN32_LIBRARY_PATH
"${NodeJS_WIN32_LIBRARY_PATH}${NodeJS_WIN32_LIBRARY_NAME}"
)
endif()
if(NodeJS_HAS_WIN32_BINARY AND NOT NodeJS_WIN32_BINARY_PATH)
# The executable location is prefixed after a specific version
if(NodeJS_HAS_WIN32_PREFIX AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
set(NodeJS_WIN32_BINARY_PATH "win-")
if(NodeJS_ARCH_IA32)
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x86/")
endif()
endif()
# 64-bit versions are prefixed
if(NodeJS_ARCH_X64)
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x64/")
endif()
set(NodeJS_WIN32_BINARY_PATH
"${NodeJS_WIN32_BINARY_PATH}${NodeJS_WIN32_BINARY_NAME}"
)
endif()
# Specify windows libraries
# XXX: This may need to be version/variant specific in the future
if(NodeJS_DEFAULT_LIBS AND NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_LIBRARIES
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
odbc32.lib DelayImp.lib
)
endif()
mark_as_advanced(
NodeJS_URL_BASE
NodeJS_DEFAULT_VARIANT_BASE
NodeJS_DEFAULT_WIN32_BINARY_NAME
NodeJS_LATEST_RELEASE_URL
)
+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 ~@match --tags ~@alternative --tags ~@matrix --tags ~@trip --tags ~@via --require features/support --require features/step_definitions -f progress'
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@matrix --tags ~@trip --require features/support --require features/step_definitions -f progress'
}
+126 -127
View File
@@ -1,66 +1,59 @@
# OSRM
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance requires a `.osrm` network,
which is prepared by the OSRM Backend C++ library.
## OSRM
The `OSRM` method is the main constructor for creating an OSRM instance.
An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
node_modules/osrm/lib/binding/osrm-contract data.osrm
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation or further details.
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
Once you have a complete `network.osrm` file, you can calculate networks in javascript with this library using the
methods below. To create an OSRM instance with your network you need to construct an instance like this:
Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
```javascript
var osrm = new OSRM('network.osrm');
```
#### Methods
**Parameters**
| Service | Description |
| -------------------------- | --------------------------------------------------------- |
| [`osrm.route`](#route) | shortest path between given coordinates |
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
| [`osrm.table`](#table) | computes distance tables for given coordinates |
| [`osrm.match`](#match) | matches given coordinates to the road network |
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Options for creating an OSRM object or string to the `.osrm` file. (optional, default `{shared_memory:true}`)
- `options.algorithm` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
Make sure you prepared the dataset with the correct toolchain.
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
#### General Options
Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options, outlined below.
| Option | Values | Description | Format |
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
| bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
| radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
| hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
## route
### route
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
- `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.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (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`)
- `options.continue_straight` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. `null`/`true`/`false`
- `options.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 `null` (unlimited, default) or `double >= 0`.
- `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.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`)
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
`null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM("berlin-latest.osrm");
osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, function(err, result) {
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
if(err) throw err;
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
@@ -69,7 +62,7 @@ osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, funct
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
## nearest
### nearest
Snaps a coordinate to the street network and returns the nearest n matches.
@@ -78,7 +71,12 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
- `options.number` **\[[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)]** Number of nearest segments that should be returned.
- `options.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 `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
@@ -98,19 +96,26 @@ osrm.nearest(options, function(err, response) {
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied
input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied input coordinate.
## table
### table
Computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
tables.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
- `options.sources` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use
- `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 `null` (unlimited, default) or `double >= 0`.
- `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.sources` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to
use
location with given index as source. Default is to use all.
- `options.destinations` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
#coordinates`) to use location with given index as destination. Default is to use all.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -132,24 +137,25 @@ osrm.table(options, function(err, response) {
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from the i-th waypoint to the j-th waypoint.
Values are given in seconds.
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
## tile
### tile
This generates [Mapbox Vector Tiles](https://mapbox.com/vector-tiles) that can be viewed with a
vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can
be used to examine the routing graph. The tiles are generated directly from the data in-memory,
so are in sync with actual routing results, and let you examine which roads are actually routable,
so are in sync with actual routing results, and let you examine which roads are actually
routable,
and what weights they have applied.
**Parameters**
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
and are supported by vector tile viewers like [Mapbox GL JS]\(<https://www.mapbox.com/mapbox-gl-js/api/>.
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -164,7 +170,7 @@ osrm.tile([0, 0, 0], function(err, response) {
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
## match
### match
Map matching matches given GPS points to the road network in the most plausible way.
Please note the request might result multiple sub-traces. Large jumps in the timestamps
@@ -175,15 +181,16 @@ if they can not be matched successfully.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
- `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` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (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`)
- `options.timestamps` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>]** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** Standard deviation of GPS precision used for map matching.
If applicable use GPS accuracy (`double >= 0`, default `5m`).
- `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.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` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -203,69 +210,54 @@ osrm.match(options, function(err, response) {
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
**`tracepoints`** Array of [`Ẁaypoint`](#waypoint) objects representing all points of the trace in order.
If the trace point was ommited by map matching because it is an outlier, the entry will be null. Each
`Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
the waypoint inside the matched route.
**`matchings`** is an array of [`Route`](#route) objects that
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
If the trace point was ommited by map matching because it is an outlier, the entry will be null.
Each `Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
the waypoint inside the matched route.
**`matchings`** is an array of [`Route`](#route) objects that assemble the trace. Each `Route` object has an additional `confidence` property,
which is the confidence of the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
## trip
### trip
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm). The returned path does not have to be the fastest 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.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` coordinate. Can also be `first`. (optional, default `any`)
- `options.destination` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route ends at `any` coordinate. Can also be `last`. (optional, default `any`)
- `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` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (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`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Fixing Start and End Points**
It is possible to explicitly set the start or end coordinate of the trip. When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
(farthest-insertion algorithm) for 10 or _ more waypoints and uses brute force for less than 10
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.
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
Right now, the following combinations are possible:
| roundtrip | source | destination | supported |
| :-- | :-- | :-- | :-- |
| true | first | last | **yes** |
| true | first | any | **yes** |
| true | any | last | **yes** |
| true | any | any | **yes** |
| false | first | last | **yes** |
| false | first | any | no |
| false | any | last | no |
| false | any | any | no |
| :-------- | :----- | :---------- | :-------- |
| true | first | last | **yes** |
| true | first | any | **yes** |
| true | any | last | **yes** |
| true | any | any | **yes** |
| false | first | last | **yes** |
| false | first | any | no |
| 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`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
}
osrm.trip(options, function(err, response) {
if (err) throw err;
console.log(response.waypoints); // array of Waypoint objects
console.log(response.trips); // array of Route objects
});
```
Non Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
@@ -285,49 +277,56 @@ osrm.trip(options, function(err, response) {
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of the
sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
**`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties,
1) `trips_index`: index to trips of the sub-trip the point was matched to, and
2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
# Responses
## Responses
Responses
## Route
### Route
Represents a route through (potentially multiple) waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#route)
## RouteLeg
### RouteLeg
Represents a route between two waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#routeleg)
## RouteStep
### RouteStep
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a single way to the subsequent step.
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a
single way to the subsequent step.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
## StepManeuver
### StepManeuver
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmanuever)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
## Waypoint
### Waypoint
Object used to describe waypoint on a route.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
+35
View File
@@ -0,0 +1,35 @@
@routing @bicycle @alley
Feature: Bicycle - Route around alleys
Background:
Given the profile file
"""
require 'bicycle'
properties.weight_name = 'cyclability'
"""
Scenario: Bicycle - Avoid taking alleys
Given the query options
| annotations | nodes |
Given the node map
"""
a-----b-----c
| : |
d.....e.....f
"""
And the ways
| nodes | highway | service |
| abc | residential | |
| def | service | alley |
| ad | residential | |
| be | service | alley |
| cf | residential | |
When I route I should get
| from | to | a:nodes | weight | # |
| a | f | 1:2:3:6 | 200.4 | Avoids d,e,f |
| a | e | 1:2:5 | 176.4 | Take the alley b,e if neccessary |
| d | f | 4:1:2:3:6 | 252.6 | Avoids the alley d,e,f |
+36
View File
@@ -34,3 +34,39 @@ Feature: Turn Penalties
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
Scenario: Bicycle - Turn penalties on cyclability
Given the profile file
"""
require 'bicycle'
properties.weight_name = 'cyclability'
"""
Given the node map
"""
a--b-----c
|
|
d
e--------f-----------g
/
/
/
h
"""
And the ways
| nodes | highway |
| abc | residential |
| bd | residential |
| efg | residential |
| fh | residential |
When I route I should get
| from | to | distance | weight | # |
| a | c | 900m +- 1 | 216 | Going straight has no penalties |
| a | d | 900m +- 1 | 220.2 | Turning right had penalties |
| e | g | 2100m +- 4| 503.9 | Going straght has no penalties |
| e | h | 2100m +- 4| 515.1 | Turn sharp right has even higher penalties|
@@ -0,0 +1,39 @@
@routing @car @traffic_light
Feature: Car - Handle traffic lights
Background:
Given the profile "car"
Scenario: Car - Encounters a traffic light
Given the node map
"""
a-1-b-2-c
d-3-e-4-f
g-h-i k-l-m
| |
j n
"""
And the ways
| nodes | highway |
| abc | primary |
| def | primary |
| ghi | primary |
| klm | primary |
| hj | primary |
| ln | primary |
And the nodes
| node | highway |
| e | traffic_signals |
| l | traffic_signals |
When I route I should get
| from | to | time | # |
| 1 | 2 | 11.1s | no turn with no traffic light |
| 3 | 4 | 13.1s | no turn with traffic light |
| g | j | 18.7s | turn with no traffic light |
| k | n | 20.7s | turn with traffic light |
@@ -48,7 +48,6 @@ Feature: Traffic - turn penalties
| mn | primary |
| mp | primary |
And the profile "car"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting not based on turn penalty file
When I route I should get
+25 -1
View File
@@ -51,7 +51,6 @@ Feature: Car - weights
| cd | primary | yes |
| be | service | yes |
| ec | service | yes |
And the extract extra arguments "--generate-edge-lookup"
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
@@ -62,3 +61,28 @@ Feature: Car - weights
| from | to | route | speed | weight |
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
| a | e | ab,be,be | 14 km/h | 112 |
Scenario: Distance weights
Given the profile file "car" extended with
"""
api_version = 1
properties.weight_name = 'distance'
"""
Given the node map
"""
a---b---c
|
d
"""
And the ways
| nodes |
| abc |
| bd |
When I route I should get
| waypoints | bearings | route | distance | weights | times |
| a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
| b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
| a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s |
+36
View File
@@ -1019,3 +1019,39 @@ Feature: Collapse
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
# http://www.openstreetmap.org/way/92415447 #3933
Scenario: Use total angle for turn instruction if entry step has large distance
# """
# kf-_ a
# | - b
# | c
# |d
# e
# |
# i
# """
And the node locations
| node | lat | lon | #id |
| a | -33.9644254 | 151.1378673 | 33226063 |
| b | -33.9644373 | 151.1377172 | 1072787030 |
| c | -33.9644791 | 151.1374452 | 4222903609 |
| d | -33.9645661 | 151.1372654 | 4222903610 |
| e | -33.9646986 | 151.1371539 | 4222903611 |
| f | -33.964386 | 151.1372133 | 1072786875 |
| i | -33.9661796 | 151.1368491 | 2781176918 |
| k | -33.9643781 | 151.1371422 | 1684173853 |
And the ways
| nodes | highway | name | oneway | #id |
| ab | trunk | President Avenue | yes | 92415447 |
| bcde | trunk | President Avenue | yes | 422534457 |
| bf | trunk | President Avenue | yes | 447779786 |
| fk | trunk | President Avenue | yes | 179293012 |
| fei | trunk | Princes Highway | yes | 130099670 |
When I route I should get
| waypoints | route | turns | locations |
| a,i | President Avenue,Princes Highway,Princes Highway | depart,turn left,arrive | a,b,i |
+139
View File
@@ -222,6 +222,43 @@ Feature: Basic Roundabout
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
Scenario: Mixed Entry and Exit - clockwise order
Given the node map
"""
c a
j b f
k e
l h d
g i
"""
And the ways
| nodes | junction | oneway |
| abc | | yes |
| def | | yes |
| ghi | | yes |
| jkl | | yes |
| behkb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-3,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
Scenario: Mixed Entry and Exit - segregated roads, different names
Given the node map
"""
@@ -681,3 +718,105 @@ Feature: Basic Roundabout
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
| u,s | ug,ds,ds | depart,roundabout-exit-4,arrive |
| u,t | ug,ft,ft | depart,roundabout-exit-5,arrive |
@3762
Scenario: Only Enter
Given the node map
"""
a
b
i c e ~ ~ ~ f - h
j d
k g
"""
And the ways
| nodes | junction | route |
| ab | | |
| ef | | ferry |
| fh | | |
| dg | | |
| ic | | |
| jk | | |
| bcjdeb | roundabout | |
When I route I should get
| waypoints | route | turns |
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
Scenario: Drive through roundabout
Given the node map
"""
a
b e d f
c
g h
"""
And the ways
| nodes | junction | oneway |
| abcda | roundabout | yes |
| edf | | |
| gch | | yes |
When I route I should get
| waypoints | bearings | route | turns |
| e,f | 90 90 | edf,edf,edf | depart,roundabout-exit-1,arrive |
| e,h | 90 135 | edf,gch,gch | depart,roundabout-exit-2,arrive |
| g,f | 45 90 | gch,edf,edf | depart,roundabout-exit-2,arrive |
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |
@4030 @4075
Scenario: Service roundabout with service exits
# Counting of service exits must be adjusted in #4075
Given the node map
"""
e
f a d
g b1c
h
"""
And the ways
| nodes | highway | junction |
| abcda | service | roundabout |
| de | service | |
| af | service | |
| bg | tertiary | |
| bh | service | |
When I route I should get
| from | to | route | turns |
| 1 | e | abcda,de,de | depart,roundabout-exit-1,arrive |
| 1 | f | abcda,af,af | depart,roundabout-exit-1,arrive |
| 1 | g | abcda,bg,bg | depart,roundabout-exit-1,arrive |
| 1 | h | abcda,bh,bh | depart,roundabout-exit-1,arrive |
Scenario: CCW and CW roundabouts with overlaps
Given the node map
"""
a d g h
b c j i
f e k l
"""
And the ways
| nodes | highway | junction |
| abcda | tertiary | roundabout |
| ed | tertiary | |
| af | tertiary | |
| ghijg | tertiary | roundabout |
| kg | tertiary | |
| hl | tertiary | |
When I route I should get
| from | to | route | turns | distance |
| e | f | ed,af,af | depart,roundabout-exit-1,arrive | 80.1m |
| f | e | af,ed,ed | depart,roundabout-exit-1,arrive | 120.1m |
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |
@@ -20,11 +20,30 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
And the data has been saved to disk
Scenario: Logging weight with updates over factor of 2, long segment
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
When I run "osrm-extract --profile {profile_file} {osm_file}"
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"
And stderr should contain "Segment: 1,3"
And I route I should get
| from | to | route | speed |
| a | b | ab,ab | 100 km/h |
| a | c | ac,ac | 100 km/h |
Scenario: Logging using weigts as durations for non-duration profile
Given the profile file "testbot" extended with
"""
properties.weight_name = 'steps'
function way_function(way, result)
result.forward_mode = mode.driving
result.backward_mode = mode.driving
result.weight = 1
result.duration = 1
end
"""
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file}"
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"
+5 -3
View File
@@ -16,10 +16,13 @@ module.exports = function () {
var headers = new Set(table.raw()[0]);
got.code = 'unknown';
if (res.body.length) {
json = JSON.parse(res.body);
got.code = json.code;
}
if (headers.has('status')) {
got.status = json.status.toString();
}
@@ -33,7 +36,7 @@ module.exports = function () {
got['#'] = row['#'];
}
var subMatchings = [],
var subMatchings = [''],
turns = '',
route = '',
duration = '',
@@ -175,8 +178,7 @@ module.exports = function () {
if (headers.has('matchings')) {
if (subMatchings.length != row.matchings.split(',').length) {
ok = false;
cb(new Error('*** table matchings and api response are not the same'));
return cb(new Error('*** table matchings and api response are not the same'));
}
row.matchings.split(',').forEach((sub, si) => {
+1
View File
@@ -126,6 +126,7 @@ module.exports = function () {
r.query = this.query;
r.json = JSON.parse(body);
r.code = r.json.code;
r.status = res.statusCode === 200 ? 'x' : null;
if (r.status) {
r.route = this.wayList(r.json.routes[0]);
+5 -3
View File
@@ -29,8 +29,10 @@ module.exports = function () {
}
var json;
got.code = 'unknown';
if (res.body.length) {
json = JSON.parse(res.body);
got.code = json.code;
}
if (headers.has('status')) {
@@ -153,11 +155,11 @@ module.exports = function () {
if (row.source) {
params.source = got.source = row.source;
}
}
if (row.destination) {
params.destination = got.destination = row.destination;
}
}
if (row.hasOwnProperty('roundtrip')) { //roundtrip is a boolean so row.roundtrip alone doesn't work as a check here
params.roundtrip = got.roundtrip = row.roundtrip;
+96 -94
View File
@@ -39,6 +39,8 @@ module.exports = function () {
let json = JSON.parse(body);
got.code = json.code;
let hasRoute = json.code === 'Ok';
if (hasRoute) {
@@ -79,102 +81,102 @@ module.exports = function () {
if (headers.has('route')) {
got.route = (instructions || '').trim();
if (headers.has('summary')) {
got.summary = (summary || '').trim();
}
if (headers.has('alternative')) {
// TODO examine more than first alternative?
got.alternative ='';
if (json.routes && json.routes.length > 1)
got.alternative = this.wayList(json.routes[1]);
}
var distance = hasRoute && json.routes[0].distance,
time = hasRoute && json.routes[0].duration,
weight = hasRoute && json.routes[0].weight;
if (headers.has('distance')) {
if (row.distance.length) {
if (!row.distance.match(/\d+m/))
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
got.distance = instructions ? util.format('%dm', distance) : '';
} else {
got.distance = '';
}
}
if (headers.has('weight')) {
if (row.weight.length) {
if (!row.weight.match(/[\d\.]+/))
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
got.weight = instructions ? util.format('%d', weight) : '';
} else {
got.weight = '';
}
}
if (headers.has('time')) {
if (!row.time.match(/\d+s/))
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
got.time = instructions ? util.format('%ds', time) : '';
}
if (headers.has('lanes')) {
got.lanes = (lanes || '').trim();
}
if (headers.has('speed')) {
if (row.speed !== '' && instructions) {
if (!row.speed.match(/\d+ km\/h/))
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
got.speed = util.format('%d km/h', speed);
} else {
got.speed = '';
}
}
if (headers.has('intersections')) {
got.intersections = (intersections || '').trim();
}
if (headers.has('locations')){
got.locations = (locations || '').trim();
}
// if header matches 'a:*', parse out the values for *
// and return in that header
headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) {
let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1)
return cb(new Error('Unrecognized annotation field', a_type));
if (annotation && !annotation[a_type])
return cb(new Error('Annotation not found in response', a_type));
got[k] = annotation && annotation[a_type] || '';
}
});
var putValue = (key, value) => {
if (headers.has(key)) got[key] = instructions ? value : '';
};
putValue('ref', refs);
putValue('bearing', bearings);
putValue('turns', turns);
putValue('modes', modes);
putValue('times', times);
putValue('distances', distances);
putValue('pronunciations', pronunciations);
putValue('destinations', destinations);
putValue('weight_name', weight_name);
putValue('weights', weights);
putValue('weight', weight);
}
if (headers.has('summary')) {
got.summary = (summary || '').trim();
}
if (headers.has('alternative')) {
// TODO examine more than first alternative?
got.alternative ='';
if (json.routes && json.routes.length > 1)
got.alternative = this.wayList(json.routes[1]);
}
var distance = hasRoute && json.routes[0].distance,
time = hasRoute && json.routes[0].duration,
weight = hasRoute && json.routes[0].weight;
if (headers.has('distance')) {
if (row.distance.length) {
if (!row.distance.match(/\d+m/))
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
got.distance = instructions ? util.format('%dm', distance) : '';
} else {
got.distance = '';
}
}
if (headers.has('weight')) {
if (row.weight.length) {
if (!row.weight.match(/[\d\.]+/))
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
got.weight = instructions ? util.format('%d', weight) : '';
} else {
got.weight = '';
}
}
if (headers.has('time')) {
if (!row.time.match(/\d+s/))
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
got.time = instructions ? util.format('%ds', time) : '';
}
if (headers.has('lanes')) {
got.lanes = (lanes || '').trim();
}
if (headers.has('speed')) {
if (row.speed !== '' && instructions) {
if (!row.speed.match(/\d+ km\/h/))
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
got.speed = util.format('%d km/h', speed);
} else {
got.speed = '';
}
}
if (headers.has('intersections')) {
got.intersections = (intersections || '').trim();
}
if (headers.has('locations')){
got.locations = (locations || '').trim();
}
// if header matches 'a:*', parse out the values for *
// and return in that header
headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) {
let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1)
return cb(new Error('Unrecognized annotation field', a_type));
if (annotation && !annotation[a_type])
return cb(new Error('Annotation not found in response', a_type));
got[k] = annotation && annotation[a_type] || '';
}
});
var putValue = (key, value) => {
if (headers.has(key)) got[key] = instructions ? value : '';
};
putValue('ref', refs);
putValue('bearing', bearings);
putValue('turns', turns);
putValue('modes', modes);
putValue('times', times);
putValue('distances', distances);
putValue('pronunciations', pronunciations);
putValue('destinations', destinations);
putValue('weight_name', weight_name);
putValue('weights', weights);
putValue('weight', weight);
for (var key in row) {
if (this.FuzzyMatch.match(got[key], row[key])) {
got[key] = row[key];
+2 -3
View File
@@ -4,7 +4,6 @@ Feature: Basic Map Matching
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Given the extract extra arguments "--generate-edge-lookup"
Given the query options
| geometries | geojson |
@@ -213,7 +212,7 @@ Feature: Basic Map Matching
And the speed file
"""
1,2,36
1,2,36,10
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
@@ -240,7 +239,7 @@ Feature: Basic Map Matching
And the speed file
"""
1,2,36
1,2,36,10
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
+35
View File
@@ -36,3 +36,38 @@ Feature: Projection to nearest point on road
| from | to | route | distance |
| d | b | abc,abc | 0m |
| b | d | abc,abc | 0m |
Scenario: Projection results negative duration
Given the profile file "testbot" extended with
"""
api_version = 1
function segment_function (segment)
segment.weight = 5.5
segment.duration = 2.8
end
"""
Given the node locations
| node | lon | lat |
| e | -51.218994 | -30.023866 |
| f | -51.218918 | -30.023741 |
| 1 | -51.219109 | -30.023766 |
| 2 | -51.219109 | -30.023764 |
| 3 | -51.219109 | -30.023763 |
| 4 | -51.219109 | -30.023762 |
| 5 | -51.219109 | -30.023761 |
| 6 | -51.219109 | -30.023756 |
And the ways
| nodes |
| ef |
When I route I should get
| waypoints | route | distance | time | weight |
| 1,4 | ef,ef | 0.4m | 0.1s | 0.1 |
| 2,4 | ef,ef | 0.1m | 0s | 0 |
| 3,4 | ef,ef | 0.1m | 0s | 0 |
| 4,4 | ef,ef | 0m | 0s | 0 |
| 5,4 | ef,ef | 0.1m | 0s | 0.1 |
| 6,4 | ef,ef | 0.6m | 0.1s | 0.2 |
+37 -30
View File
@@ -22,7 +22,6 @@ Feature: Traffic - speeds
| df | primary |
| fb | primary |
And the profile "testbot"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on speed file
@@ -30,12 +29,12 @@ Feature: Traffic - speeds
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,0
2,1,0
2,3,27
3,2,27
1,4,27
4,1,27
1,2,0,0
2,1,0,0
2,3,27,7.5
3,2,27,7.5
1,4,27,7.5
4,1,27,7.5
"""
And the query options
| annotations | datasources |
@@ -56,12 +55,12 @@ Feature: Traffic - speeds
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,1,20020.7
2,1,1,20020.7
2,3,27,741.5
3,2,27,741.5
1,4,27,1275.7
4,1,27,1275.7
1,2,1,0.2777777
2,1,1
2,3,27
3,2,27,7.5
1,4,27,7.5
4,1,27,7.5
"""
And the query options
| annotations | datasources |
@@ -89,26 +88,26 @@ Feature: Traffic - speeds
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,1,20020.789
2,1,1,20020.123
2,3,27,741.56789
3,2,27,741.3
1,4,1,34445.12
4,1,1,34445.3
1,2,1,0.27777777
2,1,1,0.27777777
2,3,27,7.5
3,2,27
1,4,1
4,1,1
"""
And the query options
| annotations | datasources |
When I route I should get
| from | to | route | speed | weights | a:datasources |
| a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
| b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
| a | b | ab,ab | 1 km/h | 20020.735,0 | 1:0 |
| a | c | ab,bc,bc | 2 km/h | 20020.735,741.509,0 | 1:1:0 |
| b | c | bc,bc | 27 km/h | 741.509,0 | 1:0 |
| a | d | ab,eb,de,de | 2 km/h | 20020.735,378.169,400.415,0 | 1:0:0 |
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
| g | b | ab,ab | 1 km/h | 10010.365,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.37,0 | 1 |
| g | a | ab,ab | 1 km/h | 10010.37,0 | 1:1 |
Scenario: Speeds that isolate a single node (a)
@@ -121,10 +120,10 @@ Feature: Traffic - speeds
"""
1,2,0
2,1,0
2,3,27
3,2,27
1,4,0
4,1,0
2,3,27,7.5
3,2,27,7.5
1,4,0,0
4,1,0,0
"""
And the query options
| annotations | true |
@@ -154,3 +153,11 @@ Feature: Traffic - speeds
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And stderr should contain "malformed"
And it should exit with an error
Scenario: Check with an empty speed file
Given the speed file
"""
"""
And the data has been extracted
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And it should exit successfully
@@ -31,7 +31,6 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
| dg | primary |
And the profile "testbot"
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
Given the turn penalty file
+61
View File
@@ -352,3 +352,64 @@ Feature: Via points
| waypoints | bearings | route | turns |
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
Scenario: Continue Straight in presence of Bearings
Given the node map
"""
h - a 1 b -- g
| |
| |- 2 c - f
| 3
e ------ d - i
|
j
"""
And the query options
| continue_straight | false |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cdea | no |
| ah | yes |
| bg | yes |
| cf | yes |
| di | yes |
| dj | yes |
When I route I should get
| waypoints | bearings | route |
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,cdea,cdea |
Scenario: Continue Straight in presence of Bearings
Given the node map
"""
h - a 1 b -- g
| |
| |- 2 c - f
| 3
e ------ d - i
|
j
"""
And the query options
| continue_straight | true |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cdea | no |
| ah | yes |
| bg | yes |
| cf | yes |
| di | yes |
| dj | yes |
When I route I should get
| waypoints | bearings | route |
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,ab,cdea,cdea,cdea |
+4 -5
View File
@@ -4,7 +4,6 @@ Feature: Weight tests
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Given the extract extra arguments "--generate-edge-lookup"
Given the query options
| geometries | geojson |
@@ -284,8 +283,8 @@ Feature: Weight tests
When I route I should get
| waypoints | route | distance | weights | times |
| a,d | , | 59.9m | 62,0 | 24s,0s |
| a,e | ,, | 60.1m | 68.7,10,0 | 38.5s,11s,0s |
| a,d | , | 59.9m | 20.5,0 | 24s,0s |
| a,e | ,, | 60.1m | 27.2,10,0 | 38.5s,11s,0s |
| d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s |
@traffic @speed
@@ -320,6 +319,6 @@ Feature: Weight tests
When I route I should get
| waypoints | route | distance | weights | times |
| a,d | abcd,abcd | 59.9m | 6.993,0 | 7s,0s |
| a,e | abcd,ce,ce | 60.1m | 6.002,2.002,0 | 6s,2s,0s |
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
+163
View File
@@ -0,0 +1,163 @@
Feature: Check zero speed updates
Scenario: Matching on restricted way, single segment
Given the query options
| geometries | geojson |
| annotations | true |
Given the node map
"""
a-1--b--c-2-d
"""
And the ways
| nodes |
| abcd |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
"""
When I match I should get
| trace | code |
| 12 | NoMatch |
Scenario: Matching restricted way, both segments
Given the node map
"""
a-1--b-2-c
"""
And the ways
| nodes | oneway |
| abc | no |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I match I should get
| trace | code |
| 12 | NoMatch |
Scenario: Matching on restricted oneway
Given the node map
"""
a-1--b-2-c
"""
And the ways
| nodes | oneway |
| abc | yes |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
"""
When I match I should get
| trace | code |
| 12 | NoMatch |
Scenario: Routing on restricted way
Given the node map
"""
a-1-b-2-c
"""
And the ways
| nodes | oneway |
| abc | no |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I route I should get
| from | to | code |
| 1 | 2 | NoRoute |
Scenario: Routing on restricted oneway
Given the node map
"""
a-1-b-2-c
"""
And the ways
| nodes | oneway |
| abc | yes |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I route I should get
| from | to | bearings | code |
| 1 | 2 | 270 270 | NoRoute |
Scenario: Via routing on restricted oneway
Given the node map
"""
a-1-b-2-c-3-d
"""
And the ways
| nodes | oneway |
| abc | no |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I route I should get
| waypoints | code |
| 1,2,3 | NoRoute |
| 3,2,1 | NoRoute |
@trip
Scenario: Trip
Given the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| bc |
| cb |
| da |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,0
2,1,0
"""
When I plan a trip I should get
| waypoints | trips | code |
| a,b,c,d | abcda | NoTrips |
| d,b,c,a | dbcad | NoTrips |
+2 -3
View File
@@ -68,9 +68,8 @@ class Contractor
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
void WriteNodeLevels(std::vector<float> &&node_levels) const;
void ReadNodeLevels(std::vector<float> &contraction_order) const;
std::size_t
WriteContractedGraph(unsigned number_of_edge_based_nodes,
const util::DeallocatingVector<QueryEdge> &contracted_edge_list);
void WriteContractedGraph(unsigned number_of_edge_based_nodes,
util::DeallocatingVector<QueryEdge> contracted_edge_list);
void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<extractor::EdgeBasedEdge> &edges,
std::vector<extractor::EdgeBasedNode> &nodes) const;
+50
View File
@@ -0,0 +1,50 @@
#ifndef OSRM_CONTRACTOR_FILES_HPP
#define OSRM_CONTRACTOR_FILES_HPP
#include "contractor/query_graph.hpp"
#include "util/serialization.hpp"
#include "storage/io.hpp"
namespace osrm
{
namespace contractor
{
namespace files
{
// reads .osrm.hsgr file
template <typename QueryGraphT>
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
{
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.ReadInto(checksum);
util::serialization::read(reader, graph);
}
// writes .osrm.hsgr file
template <typename QueryGraphT>
inline void
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
{
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteOne(checksum);
util::serialization::write(writer, graph);
}
}
}
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef OSRM_CONTRACTOR_QUERY_GRAPH_HPP
#define OSRM_CONTRACTOR_QUERY_GRAPH_HPP
#include "contractor/query_edge.hpp"
#include "util/static_graph.hpp"
#include "util/typedefs.hpp"
namespace osrm
{
namespace contractor
{
namespace detail
{
template <storage::Ownership Ownership>
using QueryGraph = util::StaticGraph<typename QueryEdge::EdgeData, Ownership>;
}
using QueryGraph = detail::QueryGraph<storage::Ownership::Container>;
using QueryGraphView = detail::QueryGraph<storage::Ownership::View>;
}
}
#endif // QUERYEDGE_HPP
+51 -29
View File
@@ -5,7 +5,8 @@
#include "partition/multi_level_partition.hpp"
#include "util/binary_heap.hpp"
#include <boost/thread/tss.hpp>
#include <tbb/enumerable_thread_specific.h>
#include <unordered_set>
namespace osrm
@@ -15,12 +16,22 @@ namespace customizer
class CellCustomizer
{
private:
struct HeapData
{
bool from_clique;
};
public:
using Heap =
util::BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
template <typename GraphT>
void Customize(const GraphT &graph, partition::CellStorage &cells, LevelID level, CellID id)
void Customize(
const GraphT &graph, Heap &heap, partition::CellStorage &cells, LevelID level, CellID id)
{
auto cell = cells.GetCell(level, id);
auto destinations = cell.GetDestinationNodes();
@@ -29,8 +40,8 @@ class CellCustomizer
for (auto source : cell.GetSourceNodes())
{
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
Heap heap(graph.GetNumberOfNodes());
heap.Insert(source, 0, {});
heap.Clear();
heap.Insert(source, 0, {false});
// explore search space
while (!heap.Empty() && !destinations_set.empty())
@@ -60,26 +71,23 @@ class CellCustomizer
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
{
Heap heap_exemplar(graph.GetNumberOfNodes());
HeapPtr heaps(heap_exemplar);
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
{
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
[&](const tbb::blocked_range<std::size_t> &range) {
auto &heap = heaps.local();
for (auto id = range.begin(), end = range.end(); id != end; ++id)
{
Customize(graph, cells, level, id);
Customize(graph, heap, cells, level, id);
}
});
}
}
private:
struct HeapData
{
};
using Heap = util::
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
using HeapPtr = boost::thread_specific_ptr<Heap>;
template <bool first_level, typename GraphT>
void RelaxNode(const GraphT &graph,
const partition::CellStorage &cells,
@@ -88,29 +96,42 @@ class CellCustomizer
NodeID node,
EdgeWeight weight) const
{
BOOST_ASSERT(heap.WasInserted(node));
if (!first_level)
{
// Relax sub-cell nodes
auto subcell_id = partition.GetCell(level - 1, node);
auto subcell = cells.GetCell(level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin();
for (auto subcell_weight : subcell.GetOutWeight(node))
// if we reaches this node from a clique arc we don't need to scan
// the clique arcs again because of the triangle inequality
//
// d(parent, node) + d(node, v) >= d(parent, v)
//
// And if there is a path (parent, node, v) there must also be a
// clique arc (parent, v) with d(parent, v).
if (!heap.GetData(node).from_clique)
{
if (subcell_weight != INVALID_EDGE_WEIGHT)
// Relax sub-cell nodes
auto subcell_id = partition.GetCell(level - 1, node);
auto subcell = cells.GetCell(level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin();
for (auto subcell_weight : subcell.GetOutWeight(node))
{
const NodeID to = *subcell_destination;
const EdgeWeight to_weight = subcell_weight + weight;
if (!heap.WasInserted(to))
if (subcell_weight != INVALID_EDGE_WEIGHT)
{
heap.Insert(to, to_weight, {});
const NodeID to = *subcell_destination;
const EdgeWeight to_weight = subcell_weight + weight;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true});
}
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to).from_clique = true;
}
}
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
}
}
++subcell_destination;
++subcell_destination;
}
}
}
@@ -126,11 +147,12 @@ class CellCustomizer
const EdgeWeight to_weight = data.weight + weight;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {});
heap.Insert(to, to_weight, {false});
}
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to).from_clique = false;
}
}
}
+7 -4
View File
@@ -7,6 +7,8 @@
#include "util/static_graph.hpp"
#include "util/typedefs.hpp"
#include "storage/shared_memory_ownership.hpp"
#include <boost/filesystem/path.hpp>
namespace osrm
@@ -16,16 +18,17 @@ namespace customizer
using EdgeBasedGraphEdgeData = partition::EdgeBasedGraphEdgeData;
struct MultiLevelEdgeBasedGraph : public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>
struct MultiLevelEdgeBasedGraph
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
{
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>;
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
using Base::Base;
};
struct MultiLevelEdgeBasedGraphView
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, true>
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
{
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, true>;
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
using Base::Base;
};
-18
View File
@@ -1,18 +0,0 @@
#ifndef OSRM_CUSTOMIZER_IO_HPP
#define OSRM_CUSTOMIZER_IO_HPP
#include "customizer/edge_based_graph.hpp"
#include "storage/io.hpp"
namespace osrm
{
namespace customizer
{
namespace io
{
}
}
}
#endif
+34 -41
View File
@@ -7,30 +7,36 @@ namespace osrm
{
namespace engine
{
namespace algorithm
namespace routing_algorithms
{
// Contraction Hiearchy
struct CH final
namespace ch
{
struct Algorithm final
{
};
}
// Contraction Hiearchy with core
struct CoreCH final
namespace corech
{
struct Algorithm final
{
};
}
// Multi-Level Dijkstra
struct MLD final
namespace mld
{
struct Algorithm final
{
};
template <typename AlgorithmT> const char *name();
template <> inline const char *name<CH>() { return "CH"; }
template <> inline const char *name<CoreCH>() { return "CoreCH"; }
template <> inline const char *name<MLD>() { return "MLD"; }
}
namespace algorithm_trais
{
// Algorithm names
template <typename AlgorithmT> const char *name();
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
{
@@ -51,62 +57,49 @@ template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
{
};
template <> struct HasAlternativePathSearch<algorithm::CH> final : std::true_type
// Algorithms supported by Contraction Hierarchies
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::CH> final : std::true_type
template <> struct HasShortestPathSearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::CH> final : std::true_type
template <> struct HasDirectShortestPathSearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::CH> final : std::true_type
template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::CH> final : std::true_type
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<algorithm::CH> final : std::true_type
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
{
};
// disbaled because of perfomance reasons
template <> struct HasAlternativePathSearch<algorithm::CoreCH> final : std::false_type
// Algorithms supported by Contraction Hierarchies with core
// the rest is disabled because of performance reasons
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::CoreCH> final : std::false_type
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::CoreCH> final : std::true_type
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasGetTileTurns<algorithm::CoreCH> final : std::true_type
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
{
};
// disbaled because of perfomance reasons
template <> struct HasAlternativePathSearch<algorithm::MLD> final : std::false_type
// Algorithms supported by Multi-Level Dijkstra
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::MLD> final : std::false_type
template <> struct HasShortestPathSearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::MLD> final : std::false_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::MLD> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::MLD> final : std::false_type
{
};
template <> struct HasGetTileTurns<algorithm::MLD> final : std::false_type
template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
{
};
}
+8 -7
View File
@@ -80,22 +80,21 @@ inline Result keep_all(const MatchParameters &params)
inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
BOOST_ASSERT(!params.coordinates.empty());
Result result;
result.can_be_removed.resize(params.coordinates.size(), false);
result.tidied_to_original.push_back(0);
std::size_t last_good = 0;
const auto uses_timestamps = !params.timestamps.empty();
Thresholds running{0., 0};
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
for (std::size_t current = 0, next = 1; next < params.coordinates.size() - 1; ++current, ++next)
{
const auto next = current + 1;
auto distance_delta = util::coordinate_calculation::haversineDistance(
params.coordinates[current], params.coordinates[next]);
running.distance_in_meters += distance_delta;
@@ -109,7 +108,6 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
if (over_distance && over_duration)
{
last_good = next;
result.tidied_to_original.push_back(next);
running = {0., 0}; // reset running distance and time
}
@@ -122,7 +120,6 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
if (over_distance)
{
last_good = next;
result.tidied_to_original.push_back(next);
running = {0., 0}; // reset running distance and time
}
@@ -133,7 +130,11 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
}
}
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
// Always use the last coordinate if more than two original coordinates
if (params.coordinates.size() > 1)
{
result.tidied_to_original.push_back(params.coordinates.size() - 1);
}
// We have to filter parallel arrays that may be empty or the exact same size.
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
+2 -2
View File
@@ -167,8 +167,8 @@ class RouteAPI : public BaseAPI
*/
guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::collapseTurnInstructions(std::move(steps));
leg.steps = guidance::postProcess(std::move(leg.steps));
leg.steps = guidance::postProcess(std::move(steps));
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
leg.steps = guidance::buildIntersections(std::move(leg.steps));
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
@@ -17,11 +17,16 @@ namespace engine
namespace datafacade
{
// Namespace local aliases for algorithms
using CH = routing_algorithms::ch::Algorithm;
using CoreCH = routing_algorithms::corech::Algorithm;
using MLD = routing_algorithms::mld::Algorithm;
using EdgeRange = util::range<EdgeID>;
template <typename AlgorithmT> class AlgorithmDataFacade;
template <> class AlgorithmDataFacade<algorithm::CH>
template <> class AlgorithmDataFacade<CH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
@@ -56,7 +61,7 @@ template <> class AlgorithmDataFacade<algorithm::CH>
const std::function<bool(EdgeData)> filter) const = 0;
};
template <> class AlgorithmDataFacade<algorithm::CoreCH>
template <> class AlgorithmDataFacade<CoreCH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
@@ -64,7 +69,7 @@ template <> class AlgorithmDataFacade<algorithm::CoreCH>
virtual bool IsCoreNode(const NodeID id) const = 0;
};
template <> class AlgorithmDataFacade<algorithm::MLD>
template <> class AlgorithmDataFacade<MLD>
{
public:
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
@@ -15,11 +15,15 @@
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/segment_data_container.hpp"
#include "extractor/turn_data_container.hpp"
#include "contractor/query_graph.hpp"
#include "partition/cell_storage.hpp"
#include "partition/multi_level_partition.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory_ownership.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
@@ -57,15 +61,14 @@ namespace datafacade
template <typename AlgorithmT> class ContiguousInternalMemoryAlgorithmDataFacade;
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
: public datafacade::AlgorithmDataFacade<algorithm::CH>
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
{
private:
using QueryGraph = util::StaticGraph<EdgeData, true>;
using QueryGraph = contractor::QueryGraphView;
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
std::unique_ptr<QueryGraph> m_query_graph;
QueryGraph m_query_graph;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
@@ -78,11 +81,11 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
util::ShM<GraphNode, true>::vector node_list(
util::vector_view<GraphNode> node_list(
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
util::ShM<GraphEdge, true>::vector edge_list(
util::vector_view<GraphEdge> edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
m_query_graph.reset(new QueryGraph(node_list, edge_list));
m_query_graph = QueryGraph(node_list, edge_list);
}
public:
@@ -99,62 +102,62 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
}
// search graph access
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
unsigned GetNumberOfNodes() const override final { return m_query_graph.GetNumberOfNodes(); }
unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final
{
return m_query_graph->GetOutDegree(n);
return m_query_graph.GetOutDegree(n);
}
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); }
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); }
EdgeData &GetEdgeData(const EdgeID e) const override final
const EdgeData &GetEdgeData(const EdgeID e) const override final
{
return m_query_graph->GetEdgeData(e);
return m_query_graph.GetEdgeData(e);
}
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); }
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph.BeginEdges(n); }
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); }
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph.EndEdges(n); }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return m_query_graph->GetAdjacentEdgeRange(node);
return m_query_graph.GetAdjacentEdgeRange(node);
}
// searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const override final
{
return m_query_graph->FindEdge(from, to);
return m_query_graph.FindEdge(from, to);
}
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final
{
return m_query_graph->FindEdgeInEitherDirection(from, to);
return m_query_graph.FindEdgeInEitherDirection(from, to);
}
EdgeID
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final
{
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
return m_query_graph.FindEdgeIndicateIfReverse(from, to, result);
}
EdgeID FindSmallestEdge(const NodeID from,
const NodeID to,
std::function<bool(EdgeData)> filter) const override final
{
return m_query_graph->FindSmallestEdge(from, to, filter);
return m_query_graph.FindSmallestEdge(from, to, filter);
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
: public datafacade::AlgorithmDataFacade<algorithm::CoreCH>
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
: public datafacade::AlgorithmDataFacade<CoreCH>
{
private:
util::ShM<bool, true>::vector m_is_core_node;
util::vector_view<bool> m_is_core_node;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
@@ -163,7 +166,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
{
auto core_marker_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
util::ShM<bool, true>::vector is_core_node(
util::vector_view<bool> is_core_node(
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
m_is_core_node = std::move(is_core_node);
}
@@ -199,10 +202,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
private:
using super = BaseDataFacade;
using IndexBlock = util::RangeTable<16, true>::BlockT;
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
using RTreeLeaf = super::RTreeLeaf;
using SharedRTree =
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>;
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using RTreeNode = SharedRTree::TreeNode;
@@ -211,28 +213,20 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
extractor::Datasources *m_datasources;
unsigned m_check_sum;
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
util::ShM<GeometryID, true>::vector m_via_geometry_list;
util::ShM<NameID, true>::vector m_name_ID_list;
util::ShM<LaneDataID, true>::vector m_lane_data_id;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
util::ShM<util::guidance::TurnBearing, true>::vector m_pre_turn_bearing;
util::ShM<util::guidance::TurnBearing, true>::vector m_post_turn_bearing;
util::vector_view<util::Coordinate> m_coordinate_list;
util::PackedVectorView<OSMNodeID> m_osmnodeid_list;
util::NameTable m_names_table;
util::ShM<unsigned, true>::vector m_name_begin_indices;
util::ShM<bool, true>::vector m_is_core_node;
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
util::ShM<TurnPenalty, true>::vector m_turn_weight_penalties;
util::ShM<TurnPenalty, true>::vector m_turn_duration_penalties;
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;
util::vector_view<TurnPenalty> m_turn_duration_penalties;
extractor::SegmentDataView segment_data;
extractor::TurnDataView turn_data;
util::ShM<char, true>::vector m_datasource_name_data;
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
util::ShM<util::guidance::LaneTupleIdPair, true>::vector m_lane_tupel_id_pairs;
util::vector_view<char> m_datasource_name_data;
util::vector_view<std::size_t> m_datasource_name_offsets;
util::vector_view<std::size_t> m_datasource_name_lengths;
util::vector_view<util::guidance::LaneTupleIdPair> m_lane_tupel_id_pairs;
std::unique_ptr<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
@@ -240,17 +234,17 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
util::NameTable m_name_table;
// bearing classes by node based node
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
util::vector_view<BearingClassID> m_bearing_class_id_table;
// entry class IDs
util::ShM<EntryClassID, true>::vector m_entry_class_id_list;
util::vector_view<EntryClassID> m_entry_class_id_list;
// 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::ShM<util::guidance::EntryClass, true>::vector m_entry_class_table;
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, true>> m_bearing_ranges_table;
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
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;
@@ -303,8 +297,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void InitializeNodeAndEdgeInformationPointers(storage::DataLayout &data_layout,
char *memory_block)
void InitializeNodeInformationPointers(storage::DataLayout &data_layout, char *memory_block)
{
const auto coordinate_list_ptr = data_layout.GetBlockPtr<util::Coordinate>(
memory_block, storage::DataLayout::COORDINATE_LIST);
@@ -323,66 +316,59 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
// We (ab)use the number of coordinates here because we know we have the same amount of ids
m_osmnodeid_list.set_number_of_entries(
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
const auto travel_mode_list_ptr = data_layout.GetBlockPtr<extractor::TravelMode>(
memory_block, storage::DataLayout::TRAVEL_MODE);
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list);
const auto lane_data_id_ptr =
data_layout.GetBlockPtr<LaneDataID>(memory_block, storage::DataLayout::LANE_DATA_ID);
util::ShM<LaneDataID, true>::vector lane_data_id(
lane_data_id_ptr, data_layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
m_lane_data_id = std::move(lane_data_id);
const auto lane_tupel_id_pair_ptr =
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
memory_block, storage::DataLayout::TURN_LANE_DATA);
util::ShM<util::guidance::LaneTupleIdPair, true>::vector lane_tupel_id_pair(
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
const auto turn_instruction_list_ptr =
data_layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
memory_block, storage::DataLayout::TURN_INSTRUCTION);
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr,
data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list = std::move(turn_instruction_list);
const auto name_id_list_ptr =
data_layout.GetBlockPtr<NameID>(memory_block, storage::DataLayout::NAME_ID_LIST);
util::ShM<NameID, true>::vector name_id_list(
name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
m_name_ID_list = std::move(name_id_list);
const auto entry_class_id_list_ptr =
data_layout.GetBlockPtr<EntryClassID>(memory_block, storage::DataLayout::ENTRY_CLASSID);
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
m_entry_class_id_list = std::move(entry_class_id_list);
const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_block, storage::DataLayout::PRE_TURN_BEARING);
typename util::ShM<util::guidance::TurnBearing, true>::vector pre_turn_bearing(
pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
m_pre_turn_bearing = std::move(pre_turn_bearing);
const auto post_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_block, storage::DataLayout::POST_TURN_BEARING);
typename util::ShM<util::guidance::TurnBearing, true>::vector post_turn_bearing(
post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
m_post_turn_bearing = std::move(post_turn_bearing);
}
void InitializeViaNodeListPointer(storage::DataLayout &data_layout, char *memory_block)
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
{
auto via_geometry_list_ptr =
data_layout.GetBlockPtr<GeometryID>(memory_block, storage::DataLayout::VIA_NODE_LIST);
util::ShM<GeometryID, true>::vector via_geometry_list(
via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
m_via_geometry_list = std::move(via_geometry_list);
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::VIA_NODE_LIST);
util::vector_view<GeometryID> geometry_ids(
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
const auto travel_mode_list_ptr =
layout.GetBlockPtr<extractor::TravelMode>(memory_ptr, storage::DataLayout::TRAVEL_MODE);
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
const auto lane_data_id_ptr =
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
util::vector_view<LaneDataID> lane_data_ids(
lane_data_id_ptr, layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
const auto turn_instruction_list_ptr =
layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
memory_ptr, storage::DataLayout::TURN_INSTRUCTION);
util::vector_view<extractor::guidance::TurnInstruction> turn_instructions(
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
const auto name_id_list_ptr =
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST);
util::vector_view<NameID> name_ids(name_id_list_ptr,
layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
const auto entry_class_id_list_ptr =
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
util::vector_view<EntryClassID> entry_class_ids(
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
util::vector_view<util::guidance::TurnBearing> pre_turn_bearings(
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
const auto post_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
turn_data = extractor::TurnDataView(std::move(geometry_ids),
std::move(name_ids),
std::move(turn_instructions),
std::move(lane_data_ids),
std::move(travel_modes),
std::move(entry_class_ids),
std::move(pre_turn_bearings),
std::move(post_turn_bearings));
}
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
@@ -398,28 +384,35 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
auto offsets_ptr = data_layout.GetBlockPtr<std::uint32_t>(
memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS);
util::ShM<std::uint32_t, true>::vector offsets(
util::vector_view<std::uint32_t> offsets(
offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]);
m_lane_description_offsets = std::move(offsets);
auto masks_ptr = data_layout.GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS);
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector masks(
util::vector_view<extractor::guidance::TurnLaneType::Mask> masks(
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
m_lane_description_masks = std::move(masks);
const auto lane_tupel_id_pair_ptr =
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
memory_block, storage::DataLayout::TURN_LANE_DATA);
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
}
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
{
auto turn_weight_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES);
m_turn_weight_penalties = util::ShM<TurnPenalty, true>::vector(
m_turn_weight_penalties = util::vector_view<TurnPenalty>(
turn_weight_penalties_ptr,
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
auto turn_duration_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
memory_block, storage::DataLayout::TURN_DURATION_PENALTIES);
m_turn_duration_penalties = util::ShM<TurnPenalty, true>::vector(
m_turn_duration_penalties = util::vector_view<TurnPenalty>(
turn_duration_penalties_ptr,
data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]);
}
@@ -428,42 +421,42 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
auto geometries_index_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::GEOMETRIES_INDEX);
util::ShM<unsigned, true>::vector geometry_begin_indices(
util::vector_view<unsigned> geometry_begin_indices(
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::ShM<NodeID, true>::vector geometry_node_list(
util::vector_view<NodeID> geometry_node_list(
geometries_node_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]);
auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
util::ShM<EdgeWeight, true>::vector geometry_fwd_weight_list(
util::vector_view<EdgeWeight> geometry_fwd_weight_list(
geometries_fwd_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
util::ShM<EdgeWeight, true>::vector geometry_rev_weight_list(
util::vector_view<EdgeWeight> geometry_rev_weight_list(
geometries_rev_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
util::ShM<EdgeWeight, true>::vector geometry_fwd_duration_list(
util::vector_view<EdgeWeight> geometry_fwd_duration_list(
geometries_fwd_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
util::ShM<EdgeWeight, true>::vector geometry_rev_duration_list(
util::vector_view<EdgeWeight> geometry_rev_duration_list(
geometries_rev_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]);
auto datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
memory_block, storage::DataLayout::DATASOURCES_LIST);
util::ShM<DatasourceID, true>::vector datasources_list(
util::vector_view<DatasourceID> datasources_list(
datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]);
segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices),
@@ -482,13 +475,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
memory_block, storage::DataLayout::BEARING_CLASSID);
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
typename util::vector_view<BearingClassID> bearing_class_id_table(
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>(
memory_block, storage::DataLayout::BEARING_VALUES);
typename util::ShM<DiscreteBearing, true>::vector bearing_class_table(
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);
@@ -496,17 +489,17 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
auto blocks_ptr =
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::BEARING_BLOCKS);
util::ShM<unsigned, true>::vector bearing_offsets(
util::vector_view<unsigned> bearing_offsets(
offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]);
util::ShM<IndexBlock, true>::vector bearing_blocks(
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, true>>(
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()));
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
memory_block, storage::DataLayout::ENTRY_CLASS);
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
typename 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);
}
@@ -514,11 +507,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeChecksumPointer(data_layout, memory_block);
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
InitializeNodeInformationPointers(data_layout, memory_block);
InitializeEdgeInformationPointers(data_layout, memory_block);
InitializeTurnPenalties(data_layout, memory_block);
InitializeGeometryPointers(data_layout, memory_block);
InitializeTimestampPointer(data_layout, memory_block);
InitializeViaNodeListPointer(data_layout, memory_block);
InitializeNamePointers(data_layout, memory_block);
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
InitializeProfilePropertiesPointer(data_layout, memory_block);
@@ -607,7 +600,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final
{
return m_via_geometry_list.at(id);
return turn_data.GetGeometryID(id);
}
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
@@ -625,12 +618,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const EdgeID id) const override final
{
return m_turn_instruction_list.at(id);
return turn_data.GetTurnInstruction(id);
}
extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final
{
return m_travel_mode_list.at(id);
return turn_data.GetTravelMode(id);
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
@@ -752,7 +745,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
NameID GetNameIndexFromEdgeID(const EdgeID id) const override final
{
return m_name_ID_list.at(id);
return turn_data.GetNameID(id);
}
StringView GetNameForID(const NameID id) const override final
@@ -824,16 +817,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return m_entry_class_id_list.at(eid);
return turn_data.GetEntryClassID(eid);
}
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
{
return m_pre_turn_bearing.at(eid);
return turn_data.GetPreTurnBearing(eid);
}
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
{
return m_post_turn_bearing.at(eid);
return turn_data.GetPostTurnBearing(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
@@ -841,15 +834,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return INVALID_LANE_DATAID != m_lane_data_id.at(id);
}
bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); }
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
BOOST_ASSERT(HasLaneData(id));
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id));
}
extractor::guidance::TurnLaneDescription
@@ -868,36 +858,34 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
template <>
class ContiguousInternalMemoryDataFacade<algorithm::CH>
class ContiguousInternalMemoryDataFacade<CH>
: public ContiguousInternalMemoryDataFacadeBase,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>(allocator)
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator)
{
}
};
template <>
class ContiguousInternalMemoryDataFacade<algorithm::CoreCH> final
: public ContiguousInternalMemoryDataFacade<algorithm::CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
class ContiguousInternalMemoryDataFacade<CoreCH> final
: public ContiguousInternalMemoryDataFacade<CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacade<algorithm::CH>(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>(allocator)
: ContiguousInternalMemoryDataFacade<CH>(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator)
{
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
: public datafacade::AlgorithmDataFacade<algorithm::MLD>
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
{
// MLD data
partition::MultiLevelPartitionView mld_partition;
@@ -922,22 +910,20 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
auto level_data =
*data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
memory_block, storage::DataLayout::MLD_LEVEL_DATA);
auto mld_partition_ptr = data_layout.GetBlockPtr<PartitionID>(
memory_block, storage::DataLayout::MLD_PARTITION);
auto partition_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION);
util::ShM<PartitionID, true>::vector partition(mld_partition_ptr,
partition_entries_count);
util::vector_view<PartitionID> partition(mld_partition_ptr, partition_entries_count);
auto mld_chilren_ptr = data_layout.GetBlockPtr<CellID>(
memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN);
auto children_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN);
util::ShM<CellID, true>::vector cell_to_children(mld_chilren_ptr,
children_entries_count);
util::vector_view<CellID> cell_to_children(mld_chilren_ptr, children_entries_count);
mld_partition =
partition::MultiLevelPartitionView{level_data, partition, cell_to_children};
@@ -969,15 +955,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
auto cell_level_offsets_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
util::ShM<EdgeWeight, true>::vector weights(mld_cell_weights_ptr, weight_entries_count);
util::ShM<NodeID, true>::vector source_boundary(mld_source_boundary_ptr,
source_boundary_entries_count);
util::ShM<NodeID, true>::vector destination_boundary(
mld_destination_boundary_ptr, destination_boundary_entries_count);
util::ShM<partition::CellStorageView::CellData, true>::vector cells(
mld_cells_ptr, cells_entries_counts);
util::ShM<std::uint64_t, true>::vector level_offsets(mld_cell_level_offsets_ptr,
cell_level_offsets_entries_count);
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_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,
destination_boundary_entries_count);
util::vector_view<partition::CellStorageView::CellData> cells(mld_cells_ptr,
cells_entries_counts);
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
cell_level_offsets_entries_count);
mld_cell_storage = partition::CellStorageView{std::move(weights),
std::move(source_boundary),
@@ -997,11 +983,11 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
auto graph_node_to_offset_ptr = data_layout.GetBlockPtr<QueryGraph::EdgeOffset>(
memory_block, storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET);
util::ShM<GraphNode, true>::vector node_list(
util::vector_view<GraphNode> node_list(
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]);
util::ShM<GraphEdge, true>::vector edge_list(
util::vector_view<GraphEdge> edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]);
util::ShM<QueryGraph::EdgeOffset, true>::vector node_to_offset(
util::vector_view<QueryGraph::EdgeOffset> node_to_offset(
graph_node_to_offset_ptr,
data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]);
@@ -1066,15 +1052,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
};
template <>
class ContiguousInternalMemoryDataFacade<algorithm::MLD> final
class ContiguousInternalMemoryDataFacade<MLD> final
: public ContiguousInternalMemoryDataFacadeBase,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
public ContiguousInternalMemoryAlgorithmDataFacade<MLD>
{
private:
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>(allocator)
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator)
{
}
@@ -130,7 +130,7 @@ class BaseDataFacade
const int bearing,
const int bearing_range) const = 0;
virtual bool hasLaneData(const EdgeID id) const = 0;
virtual bool HasLaneData(const EdgeID id) const = 0;
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
virtual extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
+18 -17
View File
@@ -49,7 +49,7 @@ class EngineInterface
virtual Status Tile(const api::TileParameters &parameters, std::string &result) const = 0;
};
template <typename AlgorithmT> class Engine final : public EngineInterface
template <typename Algorithm> class Engine final : public EngineInterface
{
public:
explicit Engine(const EngineConfig &config)
@@ -64,15 +64,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
if (config.use_shared_memory)
{
util::Log(logDEBUG) << "Using shared memory with algorithm "
<< algorithm::name<AlgorithmT>();
facade_provider = std::make_unique<WatchingProvider<AlgorithmT>>();
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<WatchingProvider<Algorithm>>();
}
else
{
util::Log(logDEBUG) << "Using internal memory with algorithm "
<< algorithm::name<AlgorithmT>();
facade_provider =
std::make_unique<ImmutableProvider<AlgorithmT>>(config.storage_config);
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ImmutableProvider<Algorithm>>(config.storage_config);
}
}
@@ -87,7 +86,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return route_plugin.HandleRequest(*facade, algorithms, params, result);
}
@@ -95,7 +94,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return table_plugin.HandleRequest(*facade, algorithms, params, result);
}
@@ -103,14 +102,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return nearest_plugin.HandleRequest(*facade, algorithms, params, result);
}
Status Trip(const api::TripParameters &params, util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return trip_plugin.HandleRequest(*facade, algorithms, params, result);
}
@@ -118,22 +117,22 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return match_plugin.HandleRequest(*facade, algorithms, params, result);
}
Status Tile(const api::TileParameters &params, std::string &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return tile_plugin.HandleRequest(*facade, algorithms, params, result);
}
static bool CheckCompability(const EngineConfig &config);
private:
std::unique_ptr<DataFacadeProvider<AlgorithmT>> facade_provider;
mutable SearchEngineData heaps;
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
mutable SearchEngineData<Algorithm> heaps;
const plugins::ViaRoutePlugin route_plugin;
const plugins::TablePlugin table_plugin;
@@ -143,7 +142,8 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
const plugins::TilePlugin tile_plugin;
};
template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &config)
template <>
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (config.use_shared_memory)
{
@@ -168,9 +168,10 @@ template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &con
}
}
template <> bool Engine<algorithm::CoreCH>::CheckCompability(const EngineConfig &config)
template <>
bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (!Engine<algorithm::CH>::CheckCompability(config))
if (!Engine<routing_algorithms::ch::Algorithm>::CheckCompability(config))
{
return false;
}
+18
View File
@@ -416,6 +416,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
}
// check phantom node segments validity
auto areSegmentsValid = [](auto first, auto last) -> bool {
return std::find(first, last, INVALID_EDGE_WEIGHT) == last;
};
bool is_forward_valid_source =
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
bool is_forward_valid_target =
areSegmentsValid(forward_weight_vector.begin(),
forward_weight_vector.begin() + data.fwd_segment_position + 1);
bool is_reverse_valid_source =
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
bool is_reverse_valid_target = areSegmentsValid(
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
forward_weight,
reverse_weight,
@@ -425,6 +439,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_duration,
forward_duration_offset,
reverse_duration_offset,
is_forward_valid_source,
is_forward_valid_target,
is_reverse_valid_source,
is_reverse_valid_target,
point_on_segment,
input_coordinate},
current_perpendicular_distance};
+5 -2
View File
@@ -170,10 +170,13 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
weight = weight + target_weight;
if (route_data.empty())
{
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
weight -=
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
duration = std::max(0, duration);
}
std::string summary;
+6 -3
View File
@@ -222,10 +222,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// u-------------v
// | |---------| source_weight
// | |---| target_weight
BOOST_ASSERT(target_weight >= source_weight);
const EdgeWeight weight = target_weight - source_weight;
const EdgeWeight duration = target_duration - source_duration;
BOOST_ASSERT(weight >= 0);
BOOST_ASSERT(duration >= 0);
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
const EdgeWeight duration = std::max(0, target_duration - source_duration);
steps.push_back(RouteStep{source_node.name_id,
facade.GetNameForID(source_node.name_id).to_string(),
+37 -35
View File
@@ -46,37 +46,6 @@ namespace engine
struct PhantomNode
{
PhantomNode(SegmentID forward_segment_id,
SegmentID reverse_segment_id,
unsigned name_id,
EdgeWeight forward_weight,
EdgeWeight reverse_weight,
EdgeWeight forward_weight_offset,
EdgeWeight reverse_weight_offset,
EdgeWeight forward_duration,
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
unsigned packed_geometry_id_,
bool is_tiny_component,
unsigned component_id,
util::Coordinate location,
util::Coordinate input_location,
unsigned short fwd_segment_position,
extractor::TravelMode forward_travel_mode,
extractor::TravelMode backward_travel_mode)
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
forward_weight_offset(forward_weight_offset),
reverse_weight_offset(reverse_weight_offset), forward_duration(forward_duration),
reverse_duration(reverse_duration), forward_duration_offset(forward_duration_offset),
reverse_duration_offset(reverse_duration_offset), packed_geometry_id(packed_geometry_id_),
component{component_id, is_tiny_component}, location(std::move(location)),
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
{
}
PhantomNode()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false},
@@ -86,7 +55,9 @@ struct PhantomNode
forward_duration_offset(0), reverse_duration_offset(0),
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE), is_valid_forward_source(false),
is_valid_forward_target(false), is_valid_reverse_source(false),
is_valid_reverse_target(false)
{
}
@@ -134,6 +105,23 @@ struct PhantomNode
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
bool IsValidForwardSource() const
{
return forward_segment_id.enabled && is_valid_forward_source;
}
bool IsValidForwardTarget() const
{
return forward_segment_id.enabled && is_valid_forward_target;
}
bool IsValidReverseSource() const
{
return reverse_segment_id.enabled && is_valid_reverse_source;
}
bool IsValidReverseTarget() const
{
return reverse_segment_id.enabled && is_valid_reverse_target;
}
bool operator==(const PhantomNode &other) const { return location == other.location; }
template <class OtherT>
@@ -146,6 +134,10 @@ struct PhantomNode
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
bool is_valid_forward_source,
bool is_valid_forward_target,
bool is_valid_reverse_source,
bool is_valid_reverse_target,
const util::Coordinate location,
const util::Coordinate input_location)
: forward_segment_id{other.forward_segment_id},
@@ -159,7 +151,11 @@ struct PhantomNode
component{other.component.id, other.component.is_tiny}, location{location},
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
forward_travel_mode{other.forward_travel_mode},
backward_travel_mode{other.backward_travel_mode}
backward_travel_mode{other.backward_travel_mode},
is_valid_forward_source{is_valid_forward_source},
is_valid_forward_target{is_valid_forward_target},
is_valid_reverse_source{is_valid_reverse_source},
is_valid_reverse_target{is_valid_reverse_target}
{
}
@@ -187,8 +183,14 @@ struct PhantomNode
unsigned short fwd_segment_position;
// note 4 bits would suffice for each,
// but the saved byte would be padding anyway
extractor::TravelMode forward_travel_mode;
extractor::TravelMode backward_travel_mode;
extractor::TravelMode forward_travel_mode : 4;
extractor::TravelMode backward_travel_mode : 4;
// is phantom node valid to be used as source or target
private:
bool is_valid_forward_source : 1;
bool is_valid_forward_target : 1;
bool is_valid_reverse_source : 1;
bool is_valid_reverse_target : 1;
};
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
+55 -53
View File
@@ -54,11 +54,11 @@ class RoutingAlgorithmsInterface
};
// Short-lived object passed to each plugin in request to wrap routing algorithms
template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
{
public:
RoutingAlgorithms(SearchEngineData &heaps,
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade)
RoutingAlgorithms(SearchEngineData<Algorithm> &heaps,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade)
: heaps(heaps), facade(facade)
{
}
@@ -93,49 +93,50 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
bool HasAlternativePathSearch() const final override
{
return algorithm_trais::HasAlternativePathSearch<AlgorithmT>::value;
return routing_algorithms::HasAlternativePathSearch<Algorithm>::value;
}
bool HasShortestPathSearch() const final override
{
return algorithm_trais::HasShortestPathSearch<AlgorithmT>::value;
return routing_algorithms::HasShortestPathSearch<Algorithm>::value;
}
bool HasDirectShortestPathSearch() const final override
{
return algorithm_trais::HasDirectShortestPathSearch<AlgorithmT>::value;
return routing_algorithms::HasDirectShortestPathSearch<Algorithm>::value;
}
bool HasMapMatching() const final override
{
return algorithm_trais::HasMapMatching<AlgorithmT>::value;
return routing_algorithms::HasMapMatching<Algorithm>::value;
}
bool HasManyToManySearch() const final override
{
return algorithm_trais::HasManyToManySearch<AlgorithmT>::value;
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
}
bool HasGetTileTurns() const final override
{
return algorithm_trais::HasGetTileTurns<AlgorithmT>::value;
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
}
private:
SearchEngineData &heaps;
SearchEngineData<Algorithm> &heaps;
// Owned by shared-ptr passed to the query
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade;
};
template <typename AlgorithmT>
template <typename Algorithm>
InternalRouteResult
RoutingAlgorithms<AlgorithmT>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
{
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
}
template <typename AlgorithmT>
InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
template <typename Algorithm>
InternalRouteResult RoutingAlgorithms<Algorithm>::ShortestPathSearch(
const std::vector<PhantomNodes> &phantom_node_pair,
const boost::optional<bool> continue_straight_at_waypoint) const
{
@@ -143,25 +144,25 @@ InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
}
template <typename AlgorithmT>
template <typename Algorithm>
InternalRouteResult
RoutingAlgorithms<AlgorithmT>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
{
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
}
template <typename AlgorithmT>
std::vector<EdgeWeight> RoutingAlgorithms<AlgorithmT>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
template <typename Algorithm>
std::vector<EdgeWeight>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::manyToManySearch(
return routing_algorithms::ch::manyToManySearch(
heaps, facade, phantom_nodes, source_indices, target_indices);
}
template <typename AlgorithmT>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMatching(
template <typename Algorithm>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
const routing_algorithms::CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
@@ -177,52 +178,53 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMat
allow_splitting);
}
template <typename AlgorithmT>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<AlgorithmT>::GetTileTurns(
template <typename Algorithm>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::GetTileTurns(
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes) const
{
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
}
// CoreCH overrides
template <>
InternalRouteResult inline RoutingAlgorithms<
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
{
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
}
template <>
inline std::vector<EdgeWeight>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
{
throw util::exception("ManyToManySearch is disabled due to performance reasons");
}
// MLD overrides for not implemented
template <>
InternalRouteResult inline RoutingAlgorithms<algorithm::MLD>::AlternativePathSearch(
const PhantomNodes &) const
InternalRouteResult inline RoutingAlgorithms<
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
{
throw util::exception("AlternativePathSearch is not implemented");
}
template <>
inline InternalRouteResult
RoutingAlgorithms<algorithm::MLD>::ShortestPathSearch(const std::vector<PhantomNodes> &,
const boost::optional<bool>) const
{
throw util::exception("ShortestPathSearch is not implemented");
}
template <>
inline std::vector<EdgeWeight>
RoutingAlgorithms<algorithm::MLD>::ManyToManySearch(const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
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");
}
template <>
inline routing_algorithms::SubMatchingList
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
const std::vector<util::Coordinate> &,
const std::vector<unsigned> &,
const std::vector<boost::optional<double>> &,
const bool) const
{
throw util::exception("MapMatching is not implemented");
}
template <>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<algorithm::MLD>::GetTileTurns(
inline std::vector<routing_algorithms::TurnData>
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::GetTileTurns(
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &,
const std::vector<std::size_t> &) const
{
@@ -15,12 +15,13 @@ namespace engine
{
namespace routing_algorithms
{
namespace ch
{
InternalRouteResult
alternativePathSearch(SearchEngineData &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const PhantomNodes &phantom_node_pair);
} // namespace ch
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -21,11 +21,20 @@ namespace routing_algorithms
/// by the previous route.
/// This variation is only an optimazation for graphs with slow queries, for example
/// not fully contracted graphs.
template <typename AlgorithmT>
InternalRouteResult
directShortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
const PhantomNodes &phantom_nodes);
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);
} // namespace routing_algorithms
} // namespace engine
@@ -13,16 +13,18 @@ namespace osrm
{
namespace engine
{
namespace routing_algorithms
{
namespace ch
{
std::vector<EdgeWeight>
manyToManySearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
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
@@ -22,25 +22,17 @@ static const constexpr double DEFAULT_GPS_PRECISION = 5;
//[1] "Hidden Markov Map Matching Through Noise and Sparseness";
// P. Newson and J. Krumm; 2009; ACM GIS
SubMatchingList
mapMatching(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision,
const bool allow_splitting);
template <typename Algorithm>
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision,
const bool allow_splitting);
SubMatchingList
mapMatching(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision,
const bool allow_splitting);
}
}
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
#endif /* MAP_MATCHING_HPP */
@@ -37,53 +37,48 @@ static constexpr bool FORWARD_DIRECTION = true;
static constexpr bool REVERSE_DIRECTION = false;
static constexpr bool DO_NOT_FORCE_LOOPS = false;
template <bool DIRECTION, typename Heap>
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
{
BOOST_ASSERT(phantom_node.IsValid());
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
if (phantom_node.forward_segment_id.enabled)
{
heap.Insert(phantom_node.forward_segment_id.id,
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_segment_id.id);
}
if (phantom_node.reverse_segment_id.enabled)
{
heap.Insert(phantom_node.reverse_segment_id.id,
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
phantom_node.reverse_segment_id.id);
}
}
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
template <bool DIRECTION>
void insertNodesInHeap(SearchEngineData::ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
{
BOOST_ASSERT(phantom_node.IsValid());
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
if (phantom_node.forward_segment_id.enabled)
{
heap.Insert(
phantom_node.forward_segment_id.id,
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, weight_sign * phantom_node.GetForwardDuration()});
}
if (phantom_node.reverse_segment_id.enabled)
{
heap.Insert(
phantom_node.reverse_segment_id.id,
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, weight_sign * phantom_node.GetReverseDuration()});
}
}
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
{
insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
const auto &source = nodes.source_phantom;
if (source.IsValidForwardSource())
{
forward_heap.Insert(source.forward_segment_id.id,
-source.GetForwardWeightPlusOffset(),
source.forward_segment_id.id);
}
if (source.IsValidReverseSource())
{
forward_heap.Insert(source.reverse_segment_id.id,
-source.GetReverseWeightPlusOffset(),
source.reverse_segment_id.id);
}
const auto &target = nodes.target_phantom;
if (target.IsValidForwardTarget())
{
reverse_heap.Insert(target.forward_segment_id.id,
target.GetForwardWeightPlusOffset(),
target.forward_segment_id.id);
}
if (target.IsValidReverseTarget())
{
reverse_heap.Insert(target.reverse_segment_id.id,
target.GetReverseWeightPlusOffset(),
target.reverse_segment_id.id);
}
}
template <typename FacadeT>
@@ -169,7 +164,7 @@ void annotatePath(const FacadeT &facade,
util::guidance::TurnBearing(0)});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.hasLaneData(turn_id))
if (facade.HasLaneData(turn_id))
unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
@@ -305,6 +300,57 @@ void annotatePath(const FacadeT &facade,
}
}
template <typename Algorithm>
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const std::vector<PathData> unpacked_path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom)
{
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
using util::coordinate_calculation::detail::EARTH_RADIUS;
double distance = 0;
double prev_lat = static_cast<double>(toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
double prev_lon = static_cast<double>(toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
double prev_cos = std::cos(prev_lat);
for (const auto &p : unpacked_path)
{
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
const double current_lat =
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
prev_lat = current_lat;
prev_lon = current_lon;
prev_cos = current_cos;
}
const double current_lat =
static_cast<double>(toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
return distance;
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -23,7 +23,7 @@ namespace ch
// Stalling
template <bool DIRECTION, typename HeapT>
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID node,
const EdgeWeight weight,
const HeapT &query_heap)
@@ -49,10 +49,10 @@ bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
}
template <bool DIRECTION>
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID node,
const EdgeWeight weight,
SearchEngineData::QueryHeap &heap)
SearchEngineData<Algorithm>::QueryHeap &heap)
{
for (const auto edge : facade.GetAdjacentEdgeRange(node))
{
@@ -113,9 +113,9 @@ we need to add an offset to the termination criterion.
static constexpr bool ENABLE_STALLING = true;
static constexpr bool DISABLE_STALLING = false;
template <bool DIRECTION, bool STALLING = ENABLE_STALLING>
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node_id,
EdgeWeight &upper_bound,
EdgeWeight min_edge_offset,
@@ -186,9 +186,8 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
}
template <bool UseDuration>
EdgeWeight
getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
NodeID node)
EdgeWeight getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
NodeID node)
{
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
for (auto edge : facade.GetAdjacentEdgeRange(node))
@@ -228,7 +227,7 @@ getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH
* original edge found.
*/
template <typename BidirectionalIterator, typename Callback>
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
Callback &&callback)
@@ -325,17 +324,17 @@ void unpackPath(const FacadeT &facade,
* @param to the node the CH edge finishes at
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
*/
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID from,
const NodeID to,
std::vector<NodeID> &unpacked_path);
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
const SearchEngineData::QueryHeap &reverse_heap,
void retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const NodeID middle_node_id,
std::vector<NodeID> &packed_path);
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &search_heap,
const NodeID middle_node_id,
std::vector<NodeID> &packed_path);
@@ -351,37 +350,33 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
std::int32_t &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &,
SearchEngineData::QueryHeap &,
std::int32_t &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
{
search(facade,
forward_heap,
reverse_heap,
weight,
packed_leg,
force_loop_forward,
force_loop_reverse,
duration_upper_bound);
}
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
} // namespace ch
namespace corech
{
// assumes that heaps are already setup correctly.
// A forced loop might be necessary, if source and target are on the same segment.
// If this is the case and the offsets of the respective direction are larger for the source
@@ -391,66 +386,41 @@ inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorith
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
int &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const std::vector<NodeID> &packed_path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom);
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
inline double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &,
SearchEngineData::QueryHeap &,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT)
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const PhantomNodes &phantom_nodes,
std::vector<PathData> &unpacked_path)
{
return getNetworkDistance(
facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
return ch::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
}
} // namespace ch
} // namespace corech
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -24,9 +24,9 @@ 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
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
NodeID node,
const PhantomNodes &phantom_nodes)
inline LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
NodeID node,
const PhantomNodes &phantom_nodes)
{
auto level = [&partition, node](const SegmentID &source, const SegmentID &target) {
if (source.enabled && target.enabled)
@@ -43,25 +43,31 @@ LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
phantom_nodes.target_phantom.reverse_segment_id)));
}
bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
// Restricted search (Args is LevelID, CellID):
// * use the fixed level for queries
// * check if the node cell is the same as the specified parent onr
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
inline LevelID
getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
{
return level;
}
bool checkParentCellRestriction(CellID cell, LevelID, CellID parent) { return cell == parent; }
inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
{
return cell == parent;
}
}
template <bool DIRECTION, typename... Args>
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
const bool force_loop_forward,
const bool force_loop_reverse,
Args... args)
{
const auto &partition = facade.GetMultiLevelPartition();
@@ -79,7 +85,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
if (path_weight >= 0 && path_weight < path_upper_bound)
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
{
middle_node = node;
path_upper_bound = path_weight;
@@ -171,11 +181,20 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
template <typename... Args>
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
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())
{
return std::make_tuple(
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
}
const auto &partition = facade.GetMultiLevelPartition();
@@ -184,7 +203,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
// run two-Target Dijkstra routing step.
NodeID middle = SPECIAL_NODEID;
EdgeWeight weight = INVALID_EDGE_WEIGHT;
EdgeWeight weight = weight_upper_bound;
EdgeWeight forward_heap_min = forward_heap.MinKey();
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
@@ -192,22 +211,34 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
{
if (!forward_heap.Empty())
{
routingStep<FORWARD_DIRECTION>(
facade, forward_heap, reverse_heap, middle, weight, args...);
routingStep<FORWARD_DIRECTION>(facade,
forward_heap,
reverse_heap,
middle,
weight,
force_loop_forward,
force_loop_reverse,
args...);
if (!forward_heap.Empty())
forward_heap_min = forward_heap.MinKey();
}
if (!reverse_heap.Empty())
{
routingStep<REVERSE_DIRECTION>(
facade, reverse_heap, forward_heap, middle, weight, args...);
routingStep<REVERSE_DIRECTION>(facade,
reverse_heap,
forward_heap,
middle,
weight,
force_loop_reverse,
force_loop_forward,
args...);
if (!reverse_heap.Empty())
reverse_heap_min = reverse_heap.MinKey();
}
};
// No path found for both target nodes?
if (weight == INVALID_EDGE_WEIGHT || SPECIAL_NODEID == middle)
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
{
return std::make_tuple(
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
@@ -268,7 +299,15 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
NodeID subpath_source, subpath_target;
std::vector<EdgeID> subpath;
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
search(facade, forward_heap, reverse_heap, sublevel, parent_cell_id);
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
force_loop_forward,
force_loop_reverse,
INVALID_EDGE_WEIGHT,
sublevel,
parent_cell_id);
BOOST_ASSERT(!subpath.empty());
BOOST_ASSERT(subpath_source == source);
BOOST_ASSERT(subpath_target == target);
@@ -279,6 +318,105 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
}
// TODO reorder parameters
// Alias to be compatible with the overload for CoreCH that needs 4 heaps for shortest path search
inline void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{
NodeID source_node, target_node;
std::vector<EdgeID> unpacked_edges;
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
facade,
forward_heap,
reverse_heap,
force_loop_forward,
force_loop_reverse,
weight_upper_bound,
phantom_nodes);
if (weight != INVALID_EDGE_WEIGHT)
{
packed_leg.push_back(source_node);
std::transform(unpacked_edges.begin(),
unpacked_edges.end(),
std::back_inserter(packed_leg),
[&facade](const auto edge) { return facade.GetTarget(edge); });
}
}
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const PhantomNodes &phantom_nodes,
std::vector<PathData> &unpacked_path)
{
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
BOOST_ASSERT(nodes_number > 0);
std::vector<EdgeID> unpacked_edges;
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
if (nodes_number > 1)
{
target_node = *std::prev(packed_path_end);
util::for_each_pair(packed_path_begin,
packed_path_end,
[&facade, &unpacked_edges](const auto from, const auto to) {
unpacked_edges.push_back(facade.FindEdge(from, to));
});
}
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
}
inline double
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{
forward_heap.Clear();
reverse_heap.Clear();
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
EdgeWeight weight = INVALID_EDGE_WEIGHT;
NodeID source_node, target_node;
std::vector<EdgeID> unpacked_edges;
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
facade,
forward_heap,
reverse_heap,
DO_NOT_FORCE_LOOPS,
DO_NOT_FORCE_LOOPS,
weight_upper_bound,
phantom_nodes);
if (weight == INVALID_EDGE_WEIGHT)
{
return std::numeric_limits<double>::max();
}
std::vector<PathData> unpacked_path;
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
}
} // namespace mld
} // namespace routing_algorithms
} // namespace engine
@@ -13,15 +13,10 @@ namespace engine
namespace routing_algorithms
{
template <typename Algorithm>
InternalRouteResult
shortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint);
InternalRouteResult
shortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint);
@@ -29,7 +29,7 @@ struct TurnData final
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
std::vector<TurnData>
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
const std::vector<RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes);
+45 -24
View File
@@ -3,7 +3,7 @@
#include <boost/thread/tss.hpp>
#include "partition/multi_level_partition.hpp"
#include "engine/algorithm.hpp"
#include "util/binary_heap.hpp"
#include "util/typedefs.hpp"
@@ -12,6 +12,16 @@ namespace osrm
namespace engine
{
// Algorithm-dependent heaps
// - CH algorithms use CH heaps
// - CoreCH algorithms use CoreCH heaps that can be upcasted to CH heaps when CH algorithms reused
// by CoreCH at calling ch::routingStep, ch::retrievePackedPathFromSingleHeap and ch::unpackPath
// - MLD algorithms use MLD heaps
template <typename Algorithm> struct SearchEngineData
{
};
struct HeapData
{
NodeID parent;
@@ -24,14 +34,7 @@ struct ManyToManyHeapData : HeapData
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
};
struct MultiLayerDijkstraHeapData : HeapData
{
bool from_clique_arc;
MultiLayerDijkstraHeapData(NodeID p) : HeapData(p), from_clique_arc(false) {}
MultiLayerDijkstraHeapData(NodeID p, bool from) : HeapData(p), from_clique_arc(from) {}
};
struct SearchEngineData
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
{
using QueryHeap = util::
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
@@ -45,14 +48,6 @@ struct SearchEngineData
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
using MultiLayerDijkstraHeap = util::BinaryHeap<NodeID,
NodeID,
EdgeWeight,
MultiLayerDijkstraHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using MultiLayerDijkstraHeapPtr = boost::thread_specific_ptr<MultiLayerDijkstraHeap>;
static SearchEngineHeapPtr forward_heap_1;
static SearchEngineHeapPtr reverse_heap_1;
static SearchEngineHeapPtr forward_heap_2;
@@ -60,18 +55,44 @@ struct SearchEngineData
static SearchEngineHeapPtr forward_heap_3;
static SearchEngineHeapPtr reverse_heap_3;
static ManyToManyHeapPtr many_to_many_heap;
static MultiLayerDijkstraHeapPtr mld_forward_heap;
static MultiLayerDijkstraHeapPtr mld_reverse_heap;
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearManyToManyThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
};
void InitializeOrClearMultiLayerDijkstraThreadLocalStorage(const unsigned number_of_nodes);
template <>
struct SearchEngineData<routing_algorithms::corech::Algorithm>
: public SearchEngineData<routing_algorithms::ch::Algorithm>
{
};
struct MultiLayerDijkstraHeapData
{
NodeID parent;
bool from_clique_arc;
MultiLayerDijkstraHeapData(NodeID p) : parent(p), from_clique_arc(false) {}
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
};
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
{
using QueryHeap = util::BinaryHeap<NodeID,
NodeID,
EdgeWeight,
MultiLayerDijkstraHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
static SearchEngineHeapPtr forward_heap_1;
static SearchEngineHeapPtr reverse_heap_1;
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
};
}
}
@@ -21,6 +21,7 @@
#include "util/guidance/entry_class.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/packed_vector.hpp"
#include "util/typedefs.hpp"
#include "storage/io.hpp"
@@ -72,7 +73,8 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const util::PackedVector<OSMNodeID> &osm_node_ids,
ProfileProperties profile_properties,
const util::NameTable &name_table,
std::vector<std::uint32_t> &turn_lane_offsets,
@@ -128,7 +130,8 @@ class EdgeBasedGraphFactory
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
EdgeID m_max_edge_id;
const std::vector<QueryNode> &m_node_info_list;
const std::vector<util::Coordinate> &m_coordinates;
const util::PackedVector<OSMNodeID> &m_osm_node_ids;
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
std::shared_ptr<RestrictionMap const> m_restriction_map;
@@ -156,9 +159,6 @@ class EdgeBasedGraphFactory
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
void FlushVectorToStream(storage::io::FileWriter &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
std::size_t restricted_turns_counter;
std::size_t skipped_uturns_counter;
std::size_t skipped_barrier_turns_counter;
+6 -5
View File
@@ -58,7 +58,8 @@ class Extractor
std::pair<std::size_t, EdgeID>
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
std::vector<QueryNode> &internal_to_external_node_map,
std::vector<util::Coordinate> &coordinates,
util::PackedVector<OSMNodeID> &osm_node_ids,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
@@ -66,18 +67,18 @@ class Extractor
const std::string &intersection_class_output_file);
void WriteProfileProperties(const std::string &output_path,
const ProfileProperties &properties) const;
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &edges,
std::vector<EdgeBasedNode> &nodes) const;
void BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
std::vector<bool> node_is_startpoint,
const std::vector<QueryNode> &internal_to_external_node_map);
const std::vector<util::Coordinate> &coordinates);
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
std::shared_ptr<util::NodeBasedDynamicGraph>
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
std::unordered_set<NodeID> &traffic_lights,
std::vector<QueryNode> &internal_to_external_node_map);
std::vector<util::Coordinate> &coordinates,
util::PackedVector<OSMNodeID> &osm_node_ids);
void WriteEdgeBasedGraph(const std::string &output_file_filename,
const EdgeID max_edge_id,
@@ -94,7 +95,7 @@ class Extractor
// 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<QueryNode> &externals);
const std::vector<util::Coordinate> &coordiantes);
// globals persisting during the extraction process and the graph generation process
+182
View File
@@ -0,0 +1,182 @@
#ifndef OSRM_EXTRACTOR_FILES_HPP
#define OSRM_EXTRACTOR_FILES_HPP
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/serialization.hpp"
#include "util/coordinate.hpp"
#include "util/packed_vector.hpp"
#include "util/serialization.hpp"
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
namespace files
{
// reads .osrm.nodes
template <typename CoordinatesT, typename PackedOSMIDsT>
inline void readNodes(const boost::filesystem::path &path,
CoordinatesT &coordinates,
PackedOSMIDsT &osm_node_ids)
{
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
storage::serialization::read(reader, coordinates);
util::serialization::read(reader, osm_node_ids);
}
// writes .osrm.nodes
template <typename CoordinatesT, typename PackedOSMIDsT>
inline void writeNodes(const boost::filesystem::path &path,
const CoordinatesT &coordinates,
const PackedOSMIDsT &osm_node_ids)
{
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, coordinates);
util::serialization::write(writer, osm_node_ids);
}
// reads .osrm.cnbg_to_ebg
inline void readNBGMapping(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
storage::serialization::read(reader, mapping);
}
// writes .osrm.cnbg_to_ebg
inline void writeNBGMapping(const boost::filesystem::path &path,
const std::vector<NBGToEBG> &mapping)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, mapping);
}
// reads .osrm.datasource_names
inline void readDatasources(const boost::filesystem::path &path, Datasources &sources)
{
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, sources);
}
// writes .osrm.datasource_names
inline void writeDatasources(const boost::filesystem::path &path, Datasources &sources)
{
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, sources);
}
// reads .osrm.geometry
template <typename SegmentDataT>
inline void readSegmentData(const boost::filesystem::path &path, SegmentDataT &segment_data)
{
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
std::is_same<SegmentDataView, SegmentDataT>::value,
"");
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, segment_data);
}
// writes .osrm.geometry
template <typename SegmentDataT>
inline void writeSegmentData(const boost::filesystem::path &path, const SegmentDataT &segment_data)
{
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
std::is_same<SegmentDataView, SegmentDataT>::value,
"");
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, segment_data);
}
// reads .osrm.edges
template <typename TurnDataT>
inline void readTurnData(const boost::filesystem::path &path, TurnDataT &turn_data)
{
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
std::is_same<TurnDataView, TurnDataT>::value ||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
"");
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, turn_data);
}
// writes .osrm.edges
template <typename TurnDataT>
inline void writeTurnData(const boost::filesystem::path &path, const TurnDataT &turn_data)
{
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
std::is_same<TurnDataView, TurnDataT>::value ||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
"");
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, turn_data);
}
// reads .osrm.tls
template <typename OffsetsT, typename MaskT>
inline void readTurnLaneDescriptions(const boost::filesystem::path &path,
OffsetsT &turn_offsets,
MaskT &turn_masks)
{
static_assert(
std::is_same<typename MaskT::value_type, extractor::guidance::TurnLaneType::Mask>::value,
"");
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
storage::serialization::read(reader, turn_offsets);
storage::serialization::read(reader, turn_masks);
}
// writes .osrm.tls
template <typename OffsetsT, typename MaskT>
inline void writeTurnLaneDescriptions(const boost::filesystem::path &path,
const OffsetsT &turn_offsets,
const MaskT &turn_masks)
{
static_assert(
std::is_same<typename MaskT::value_type, extractor::guidance::TurnLaneType::Mask>::value,
"");
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, turn_offsets);
storage::serialization::write(writer, turn_masks);
}
}
}
}
#endif
@@ -23,7 +23,7 @@ class CoordinateExtractor
public:
CoordinateExtractor(const util::NodeBasedDynamicGraph &node_based_graph,
const extractor::CompressedEdgeContainer &compressed_geometries,
const std::vector<extractor::QueryNode> &node_coordinates);
const std::vector<util::Coordinate> &node_coordinates);
/* Find a interpolated coordinate a long the compressed geometries. The desired coordinate
* should be in a certain distance. This method is dedicated to find representative coordinates
@@ -156,7 +156,7 @@ class CoordinateExtractor
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const extractor::CompressedEdgeContainer &compressed_geometries;
const std::vector<extractor::QueryNode> &node_coordinates;
const std::vector<util::Coordinate> &node_coordinates;
double ComputeInterpolationFactor(const double desired_distance,
const double distance_to_first,
@@ -40,7 +40,7 @@ class IntersectionGenerator
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container);
// For a source node `a` and a via edge `ab` creates an intersection at target `b`.
@@ -112,7 +112,7 @@ class IntersectionGenerator
const util::NodeBasedDynamicGraph &node_based_graph;
const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes;
const std::vector<QueryNode> &node_info_list;
const std::vector<util::Coordinate> &coordinates;
// own state, used to find the correct coordinates along a road
const CoordinateExtractor coordinate_extractor;
@@ -34,7 +34,7 @@ class IntersectionHandler
{
public:
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
@@ -51,7 +51,7 @@ class IntersectionHandler
protected:
const util::NodeBasedDynamicGraph &node_based_graph;
const std::vector<QueryNode> &node_info_list;
const std::vector<util::Coordinate> &coordinates;
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
const IntersectionGenerator &intersection_generator;
@@ -43,7 +43,7 @@ class IntersectionNormalizer
std::vector<IntersectionNormalizationOperation> performed_merges;
};
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<extractor::QueryNode> &node_coordinates,
const std::vector<util::Coordinate> &node_coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
@@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
#include "extractor/guidance/intersection.hpp"
#include "util/coordinate.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
@@ -22,7 +23,6 @@ class NameTable;
namespace extractor
{
struct QueryNode;
class SuffixTable;
namespace guidance
@@ -37,7 +37,7 @@ class MergableRoadDetector
using MergableRoadData = IntersectionShapeData;
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_coordinates,
const std::vector<util::Coordinate> &node_coordinates,
const IntersectionGenerator &intersection_generator,
const CoordinateExtractor &coordinate_extractor,
const util::NameTable &name_table,
@@ -138,7 +138,7 @@ class MergableRoadDetector
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
const util::NodeBasedDynamicGraph &node_based_graph;
const std::vector<QueryNode> &node_coordinates;
const std::vector<util::Coordinate> &node_coordinates;
const IntersectionGenerator &intersection_generator;
const CoordinateExtractor &coordinate_extractor;
@@ -25,7 +25,7 @@ class MotorwayHandler : public IntersectionHandler
{
public:
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
@@ -41,7 +41,7 @@ class RoundaboutHandler : public IntersectionHandler
{
public:
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
@@ -27,7 +27,7 @@ class SliproadHandler final : public IntersectionHandler
public:
SliproadHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
@@ -23,7 +23,7 @@ class SuppressModeHandler final : public IntersectionHandler
public:
SuppressModeHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
+1 -1
View File
@@ -40,7 +40,7 @@ class TurnAnalysis
{
public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container,
+1 -1
View File
@@ -29,7 +29,7 @@ class TurnHandler : public IntersectionHandler
{
public:
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
-103
View File
@@ -1,103 +0,0 @@
#ifndef OSRM_EXTRACTOR_IO_HPP
#define OSRM_EXTRACTOR_IO_HPP
#include "extractor/datasources.hpp"
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/segment_data_container.hpp"
#include "storage/io.hpp"
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
namespace io
{
inline void read(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.DeserializeVector(mapping);
}
inline void write(const boost::filesystem::path &path, const std::vector<NBGToEBG> &mapping)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter reader{path, fingerprint};
reader.SerializeVector(mapping);
}
inline void read(const boost::filesystem::path &path, Datasources &sources)
{
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.ReadInto(sources);
}
inline void write(const boost::filesystem::path &path, Datasources &sources)
{
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteFrom(sources);
}
template <>
inline void read(const boost::filesystem::path &path, SegmentDataContainer &segment_data)
{
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
auto num_indices = reader.ReadElementCount32();
segment_data.index.resize(num_indices);
reader.ReadInto(segment_data.index.data(), num_indices);
auto num_entries = reader.ReadElementCount32();
segment_data.nodes.resize(num_entries);
segment_data.fwd_weights.resize(num_entries);
segment_data.rev_weights.resize(num_entries);
segment_data.fwd_durations.resize(num_entries);
segment_data.rev_durations.resize(num_entries);
segment_data.datasources.resize(num_entries);
reader.ReadInto(segment_data.nodes);
reader.ReadInto(segment_data.fwd_weights);
reader.ReadInto(segment_data.rev_weights);
reader.ReadInto(segment_data.fwd_durations);
reader.ReadInto(segment_data.rev_durations);
reader.ReadInto(segment_data.datasources);
}
template <>
inline void write(const boost::filesystem::path &path, const SegmentDataContainer &segment_data)
{
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteElementCount32(segment_data.index.size());
writer.WriteFrom(segment_data.index);
writer.WriteElementCount32(segment_data.nodes.size());
BOOST_ASSERT(segment_data.fwd_weights.size() == segment_data.nodes.size());
BOOST_ASSERT(segment_data.rev_weights.size() == segment_data.nodes.size());
BOOST_ASSERT(segment_data.fwd_durations.size() == segment_data.nodes.size());
BOOST_ASSERT(segment_data.rev_durations.size() == segment_data.nodes.size());
BOOST_ASSERT(segment_data.datasources.size() == segment_data.nodes.size());
writer.WriteFrom(segment_data.nodes);
writer.WriteFrom(segment_data.fwd_weights);
writer.WriteFrom(segment_data.rev_weights);
writer.WriteFrom(segment_data.fwd_durations);
writer.WriteFrom(segment_data.rev_durations);
writer.WriteFrom(segment_data.datasources);
}
}
}
}
#endif
+21 -18
View File
@@ -1,8 +1,11 @@
#ifndef OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
#define OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/typedefs.hpp"
#include "util/vector_view.hpp"
#include "storage/io_fwd.hpp"
#include "storage/shared_memory_ownership.hpp"
#include <boost/filesystem/path.hpp>
#include <boost/range/adaptor/reversed.hpp>
@@ -22,24 +25,24 @@ class CompressedEdgeContainer;
namespace detail
{
template <bool UseShareMemory> class SegmentDataContainerImpl;
template <storage::Ownership Ownership> class SegmentDataContainerImpl;
}
namespace io
namespace serialization
{
template <bool UseShareMemory>
inline void read(const boost::filesystem::path &path,
detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
template <bool UseShareMemory>
inline void write(const boost::filesystem::path &path,
const detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader,
detail::SegmentDataContainerImpl<Ownership> &segment_data);
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
}
namespace detail
{
template <bool UseShareMemory> class SegmentDataContainerImpl
template <storage::Ownership Ownership> class SegmentDataContainerImpl
{
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
friend CompressedEdgeContainer;
@@ -189,11 +192,11 @@ template <bool UseShareMemory> class SegmentDataContainerImpl
auto GetNumberOfSegments() const { return fwd_weights.size(); }
friend void
io::read<UseShareMemory>(const boost::filesystem::path &path,
detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
friend void
io::write<UseShareMemory>(const boost::filesystem::path &path,
const detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
serialization::read<Ownership>(storage::io::FileReader &reader,
detail::SegmentDataContainerImpl<Ownership> &segment_data);
friend void serialization::write<Ownership>(
storage::io::FileWriter &writer,
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
private:
Vector<std::uint32_t> index;
@@ -206,8 +209,8 @@ template <bool UseShareMemory> class SegmentDataContainerImpl
};
}
using SegmentDataView = detail::SegmentDataContainerImpl<true>;
using SegmentDataContainer = detail::SegmentDataContainerImpl<false>;
using SegmentDataView = detail::SegmentDataContainerImpl<storage::Ownership::View>;
using SegmentDataContainer = detail::SegmentDataContainerImpl<storage::Ownership::Container>;
}
}
+88
View File
@@ -0,0 +1,88 @@
#ifndef OSRM_EXTRACTOR_IO_HPP
#define OSRM_EXTRACTOR_IO_HPP
#include "extractor/datasources.hpp"
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/segment_data_container.hpp"
#include "extractor/turn_data_container.hpp"
#include "storage/io.hpp"
#include "storage/serialization.hpp"
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
namespace serialization
{
inline void read(storage::io::FileReader &reader, Datasources &sources)
{
reader.ReadInto(sources);
}
inline void write(storage::io::FileWriter &writer, Datasources &sources)
{
writer.WriteFrom(sources);
}
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader,
detail::SegmentDataContainerImpl<Ownership> &segment_data)
{
storage::serialization::read(reader, segment_data.index);
storage::serialization::read(reader, segment_data.nodes);
storage::serialization::read(reader, segment_data.fwd_weights);
storage::serialization::read(reader, segment_data.rev_weights);
storage::serialization::read(reader, segment_data.fwd_durations);
storage::serialization::read(reader, segment_data.rev_durations);
storage::serialization::read(reader, segment_data.datasources);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::SegmentDataContainerImpl<Ownership> &segment_data)
{
storage::serialization::write(writer, segment_data.index);
storage::serialization::write(writer, segment_data.nodes);
storage::serialization::write(writer, segment_data.fwd_weights);
storage::serialization::write(writer, segment_data.rev_weights);
storage::serialization::write(writer, segment_data.fwd_durations);
storage::serialization::write(writer, segment_data.rev_durations);
storage::serialization::write(writer, segment_data.datasources);
}
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader,
detail::TurnDataContainerImpl<Ownership> &turn_data_container)
{
storage::serialization::read(reader, turn_data_container.geometry_ids);
storage::serialization::read(reader, turn_data_container.name_ids);
storage::serialization::read(reader, turn_data_container.turn_instructions);
storage::serialization::read(reader, turn_data_container.lane_data_ids);
storage::serialization::read(reader, turn_data_container.travel_modes);
storage::serialization::read(reader, turn_data_container.entry_class_ids);
storage::serialization::read(reader, turn_data_container.pre_turn_bearings);
storage::serialization::read(reader, turn_data_container.post_turn_bearings);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::TurnDataContainerImpl<Ownership> &turn_data_container)
{
storage::serialization::write(writer, turn_data_container.geometry_ids);
storage::serialization::write(writer, turn_data_container.name_ids);
storage::serialization::write(writer, turn_data_container.turn_instructions);
storage::serialization::write(writer, turn_data_container.lane_data_ids);
storage::serialization::write(writer, turn_data_container.travel_modes);
storage::serialization::write(writer, turn_data_container.entry_class_ids);
storage::serialization::write(writer, turn_data_container.pre_turn_bearings);
storage::serialization::write(writer, turn_data_container.post_turn_bearings);
}
}
}
}
#endif
+131
View File
@@ -0,0 +1,131 @@
#ifndef OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
#define OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "storage/io_fwd.hpp"
#include "storage/shared_memory_ownership.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/vector_view.hpp"
#include "util/typedefs.hpp"
namespace osrm
{
namespace extractor
{
namespace detail
{
template <storage::Ownership Ownership> class TurnDataContainerImpl;
}
namespace serialization
{
template <storage::Ownership Ownership>
void read(storage::io::FileReader &reader, detail::TurnDataContainerImpl<Ownership> &turn_data);
template <storage::Ownership Ownership>
void write(storage::io::FileWriter &writer,
const detail::TurnDataContainerImpl<Ownership> &turn_data);
}
namespace detail
{
template <storage::Ownership Ownership> class TurnDataContainerImpl
{
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public:
TurnDataContainerImpl() = default;
TurnDataContainerImpl(Vector<GeometryID> geometry_ids_,
Vector<NameID> name_ids_,
Vector<extractor::guidance::TurnInstruction> turn_instructions_,
Vector<LaneDataID> lane_data_ids_,
Vector<extractor::TravelMode> travel_modes_,
Vector<EntryClassID> entry_class_ids_,
Vector<util::guidance::TurnBearing> pre_turn_bearings_,
Vector<util::guidance::TurnBearing> post_turn_bearings_)
: geometry_ids(std::move(geometry_ids_)), name_ids(std::move(name_ids_)),
turn_instructions(std::move(turn_instructions_)),
lane_data_ids(std::move(lane_data_ids_)), travel_modes(std::move(travel_modes_)),
entry_class_ids(std::move(entry_class_ids_)),
pre_turn_bearings(std::move(pre_turn_bearings_)),
post_turn_bearings(std::move(post_turn_bearings_))
{
}
GeometryID GetGeometryID(const EdgeID id) const { return geometry_ids[id]; }
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
extractor::TravelMode GetTravelMode(const EdgeID id) const { return travel_modes[id]; }
util::guidance::TurnBearing GetPreTurnBearing(const EdgeID id) const
{
return pre_turn_bearings[id];
}
util::guidance::TurnBearing GetPostTurnBearing(const EdgeID id) const
{
return post_turn_bearings[id];
}
LaneDataID GetLaneDataID(const EdgeID id) const { return lane_data_ids[id]; }
bool HasLaneData(const EdgeID id) const { return INVALID_LANE_DATAID != lane_data_ids[id]; }
NameID GetNameID(const EdgeID id) const { return name_ids[id]; }
extractor::guidance::TurnInstruction GetTurnInstruction(const EdgeID id) const
{
return turn_instructions[id];
}
// Used by EdgeBasedGraphFactory to fill data structure
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
void push_back(GeometryID geometry_id,
NameID name_id,
extractor::guidance::TurnInstruction turn_instruction,
LaneDataID lane_data_id,
EntryClassID entry_class_id,
extractor::TravelMode travel_mode,
util::guidance::TurnBearing pre_turn_bearing,
util::guidance::TurnBearing post_turn_bearing)
{
geometry_ids.push_back(geometry_id);
name_ids.push_back(name_id);
turn_instructions.push_back(turn_instruction);
lane_data_ids.push_back(lane_data_id);
travel_modes.push_back(travel_mode);
entry_class_ids.push_back(entry_class_id);
pre_turn_bearings.push_back(pre_turn_bearing);
post_turn_bearings.push_back(post_turn_bearing);
}
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
TurnDataContainerImpl &turn_data_container);
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
const TurnDataContainerImpl &turn_data_container);
private:
Vector<GeometryID> geometry_ids;
Vector<NameID> name_ids;
Vector<extractor::guidance::TurnInstruction> turn_instructions;
Vector<LaneDataID> lane_data_ids;
Vector<extractor::TravelMode> travel_modes;
Vector<EntryClassID> entry_class_ids;
Vector<util::guidance::TurnBearing> pre_turn_bearings;
Vector<util::guidance::TurnBearing> post_turn_bearings;
};
}
using TurnDataExternalContainer = detail::TurnDataContainerImpl<storage::Ownership::External>;
using TurnDataContainer = detail::TurnDataContainerImpl<storage::Ownership::Container>;
using TurnDataView = detail::TurnDataContainerImpl<storage::Ownership::View>;
}
}
#endif
+7 -8
View File
@@ -18,7 +18,6 @@
#include "osrm/trip_parameters.hpp"
#include <boost/assert.hpp>
#include <boost/make_unique.hpp>
#include <boost/optional.hpp>
#include <algorithm>
@@ -81,7 +80,7 @@ inline void ParseResult(const osrm::Status &result_status, const std::string & /
inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
Nan::HandleScope scope;
auto engine_config = boost::make_unique<osrm::EngineConfig>();
auto engine_config = std::make_unique<osrm::EngineConfig>();
if (args.Length() == 0)
{
@@ -631,7 +630,7 @@ inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
route_parameters_ptr params = boost::make_unique<osrm::RouteParameters>();
route_parameters_ptr params = std::make_unique<osrm::RouteParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return route_parameters_ptr();
@@ -681,7 +680,7 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
inline tile_parameters_ptr
argumentsToTileParameters(const Nan::FunctionCallbackInfo<v8::Value> &args, bool /*unused*/)
{
tile_parameters_ptr params = boost::make_unique<osrm::TileParameters>();
tile_parameters_ptr params = std::make_unique<osrm::TileParameters>();
if (args.Length() < 2)
{
@@ -742,7 +741,7 @@ inline nearest_parameters_ptr
argumentsToNearestParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
nearest_parameters_ptr params = boost::make_unique<osrm::NearestParameters>();
nearest_parameters_ptr params = std::make_unique<osrm::NearestParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return nearest_parameters_ptr();
@@ -781,7 +780,7 @@ inline table_parameters_ptr
argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
table_parameters_ptr params = boost::make_unique<osrm::TableParameters>();
table_parameters_ptr params = std::make_unique<osrm::TableParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return table_parameters_ptr();
@@ -875,7 +874,7 @@ inline trip_parameters_ptr
argumentsToTripParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
trip_parameters_ptr params = boost::make_unique<osrm::TripParameters>();
trip_parameters_ptr params = std::make_unique<osrm::TripParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return trip_parameters_ptr();
@@ -970,7 +969,7 @@ inline match_parameters_ptr
argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
{
match_parameters_ptr params = boost::make_unique<osrm::MatchParameters>();
match_parameters_ptr params = std::make_unique<osrm::MatchParameters>();
bool has_base_params = argumentsToParameter(args, params, requires_multiple_coordinates);
if (!has_base_params)
return match_parameters_ptr();
+23 -21
View File
@@ -6,10 +6,11 @@
#include "util/assert.hpp"
#include "util/for_each_range.hpp"
#include "util/log.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/typedefs.hpp"
#include "util/vector_view.hpp"
#include "storage/io.hpp"
#include "storage/io_fwd.hpp"
#include "storage/shared_memory_ownership.hpp"
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>
@@ -26,24 +27,23 @@ namespace partition
{
namespace detail
{
template <bool UseShareMemory> class CellStorageImpl;
template <storage::Ownership Ownership> class CellStorageImpl;
}
using CellStorage = detail::CellStorageImpl<false>;
using CellStorageView = detail::CellStorageImpl<true>;
using CellStorage = detail::CellStorageImpl<storage::Ownership::Container>;
using CellStorageView = detail::CellStorageImpl<storage::Ownership::View>;
namespace io
namespace serialization
{
template <bool UseShareMemory>
inline void read(const boost::filesystem::path &path,
detail::CellStorageImpl<UseShareMemory> &storage);
template <bool UseShareMemory>
inline void write(const boost::filesystem::path &path,
const detail::CellStorageImpl<UseShareMemory> &storage);
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, detail::CellStorageImpl<Ownership> &storage);
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::CellStorageImpl<Ownership> &storage);
}
namespace detail
{
template <bool UseShareMemory> class CellStorageImpl
template <storage::Ownership Ownership> class CellStorageImpl
{
public:
using WeightOffset = std::uint32_t;
@@ -65,7 +65,7 @@ template <bool UseShareMemory> class CellStorageImpl
};
private:
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
// 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.
@@ -185,7 +185,8 @@ template <bool UseShareMemory> class CellStorageImpl
CellStorageImpl() {}
template <typename GraphT, typename = std::enable_if<!UseShareMemory>>
template <typename GraphT,
typename = std::enable_if<Ownership == storage::Ownership::Container>>
CellStorageImpl(const partition::MultiLevelPartition &partition, const GraphT &base_graph)
{
// pre-allocate storge for CellData so we can have random access to it by cell id
@@ -314,7 +315,7 @@ template <bool UseShareMemory> class CellStorageImpl
weights.resize(weight_offset + 1, INVALID_EDGE_WEIGHT);
}
template <typename = std::enable_if<UseShareMemory>>
template <typename = std::enable_if<Ownership == storage::Ownership::View>>
CellStorageImpl(Vector<EdgeWeight> weights_,
Vector<NodeID> source_boundary_,
Vector<NodeID> destination_boundary_,
@@ -339,7 +340,8 @@ template <bool UseShareMemory> class CellStorageImpl
destination_boundary.empty() ? nullptr : destination_boundary.data()};
}
template <typename = std::enable_if<!UseShareMemory>> Cell GetCell(LevelID level, CellID id)
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
Cell GetCell(LevelID level, CellID id)
{
const auto level_index = LevelIDToIndex(level);
BOOST_ASSERT(level_index < level_to_cell_offset.size());
@@ -350,10 +352,10 @@ template <bool UseShareMemory> class CellStorageImpl
cells[cell_index], weights.data(), source_boundary.data(), destination_boundary.data()};
}
friend void io::read<UseShareMemory>(const boost::filesystem::path &path,
detail::CellStorageImpl<UseShareMemory> &storage);
friend void io::write<UseShareMemory>(const boost::filesystem::path &path,
const detail::CellStorageImpl<UseShareMemory> &storage);
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
detail::CellStorageImpl<Ownership> &storage);
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
const detail::CellStorageImpl<Ownership> &storage);
private:
Vector<EdgeWeight> weights;
+104
View File
@@ -0,0 +1,104 @@
#ifndef OSRM_PARTITION_SERILIZATION_HPP
#define OSRM_PARTITION_SERILIZATION_HPP
#include "customizer/edge_based_graph.hpp"
#include "partition/serialization.hpp"
#include "storage/io.hpp"
namespace osrm
{
namespace partition
{
namespace files
{
// reads .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void readGraph(const boost::filesystem::path &path, MultiLevelGraphT &graph)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, graph);
}
// writes .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void writeGraph(const boost::filesystem::path &path, const MultiLevelGraphT &graph)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, graph);
}
// read .osrm.partition file
template <typename MultiLevelPartitionT>
inline void readPartition(const boost::filesystem::path &path, MultiLevelPartitionT &mlp)
{
static_assert(std::is_same<MultiLevelPartitionView, MultiLevelPartitionT>::value ||
std::is_same<MultiLevelPartition, MultiLevelPartitionT>::value,
"");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, mlp);
}
// writes .osrm.partition file
template <typename MultiLevelPartitionT>
inline void writePartition(const boost::filesystem::path &path, const MultiLevelPartitionT &mlp)
{
static_assert(std::is_same<MultiLevelPartitionView, MultiLevelPartitionT>::value ||
std::is_same<MultiLevelPartition, MultiLevelPartitionT>::value,
"");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, mlp);
}
// reads .osrm.cells file
template <typename CellStorageT>
inline void readCells(const boost::filesystem::path &path, CellStorageT &storage)
{
static_assert(std::is_same<CellStorageView, CellStorageT>::value ||
std::is_same<CellStorage, CellStorageT>::value,
"");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
serialization::read(reader, storage);
}
// writes .osrm.cells file
template <typename CellStorageT>
inline void writeCells(const boost::filesystem::path &path, CellStorageT &storage)
{
static_assert(std::is_same<CellStorageView, CellStorageT>::value ||
std::is_same<CellStorage, CellStorageT>::value,
"");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
serialization::write(writer, storage);
}
}
}
}
#endif
-89
View File
@@ -1,89 +0,0 @@
#ifndef OSRM_PARTITION_IO_HPP
#define OSRM_PARTITION_IO_HPP
#include "partition/cell_storage.hpp"
#include "partition/edge_based_graph.hpp"
#include "partition/multi_level_graph.hpp"
#include "partition/multi_level_partition.hpp"
#include "storage/io.hpp"
namespace osrm
{
namespace partition
{
namespace io
{
template <typename EdgeDataT, bool UseSharedMemory>
inline void read(const boost::filesystem::path &path,
MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.DeserializeVector(graph.node_array);
reader.DeserializeVector(graph.edge_array);
reader.DeserializeVector(graph.edge_to_level);
}
template <typename EdgeDataT, bool UseSharedMemory>
inline void write(const boost::filesystem::path &path,
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.SerializeVector(graph.node_array);
writer.SerializeVector(graph.edge_array);
writer.SerializeVector(graph.node_to_edge_offset);
}
template <> inline void read(const boost::filesystem::path &path, MultiLevelPartition &mlp)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.ReadInto<MultiLevelPartition::LevelData>(mlp.level_data);
reader.DeserializeVector(mlp.partition);
reader.DeserializeVector(mlp.cell_to_children);
}
template <> inline void write(const boost::filesystem::path &path, const MultiLevelPartition &mlp)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteOne(mlp.level_data);
writer.SerializeVector(mlp.partition);
writer.SerializeVector(mlp.cell_to_children);
}
template <> inline void read(const boost::filesystem::path &path, CellStorage &storage)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.DeserializeVector(storage.weights);
reader.DeserializeVector(storage.source_boundary);
reader.DeserializeVector(storage.destination_boundary);
reader.DeserializeVector(storage.cells);
reader.DeserializeVector(storage.level_to_cell_offset);
}
template <> inline void write(const boost::filesystem::path &path, const CellStorage &storage)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.SerializeVector(storage.weights);
writer.SerializeVector(storage.source_boundary);
writer.SerializeVector(storage.destination_boundary);
writer.SerializeVector(storage.cells);
writer.SerializeVector(storage.level_to_cell_offset);
}
}
}
}
#endif
+19 -15
View File
@@ -3,7 +3,11 @@
#include "partition/multi_level_partition.hpp"
#include "storage/io_fwd.hpp"
#include "storage/shared_memory_ownership.hpp"
#include "util/static_graph.hpp"
#include "util/vector_view.hpp"
#include <tbb/parallel_sort.h>
@@ -12,26 +16,26 @@
namespace osrm
{
namespace partition
{
template <typename EdgeDataT, bool UseSharedMemory> class MultiLevelGraph;
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
namespace io
namespace serialization
{
template <typename EdgeDataT, bool UseSharedMemory>
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
template <typename EdgeDataT, storage::Ownership Ownership>
void read(storage::io::FileReader &reader, MultiLevelGraph<EdgeDataT, Ownership> &graph);
template <typename EdgeDataT, bool UseSharedMemory>
void write(const boost::filesystem::path &path,
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
template <typename EdgeDataT, storage::Ownership Ownership>
void write(storage::io::FileWriter &writer, const MultiLevelGraph<EdgeDataT, Ownership> &graph);
}
template <typename EdgeDataT, bool UseSharedMemory>
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
template <typename EdgeDataT, storage::Ownership Ownership>
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
{
private:
using SuperT = util::StaticGraph<EdgeDataT, UseSharedMemory>;
template <typename T> using Vector = typename util::ShM<T, UseSharedMemory>::vector;
using SuperT = util::StaticGraph<EdgeDataT, Ownership>;
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public:
// We limit each node to have 255 edges
@@ -190,11 +194,11 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
}
friend void
io::read<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
serialization::read<EdgeDataT, Ownership>(storage::io::FileReader &reader,
MultiLevelGraph<EdgeDataT, Ownership> &graph);
friend void
io::write<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
serialization::write<EdgeDataT, Ownership>(storage::io::FileWriter &writer,
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
Vector<EdgeOffset> node_to_edge_offset;
};
+48 -35
View File
@@ -4,10 +4,11 @@
#include "util/exception.hpp"
#include "util/for_each_pair.hpp"
#include "util/msb.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/typedefs.hpp"
#include "util/vector_view.hpp"
#include "storage/io.hpp"
#include "storage/io_fwd.hpp"
#include "storage/shared_memory_ownership.hpp"
#include <algorithm>
#include <array>
@@ -25,31 +26,29 @@ namespace partition
{
namespace detail
{
template <bool UseShareMemory> class MultiLevelPartitionImpl;
template <storage::Ownership Ownership> class MultiLevelPartitionImpl;
}
using MultiLevelPartition = detail::MultiLevelPartitionImpl<false>;
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<true>;
using MultiLevelPartition = detail::MultiLevelPartitionImpl<storage::Ownership::Container>;
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<storage::Ownership::View>;
namespace io
namespace serialization
{
template <bool UseShareMemory>
void read(const boost::filesystem::path &file,
detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
template <bool UseShareMemory>
void write(const boost::filesystem::path &file,
const detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
template <storage::Ownership Ownership>
void read(storage::io::FileReader &reader, detail::MultiLevelPartitionImpl<Ownership> &mlp);
template <storage::Ownership Ownership>
void write(storage::io::FileWriter &writer, const detail::MultiLevelPartitionImpl<Ownership> &mlp);
}
namespace detail
{
template <bool UseShareMemory> class MultiLevelPartitionImpl final
template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
{
// we will support at most 16 levels
static const constexpr std::uint8_t MAX_NUM_LEVEL = 16;
static const constexpr std::uint8_t NUM_PARTITION_BITS = sizeof(PartitionID) * CHAR_BIT;
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public:
// Contains all data necessary to describe the level hierarchy
@@ -62,13 +61,16 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
std::array<LevelID, NUM_PARTITION_BITS> bit_to_level;
std::array<std::uint32_t, MAX_NUM_LEVEL - 1> lidx_to_children_offsets;
};
using LevelDataPtr = typename std::conditional<Ownership == storage::Ownership::View,
LevelData *,
std::unique_ptr<LevelData>>::type;
MultiLevelPartitionImpl() = default;
MultiLevelPartitionImpl();
// cell_sizes is index by level (starting at 0, the base graph).
// However level 0 always needs to have cell size 1, since it is the
// basegraph.
template <typename = typename std::enable_if<!UseShareMemory>>
template <typename = typename std::enable_if<Ownership == storage::Ownership::Container>>
MultiLevelPartitionImpl(const std::vector<std::vector<CellID>> &partitions,
const std::vector<std::uint32_t> &lidx_to_num_cells)
: level_data(MakeLevelData(lidx_to_num_cells))
@@ -76,8 +78,8 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
InitializePartitionIDs(partitions);
}
template <typename = typename std::enable_if<UseShareMemory>>
MultiLevelPartitionImpl(LevelData level_data,
template <typename = typename std::enable_if<Ownership == storage::Ownership::View>>
MultiLevelPartitionImpl(LevelDataPtr level_data,
Vector<PartitionID> partition_,
Vector<CellID> cell_to_children_)
: level_data(std::move(level_data)), partition(std::move(partition_)),
@@ -90,8 +92,8 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
{
auto p = partition[node];
auto lidx = LevelIDToIndex(l);
auto masked = p & level_data.lidx_to_mask[lidx];
return masked >> level_data.lidx_to_offset[lidx];
auto masked = p & level_data->lidx_to_mask[lidx];
return masked >> level_data->lidx_to_offset[lidx];
}
LevelID GetQueryLevel(NodeID start, NodeID target, NodeID node) const
@@ -106,10 +108,10 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
return 0;
auto msb = util::msb(partition[first] ^ partition[second]);
return level_data.bit_to_level[msb];
return level_data->bit_to_level[msb];
}
std::uint8_t GetNumberOfLevels() const { return level_data.num_level; }
std::uint8_t GetNumberOfLevels() const { return level_data->num_level; }
std::uint32_t GetNumberOfCells(LevelID level) const
{
@@ -121,7 +123,7 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
{
BOOST_ASSERT(level > 1);
auto lidx = LevelIDToIndex(level);
auto offset = level_data.lidx_to_children_offsets[lidx];
auto offset = level_data->lidx_to_children_offsets[lidx];
return cell_to_children[offset + cell];
}
@@ -130,14 +132,14 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
{
BOOST_ASSERT(level > 1);
auto lidx = LevelIDToIndex(level);
auto offset = level_data.lidx_to_children_offsets[lidx];
auto offset = level_data->lidx_to_children_offsets[lidx];
return cell_to_children[offset + cell + 1];
}
friend void io::read<UseShareMemory>(const boost::filesystem::path &file,
MultiLevelPartitionImpl &mlp);
friend void io::write<UseShareMemory>(const boost::filesystem::path &file,
const MultiLevelPartitionImpl &mlp);
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
MultiLevelPartitionImpl &mlp);
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
const MultiLevelPartitionImpl &mlp);
private:
auto MakeLevelData(const std::vector<std::uint32_t> &lidx_to_num_cells)
@@ -146,7 +148,7 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
auto offsets = MakeLevelOffsets(lidx_to_num_cells);
auto masks = MakeLevelMasks(offsets, num_level);
auto bits = MakeBitToLevel(offsets, num_level);
return LevelData{num_level, offsets, masks, bits, {0}};
return std::make_unique<LevelData>(LevelData{num_level, offsets, masks, bits, {0}});
}
inline std::size_t LevelIDToIndex(LevelID l) const { return l - 1; }
@@ -160,8 +162,8 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
{
auto lidx = LevelIDToIndex(l);
auto shifted_id = cell_id << level_data.lidx_to_offset[lidx];
auto cleared_cell = partition[node] & ~level_data.lidx_to_mask[lidx];
auto shifted_id = cell_id << level_data->lidx_to_offset[lidx];
auto cleared_cell = partition[node] & ~level_data->lidx_to_mask[lidx];
partition[node] = cleared_cell | shifted_id;
}
@@ -289,13 +291,13 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
level--;
}
level_data.lidx_to_children_offsets[0] = 0;
level_data->lidx_to_children_offsets[0] = 0;
for (auto level_idx = 0UL; level_idx < partitions.size() - 1; ++level_idx)
{
const auto &parent_partition = partitions[level_idx + 1];
level_data.lidx_to_children_offsets[level_idx + 1] = cell_to_children.size();
level_data->lidx_to_children_offsets[level_idx + 1] = cell_to_children.size();
CellID last_parent_id = parent_partition[permutation.front()];
cell_to_children.push_back(GetCell(level_idx + 1, permutation.front()));
@@ -314,11 +316,22 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
}
}
//! this is always owned by this class because it is so small
LevelData level_data;
LevelDataPtr level_data = {};
Vector<PartitionID> partition;
Vector<CellID> cell_to_children;
};
template <>
inline MultiLevelPartitionImpl<storage::Ownership::Container>::MultiLevelPartitionImpl()
: level_data(std::make_unique<LevelData>())
{
}
template <>
inline MultiLevelPartitionImpl<storage::Ownership::View>::MultiLevelPartitionImpl()
: level_data(nullptr)
{
}
}
}
}
+78
View File
@@ -0,0 +1,78 @@
#ifndef OSRM_PARTITION_SERIALIZATION_HPP
#define OSRM_PARTITION_SERIALIZATION_HPP
#include "partition/cell_storage.hpp"
#include "partition/edge_based_graph.hpp"
#include "partition/multi_level_graph.hpp"
#include "partition/multi_level_partition.hpp"
#include "storage/io.hpp"
#include "storage/serialization.hpp"
#include "storage/shared_memory_ownership.hpp"
namespace osrm
{
namespace partition
{
namespace serialization
{
template <typename EdgeDataT, storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::read(reader, graph.node_array);
storage::serialization::read(reader, graph.edge_array);
storage::serialization::read(reader, graph.node_to_edge_offset);
}
template <typename EdgeDataT, storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::write(writer, graph.node_array);
storage::serialization::write(writer, graph.edge_array);
storage::serialization::write(writer, graph.node_to_edge_offset);
}
template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, detail::MultiLevelPartitionImpl<Ownership> &mlp)
{
reader.ReadInto(*mlp.level_data);
storage::serialization::read(reader, mlp.partition);
storage::serialization::read(reader, mlp.cell_to_children);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::MultiLevelPartitionImpl<Ownership> &mlp)
{
writer.WriteOne(*mlp.level_data);
storage::serialization::write(writer, mlp.partition);
storage::serialization::write(writer, mlp.cell_to_children);
}
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.source_boundary);
storage::serialization::read(reader, storage.destination_boundary);
storage::serialization::read(reader, storage.cells);
storage::serialization::read(reader, storage.level_to_cell_offset);
}
template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer,
const detail::CellStorageImpl<Ownership> &storage)
{
storage::serialization::write(writer, storage.weights);
storage::serialization::write(writer, storage.source_boundary);
storage::serialization::write(writer, storage.destination_boundary);
storage::serialization::write(writer, storage.cells);
storage::serialization::write(writer, storage.level_to_cell_offset);
}
}
}
}
#endif
+1 -71
View File
@@ -128,20 +128,6 @@ class FileReader
std::uint32_t ReadElementCount32() { return ReadOne<std::uint32_t>(); }
std::uint64_t ReadElementCount64() { return ReadOne<std::uint64_t>(); }
template <typename T> void DeserializeVector(std::vector<T> &data)
{
const auto count = ReadElementCount64();
data.resize(count);
ReadInto(data.data(), count);
}
template <typename T> std::size_t GetVectorMemorySize()
{
const auto count = ReadElementCount64();
Skip<T>(count);
return sizeof(count) + sizeof(T) * count;
}
template <typename T> std::size_t ReadVectorSize()
{
const auto count = ReadElementCount64();
@@ -149,19 +135,6 @@ class FileReader
return count;
}
template <typename T> void *DeserializeVector(void *begin, const void *end)
{
auto count = ReadElementCount64();
auto required = reinterpret_cast<char *>(begin) + sizeof(count) + sizeof(T) * count;
if (required > end)
throw util::exception("Not enough memory ");
*reinterpret_cast<decltype(count) *>(begin) = count;
ReadInto(reinterpret_cast<T *>(reinterpret_cast<char *>(begin) + sizeof(decltype(count))),
count);
return required;
}
bool ReadAndCheckFingerprint()
{
auto loaded_fingerprint = ReadOne<util::FingerPrint>();
@@ -199,42 +172,6 @@ class FileReader
input_stream.seekg(current_pos, input_stream.beg);
return length;
}
std::vector<std::string> ReadLines()
{
std::vector<std::string> result;
std::string thisline;
try
{
while (std::getline(input_stream, thisline))
{
result.push_back(thisline);
}
}
catch (const std::ios_base::failure &)
{
// EOF is OK here, everything else, re-throw
if (!input_stream.eof())
throw;
}
return result;
}
std::string ReadLine()
{
std::string thisline;
try
{
std::getline(input_stream, thisline);
}
catch (const std::ios_base::failure & /*e*/)
{
// EOF is OK here, everything else, re-throw
if (!input_stream.eof())
throw;
}
return thisline;
}
};
class FileWriter
@@ -291,18 +228,11 @@ class FileWriter
template <typename T> void WriteFrom(const T &src) { WriteFrom(&src, 1); }
template <typename T> void WriteOne(const T tmp) { WriteFrom(tmp); }
template <typename T> void WriteOne(const T &tmp) { WriteFrom(tmp); }
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
template <typename T> void SerializeVector(const std::vector<T> &data)
{
const auto count = data.size();
WriteElementCount64(count);
return WriteFrom(data.data(), count);
}
void WriteFingerprint()
{
const auto fingerprint = util::FingerPrint::GetValid();
+18
View File
@@ -0,0 +1,18 @@
#ifndef OSRM_STORAGE_IO_FWD_HPP_
#define OSRM_STORAGE_IO_FWD_HPP_
namespace osrm
{
namespace storage
{
namespace io
{
class FileReader;
class FileWriter;
} // ns io
} // ns storage
} // ns osrm
#endif
+45 -107
View File
@@ -1,23 +1,12 @@
#ifndef OSRM_STORAGE_SERIALIZATION_HPP_
#define OSRM_STORAGE_SERIALIZATION_HPP_
#ifndef OSRM_STORAGE_SERIALIZATION_HPP
#define OSRM_STORAGE_SERIALIZATION_HPP
#include "util/integer_range.hpp"
#include "util/vector_view.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/extractor.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/query_node.hpp"
#include "storage/io.hpp"
#include "util/exception.hpp"
#include "util/fingerprint.hpp"
#include "util/log.hpp"
#include "util/static_graph.hpp"
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/seek.hpp>
#include <cerrno>
#include <cstring>
#include <tuple>
#include <type_traits>
#include <cstdint>
namespace osrm
{
@@ -25,105 +14,54 @@ namespace storage
{
namespace serialization
{
// To make function calls consistent, this function returns the fixed number of properties
inline std::size_t readPropertiesCount() { return 1; }
struct HSGRHeader
template <typename T> inline void read(storage::io::FileReader &reader, stxxl::vector<T> &vec)
{
std::uint32_t checksum;
std::uint64_t number_of_nodes;
std::uint64_t number_of_edges;
};
// Reads the checksum, number of nodes and number of edges written in the header file of a `.hsgr`
// file and returns them in a HSGRHeader struct
inline HSGRHeader readHSGRHeader(io::FileReader &input_file)
{
HSGRHeader header;
input_file.ReadInto(header.checksum);
input_file.ReadInto(header.number_of_nodes);
input_file.ReadInto(header.number_of_edges);
// If we have edges, then we must have nodes.
// However, there can be nodes with no edges (some test cases create this)
BOOST_ASSERT_MSG(header.number_of_edges == 0 || header.number_of_nodes > 0,
"edges exist, but there are no nodes");
return header;
}
// Reads the graph data of a `.hsgr` file into memory
// Needs to be called after readHSGRHeader() to get the correct offset in the stream
using NodeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::NodeArrayEntry;
using EdgeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::EdgeArrayEntry;
inline void readHSGR(io::FileReader &input_file,
NodeT *node_buffer,
const std::uint64_t number_of_nodes,
EdgeT *edge_buffer,
const std::uint64_t number_of_edges)
{
BOOST_ASSERT(node_buffer);
BOOST_ASSERT(edge_buffer);
input_file.ReadInto(node_buffer, number_of_nodes);
input_file.ReadInto(edge_buffer, number_of_edges);
}
// Loads edge data from .edge files into memory which includes its
// geometry, name ID, turn instruction, lane data ID, travel mode, entry class ID
// Needs to be called after readElementCount() to get the correct offset in the stream
inline void readEdges(io::FileReader &edges_input_file,
GeometryID *geometry_list,
NameID *name_id_list,
extractor::guidance::TurnInstruction *turn_instruction_list,
LaneDataID *lane_data_id_list,
extractor::TravelMode *travel_mode_list,
EntryClassID *entry_class_id_list,
util::guidance::TurnBearing *pre_turn_bearing_list,
util::guidance::TurnBearing *post_turn_bearing_list,
const std::uint64_t number_of_edges)
{
BOOST_ASSERT(geometry_list);
BOOST_ASSERT(name_id_list);
BOOST_ASSERT(turn_instruction_list);
BOOST_ASSERT(lane_data_id_list);
BOOST_ASSERT(travel_mode_list);
BOOST_ASSERT(entry_class_id_list);
extractor::OriginalEdgeData current_edge_data;
for (std::uint64_t i = 0; i < number_of_edges; ++i)
auto size = reader.ReadOne<std::uint64_t>();
vec.reserve(size);
for (auto idx : util::irange<std::size_t>(0, size))
{
edges_input_file.ReadInto(current_edge_data);
geometry_list[i] = current_edge_data.via_geometry;
name_id_list[i] = current_edge_data.name_id;
turn_instruction_list[i] = current_edge_data.turn_instruction;
lane_data_id_list[i] = current_edge_data.lane_data_id;
travel_mode_list[i] = current_edge_data.travel_mode;
entry_class_id_list[i] = current_edge_data.entry_classid;
pre_turn_bearing_list[i] = current_edge_data.pre_turn_bearing;
post_turn_bearing_list[i] = current_edge_data.post_turn_bearing;
(void)idx;
vec.push_back(reader.ReadOne<T>());
}
}
// Loads coordinates and OSM node IDs from .nodes files into memory
// Needs to be called after readElementCount() to get the correct offset in the stream
template <typename OSMNodeIDVectorT>
void readNodes(io::FileReader &nodes_file,
util::Coordinate *coordinate_list,
OSMNodeIDVectorT &osmnodeid_list,
const std::uint64_t number_of_coordinates)
template <typename T>
inline void write(storage::io::FileWriter &writer, const stxxl::vector<T> &vec)
{
BOOST_ASSERT(coordinate_list);
extractor::QueryNode current_node;
for (std::uint64_t i = 0; i < number_of_coordinates; ++i)
writer.WriteOne(vec.size());
for (auto idx : util::irange<std::size_t>(0, vec.size()))
{
nodes_file.ReadInto(current_node);
coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
osmnodeid_list.push_back(current_node.node_id);
BOOST_ASSERT(coordinate_list[i].IsValid());
writer.WriteOne<T>(vec[idx]);
}
}
template <typename T> void read(io::FileReader &reader, std::vector<T> &data)
{
const auto count = reader.ReadElementCount64();
data.resize(count);
reader.ReadInto(data.data(), count);
}
template <typename T> void write(io::FileWriter &writer, const std::vector<T> &data)
{
const auto count = data.size();
writer.WriteElementCount64(count);
return writer.WriteFrom(data.data(), count);
}
template <typename T> void read(io::FileReader &reader, util::vector_view<T> &data)
{
const auto count = reader.ReadElementCount64();
BOOST_ASSERT(data.size() == count);
reader.ReadInto(data.data(), count);
}
template <typename T> void write(io::FileWriter &writer, const util::vector_view<T> &data)
{
const auto count = data.size();
writer.WriteElementCount64(count);
return writer.WriteFrom(data.data(), count);
}
}
}
}
+2
View File
@@ -25,6 +25,8 @@
#include <exception>
#include <thread>
#include "storage/shared_memory_ownership.hpp"
namespace osrm
{
namespace storage
@@ -0,0 +1,18 @@
#ifndef SHARED_MEMORY_OWNERSHIP_HPP
#define SHARED_MEMORY_OWNERSHIP_HPP
namespace osrm
{
namespace storage
{
enum class Ownership
{
Container,
View,
External
};
}
}
#endif // SHARED_MEMORY_OWNERSHIP_HPP
+41 -31
View File
@@ -10,13 +10,12 @@
#include <tbb/parallel_for.h>
#include <tbb/spin_mutex.h>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <fstream>
#include <vector>
namespace osrm
@@ -24,20 +23,15 @@ namespace osrm
namespace updater
{
namespace
{
namespace qi = boost::spirit::qi;
}
// Functor to parse a list of CSV files using "key,value,comment" grammar.
// Key and Value structures must be a model of Random Access Sequence.
// Also the Value structure must have source member that will be filled
// with the corresponding file index in the CSV filenames vector.
template <typename Key, typename Value> struct CSVFilesParser
{
using Iterator = boost::spirit::line_pos_iterator<boost::spirit::istream_iterator>;
using KeyRule = qi::rule<Iterator, Key()>;
using ValueRule = qi::rule<Iterator, Value()>;
using Iterator = boost::iostreams::mapped_file_source::iterator;
using KeyRule = boost::spirit::qi::rule<Iterator, Key()>;
using ValueRule = boost::spirit::qi::rule<Iterator, Value()>;
CSVFilesParser(std::size_t start_index, const KeyRule &key_rule, const ValueRule &value_rule)
: start_index(start_index), key_rule(key_rule), value_rule(value_rule)
@@ -95,30 +89,46 @@ template <typename Key, typename Value> struct CSVFilesParser
// Parse a single CSV file and return result as a vector<Key, Value>
auto ParseCSVFile(const std::string &filename, std::size_t file_id) const
{
std::ifstream input_stream(filename, std::ios::binary);
input_stream.unsetf(std::ios::skipws);
namespace qi = boost::spirit::qi;
boost::spirit::istream_iterator sfirst(input_stream), slast;
Iterator first(sfirst), last(slast);
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
ValueRule value_source =
value_rule[qi::_val = qi::_1, boost::phoenix::bind(&Value::source, qi::_val) = file_id];
qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
std::vector<std::pair<Key, Value>> result;
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
if (!ok || first != last)
try
{
const auto message =
boost::format("CSV file %1% malformed on line %2%") % filename % first.position();
if (boost::filesystem::file_size(filename) == 0)
return result;
boost::iostreams::mapped_file_source mmap(filename);
auto first = mmap.begin(), last = mmap.end();
BOOST_ASSERT(file_id <= std::numeric_limits<std::uint8_t>::max());
ValueRule value_source =
value_rule[qi::_val = qi::_1, bind(&Value::source, qi::_val) = file_id];
qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
if (!ok || first != last)
{
auto begin_of_line = first - 1;
while (begin_of_line >= mmap.begin() && *begin_of_line != '\n')
--begin_of_line;
auto line_number = std::count(mmap.begin(), first, '\n') + 1;
const auto message = boost::format("CSV file %1% malformed on line %2%:\n %3%\n") %
filename % std::to_string(line_number) %
std::string(begin_of_line + 1, std::find(first, last, '\n'));
throw util::exception(message.str() + SOURCE_REF);
}
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
return std::move(result);
}
catch (const boost::exception &e)
{
const auto message = boost::format("exception in loading %1%:\n %2%") % filename %
boost::diagnostic_information(e);
throw util::exception(message.str() + SOURCE_REF);
}
util::Log() << "Loaded " << filename << " with " << result.size() << "values";
return std::move(result);
}
const std::size_t start_index;
+2 -2
View File
@@ -49,9 +49,9 @@ struct Segment final
struct SpeedSource final
{
SpeedSource() : speed(0), weight(std::numeric_limits<double>::quiet_NaN()) {}
SpeedSource() : speed(0), rate(std::numeric_limits<double>::quiet_NaN()) {}
unsigned speed;
double weight;
double rate;
std::uint8_t source;
};
+3 -3
View File
@@ -34,9 +34,9 @@
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
do \
{ \
(void)cond; \
(void)coordinate; \
(void)msg; \
(void)(cond); \
(void)(coordinate); \
(void)(msg); \
} while (0)
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
+42 -4
View File
@@ -16,6 +16,48 @@ namespace osrm
namespace util
{
template <typename NodeID, typename Key> class GenerationArrayStorage
{
using GenerationCounter = std::uint16_t;
public:
explicit GenerationArrayStorage(std::size_t size)
: positions(size, 0), generation(1), generations(size, 0)
{
}
Key &operator[](NodeID node)
{
generation[node] = generation;
return positions[node];
}
Key peek_index(const NodeID node) const
{
if (generations[node] < generation)
{
return std::numeric_limits<Key>::max();
}
return positions[node];
}
void Clear()
{
generation++;
// if generation overflows we end up at 0 again and need to clear the vector
if (generation == 0)
{
generation = 1;
std::fill(generations.begin(), generations.end(), 0);
}
}
private:
GenerationCounter generation;
std::vector<GenerationCounter> generations;
std::vector<Key> positions;
};
template <typename NodeID, typename Key> class ArrayStorage
{
public:
@@ -92,10 +134,6 @@ template <typename NodeID,
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
class BinaryHeap
{
private:
BinaryHeap(const BinaryHeap &right);
void operator=(const BinaryHeap &right);
public:
using WeightType = Weight;
using DataType = Data;
+7
View File
@@ -239,6 +239,13 @@ class DeallocatingVector
bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]);
}
// copying is not safe since this would only do a shallow copy
DeallocatingVector(DeallocatingVector &other) = delete;
DeallocatingVector &operator=(DeallocatingVector &other) = delete;
// moving is fine
DeallocatingVector(DeallocatingVector &&other) = default;
DeallocatingVector &operator=(DeallocatingVector &&other) = default;
~DeallocatingVector() { clear(); }
friend void swap<>(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &lhs,
+12
View File
@@ -5,6 +5,8 @@
#include "util/integer_range.hpp"
#include "util/typedefs.hpp"
#include "storage/io_fwd.hpp"
#include <boost/assert.hpp>
#include <cstdint>
@@ -19,6 +21,16 @@ namespace osrm
{
namespace util
{
template <typename EdgeDataT> class DynamicGraph;
namespace serialization
{
template <typename EdgeDataT, bool UseSharedMemory>
void read(storage::io::FileReader &reader, DynamicGraph<EdgeDataT> &graph);
template <typename EdgeDataT, bool UseSharedMemory>
void write(storage::io::FileWriter &writer, const DynamicGraph<EdgeDataT> &graph);
}
template <typename EdgeDataT> class DynamicGraph
{

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