Compare commits

...

105 Commits

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

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