Compare commits

...

122 Commits

Author SHA1 Message Date
Patrick Niklaus 851ae2ce4f Bump OSRM version to final 5.13.0 release 2017-10-30 19:48:38 +00:00
Patrick Niklaus 577801ad38 Bump version to RC4 2017-10-26 19:54:23 +00:00
Daniel J. Hofmann 7a86b7985f Adds cardinal_directions flag to profiles and disables ref-rewriting by default 2017-10-26 19:51:09 +00:00
Denis Koronchik 41551119f2 Review fixes 2017-10-26 19:51:00 +00:00
Denis Koronchik 521636c854 Work on forward/backward ref's support 2017-10-26 19:50:49 +00:00
Patrick Niklaus 6172dffd35 Bump version 2017-10-24 10:42:59 +00:00
Michael Krasnyk 57099e4a85 Add unclassified roads to restricted_highway_whitelist, #4631 2017-10-24 10:04:44 +00:00
Patrick Niklaus 6be468bdb4 Contract the exclude-flag sub-graphs as well 2017-10-24 10:04:44 +00:00
Patrick Niklaus 29ce651493 Enable building the 5.13 branch 2017-10-20 15:24:29 +00:00
Patrick Niklaus 1b53b90eec Add missing entry to changelog 2017-10-20 15:08:18 +00:00
Patrick Niklaus 5f84032261 Bump version to RC2 2017-10-20 14:57:08 +00:00
Patrick Niklaus 9c73e42f5f Rename locations-cache -> location-cache 2017-10-20 14:56:10 +00:00
Patrick Niklaus c638499c0f Add changelog entry for changed behavior 2017-10-20 14:56:10 +00:00
Patrick Niklaus 7c5977daf6 Change --use-location-cache=false to --disbale-location-cache 2017-10-20 14:56:10 +00:00
Patrick Niklaus 253522c406 Fix tests 2017-10-20 14:56:10 +00:00
Patrick Niklaus 1e2d3882d1 Replace use of implicit_value since that broke with boost 1.65 2017-10-20 14:56:10 +00:00
Patrick Niklaus fd43586b60 Update package-lock 2017-10-18 15:02:51 +00:00
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
216 changed files with 8305 additions and 8578 deletions
+28 -13
View File
@@ -13,6 +13,7 @@ notifications:
branches:
only:
- master
- "5.13"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@@ -68,10 +69,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 +104,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 +113,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 +196,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 +205,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 +220,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 +229,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 +244,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 +253,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 +268,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 +277,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 +352,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}
+27 -7
View File
@@ -1,15 +1,35 @@
# UNRELEASED
# 5.13.0
- 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; off by default see `profile.cardinal_directions`
- 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
- Added `forward_ref` and `backward_ref` support
- 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
- Removed `.osrm.core` file since CoreCH is deprecated now.
- Tools:
- Because of boost/program_options#32 with boost 1.65+ we needed to change the behavior of the following flags to not accept `={true|false}` anymore:
- `--use-locations-cache=false` becomes `--disable-location-cache`
- `--parse-conditional-restrictions=true` becomes `--parse-conditional-restrictions`
- The deprecated options `--use-level-cache` and `--generate-edge-lookup`
- Bugfixes:
- Fixed #4348: Some cases of sliproads pre-processing were broken
- Fixed #4331: Correctly compute left/right modifiers of forks in case the fork is curved.
- Fixed #4472: Correctly count the number of lanes using the delimter in `turn:lanes` tag.
- Fixed #4214: Multiple runs of `osrm-partition` lead to crash.
- Fixed #4348: Fix assorted problems around slip roads.
- Fixed #4420: A bug that would result in unnecessary instructions, due to problems in suffix/prefix detection
- Algorithm
- Deprecate CoreCH functionality. Usage of CoreCH specific options will fall back to using CH with core_factor of 1.0
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices which yields speedup.
# 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 +92,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'
};
+7 -53
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.
@@ -169,7 +171,9 @@ is_startpoint | Boolean | Can a journey start on this
roundabout | Boolean | Is this part of a roundabout?
circular | Boolean | Is this part of a non-roundabout circular junction?
name | String | Name of the way
ref | String | Road number
ref | String | Road number (equal to set `forward_ref` and `backward_ref` with one value)
forward_ref | String | Road number in forward way direction
backward_ref | String | Road number in backward way direction
destinations | String | The road's destinations
exits | String | The ramp's exit numbers or names
pronunciation | String | Name pronunciation
@@ -179,56 +183,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.
+10 -9
View File
@@ -157,15 +157,16 @@ Feature: Car - Restricted access
Scenario: Car - Access combinations
Then routability should be
| highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
| runway | private | | | permissive | x | x | |
| primary | forestry | | yes | | x | x | |
| cycleway | | | designated | | x | x | |
| residential | | yes | no | | | | |
| motorway | yes | permissive | | private | x | | implied oneway |
| trunk | agricultural | designated | permissive | no | | | |
| pedestrian | | | | | | | |
| pedestrian | | | | destination | | | temporary disabled #3773 |
| highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
| runway | private | | | permissive | x | x | |
| primary | forestry | | yes | | x | x | |
| cycleway | | | designated | | x | x | |
| unclassified | | | destination | destination | x | x | |
| residential | | yes | no | | | | |
| motorway | yes | permissive | | private | x | | implied oneway |
| trunk | agricultural | designated | permissive | no | | | |
| pedestrian | | | | | | | |
| pedestrian | | | | destination | | | temporary disabled #3773 |
Scenario: Car - Ignore access tags for other modes
Then routability should be
+179 -179
View File
@@ -17,27 +17,27 @@ Feature: Car - Turn restrictions
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
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
@@ -677,7 +677,7 @@ Feature: Car - Turn restrictions
# https://www.openstreetmap.org/#map=18/38.91099/-77.00888
@no_turning @conditionals
Scenario: Car - DC North capitol situation, two on one off
Given the extract extra arguments "--parse-conditional-restrictions=1"
Given the extract extra arguments "--parse-conditional-restrictions"
# 9pm Wed 02 May, 2017 UTC, 5pm EDT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
@@ -724,7 +724,7 @@ Feature: Car - Turn restrictions
@no_turning @conditionals
Scenario: Car - DC North capitol situation, one on two off
Given the extract extra arguments "--parse-conditional-restrictions=1"
Given the extract extra arguments "--parse-conditional-restrictions"
# 10:30am utc, wed, 6:30am est
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
@@ -848,7 +848,7 @@ Feature: Car - Turn restrictions
@only_turning @conditionals
Scenario: Car - Somewhere in London, the UK, GMT timezone
Given the extract extra arguments "--parse-conditional-restrictions=1"
Given the extract extra arguments "--parse-conditional-restrictions"
# 9am UTC, 10am BST
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
+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
+329
View File
@@ -0,0 +1,329 @@
@routing @car @relations
Feature: Car - route relations
Background:
Given the profile "car"
Scenario: Assignment using relation membership roles
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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: No cardinal directions by default
Given the profile file "car" initialized with
"""
profile.cardinal_directions = false
"""
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,I 80 |
| c,d | eastbound,eastbound | I 80; CO 93,I 80; CO 93 |
Scenario: No cardinal directions by default
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,I 80 |
| c,d | eastbound,eastbound | I 80; CO 93,I 80; CO 93 |
Scenario: Assignment using relation direction property (no role on members)
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 |
| a,b | mainroad,mainroad | I 80 $west,I 80 $west |
| b,a | mainroad,mainroad | I 80 $east,I 80 $east |
Scenario: Conflict between role and direction
Given the profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 profile file "car" initialized with
"""
profile.cardinal_directions = true
"""
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 --disable-location-cache"
Then it should exit with an error
And stderr should contain "invalid location"
Scenario: osrm-extract location-dependent data
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
for _, key in ipairs({'answer', 'boolean', 'object', 'array'}) do
print (key .. ' ' .. tostring(way:get_location_tag(key)))
end
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node map
"""
a b
"""
And the ways with locations
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --disable-location-cache"
Then it should exit successfully
And stdout should contain "answer 42"
And stdout should contain "boolean true"
And stdout should contain "array nil"
And stdout should contain "object nil"
Scenario: osrm-extract location-dependent data with multi-polygons
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print('ISO3166-1 ' .. (way:get_location_tag('ISO3166-1') or 'none'))
print('answer ' .. (way:get_location_tag('answer') or 'none'))
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node locations
| node | lat | lon | id |
| a | 22.4903670 | 113.9455227 | 1 |
| b | 22.4901701 | 113.9455899 | 2 |
| c | 22.4901852 | 113.9458608 | 3 |
| d | 22.4904033 | 113.9456999 | 4 |
| e | 1.1 | 1 | 5 |
| f | 1.2 | 1 | 6 |
And the ways with locations
| nodes | # |
| ab | Hong Kong |
| cd | China Mainland |
| ef | Null Island |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson --location-dependent-data test/data/regions/hong-kong.geojson --disable-location-cache"
Then it should exit successfully
And stdout should not contain "1 GeoJSON polygon"
And stdout should contain "2 GeoJSON polygons"
And stdout should contain "ISO3166-1 HK"
And stdout should contain "ISO3166-1 none"
And stdout should contain "answer 42"
Scenario: osrm-extract location-dependent data via locations cache
Given the profile file
"""
functions = require('testbot')
functions.process_way = function(profile, way, result, relations)
print ('answer ' .. tostring(way:get_location_tag('answer')))
result.forward_mode = mode.driving
result.forward_speed = 1
end
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file} --location-dependent-data test/data/regions/null-island.geojson"
Then it should exit successfully
And stdout should contain "answer 42"
+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,18 @@ 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));
contractGraph(filtered_core_graph, is_shared_core, is_shared_core, node_weights);
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;
};
}
}
+19 -10
View File
@@ -46,28 +46,32 @@ struct ExtractionWay
backward_rate = -1;
duration = -1;
weight = -1;
roundabout = false;
circular = false;
is_startpoint = true;
name.clear();
ref.clear();
forward_ref.clear();
backward_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
void SetName(const char *value) { detail::maybeSetString(name, value); }
const char *GetName() const { return name.c_str(); }
void SetRef(const char *value) { detail::maybeSetString(ref, value); }
const char *GetRef() const { return ref.c_str(); }
void SetForwardRef(const char *value) { detail::maybeSetString(forward_ref, value); }
const char *GetForwardRef() const { return forward_ref.c_str(); }
void SetBackwardRef(const char *value) { detail::maybeSetString(backward_ref, value); }
const char *GetBackwardRef() const { return backward_ref.c_str(); }
void SetDestinations(const char *value) { detail::maybeSetString(destinations, value); }
const char *GetDestinations() const { return destinations.c_str(); }
void SetExits(const char *value) { detail::maybeSetString(exits, value); }
@@ -100,7 +104,8 @@ struct ExtractionWay
// weight of the whole way in both directions
double weight;
std::string name;
std::string ref;
std::string forward_ref;
std::string backward_ref;
std::string pronunciation;
std::string destinations;
std::string exits;
@@ -109,11 +114,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,
+2 -1
View File
@@ -63,7 +63,8 @@ class ExtractorCallbacks
// actually maps to name ids
using MapKey = std::tuple<std::string, std::string, std::string, std::string, std::string>;
using MapVal = unsigned;
std::unordered_map<MapKey, MapVal> string_map;
using StringMap = std::unordered_map<MapKey, MapVal>;
StringMap string_map;
ExtractionContainers &external_memory;
std::unordered_map<std::string, ClassData> &classes_map;
guidance::LaneDescriptionMap &lane_description_map;
+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;
};
}
}

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