Compare commits

...

234 Commits

Author SHA1 Message Date
Patrick Niklaus 254ee07942 Add new sanity check assertions to UnpackPath 2016-05-23 23:15:15 +02:00
Patrick Niklaus 0bf8bd2230 Remove invalid assertion.
This ports the matching change from RoutingBase.
2016-05-23 23:15:15 +02:00
Michael Krasnyk b5225f07cb Fix #2413 by converting enums to unsigned char constants 2016-05-23 18:33:24 +02:00
Moritz Kobitzsch abed7690d0 fix continue on obvious 2016-05-23 17:55:30 +02:00
Patrick Niklaus f96174ddbe Merge pull request #2428 from zimathias/disable-access-logging-option
Disable access logging option
2016-05-23 10:12:42 -04:00
Mathias Gug e5b713841a Fix style. 2016-05-20 12:47:47 -07:00
Mathias Gug 3b1b12069f Add changelog entry. 2016-05-20 12:47:47 -07:00
Mathias Gug 1635f7351d Support environment variable to disable http requests logging. 2016-05-20 12:47:47 -07:00
Daniel J. Hofmann ce5ae411c1 Resurrect Flat Map + Binary Search commit from PR 2412 2016-05-20 20:43:45 +02:00
Patrick Niklaus d1bc32fb31 Add comments and debug code 2016-05-20 18:52:29 +02:00
Patrick Niklaus f9f87f25d4 Use elogate() to fixup geometry when merging steps, fixes #2424 2016-05-20 18:52:29 +02:00
Patrick Niklaus 89aa6b7881 Add regression test for #2424 2016-05-20 18:52:29 +02:00
Patrick Niklaus edf9e0c1ed [skip ci] Update changelog and OSRM version 2016-05-20 18:52:00 +02:00
Dane Springmeyer c2e520ad9d Fix linking of osrm-example to boost_iostreams
Fixes linking error seen on OS X:

```
[ 50%] Linking CXX executable osrm-example
/Users/dane/.homebrew/Cellar/cmake/3.5.0/bin/cmake -E cmake_link_script CMakeFiles/osrm-example.dir/link.txt --verbose=1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++    -std=c++11  -Wl,-search_paths_first -Wl,-headerpad_max_install_names  CMakeFiles/osrm-example.dir/example.cpp.o  -o osrm-example  /Users/dane/projects/osrm-backend/here/lib/libOSRM.a /Users/dane/.homebrew/lib/libboost_filesystem-mt.dylib /Users/dane/.homebrew/lib/libboost_system-mt.dylib /Users/dane/.homebrew/lib/libboost_thread-mt.dylib /Users/dane/.homebrew/lib/libboost_chrono-mt.dylib /Users/dane/.homebrew/lib/libboost_date_time-mt.dylib /Users/dane/.homebrew/lib/libboost_atomic-mt.dylib 
undef: __ZN5boost9iostreams18mapped_file_source9open_implERKNS0_24basic_mapped_file_paramsINS0_6detail4pathEEE
undef: __ZN5boost9iostreams18mapped_file_sourceC1Ev
undef: __ZNK5boost9iostreams18mapped_file_source4sizeEv
undef: __ZNK5boost9iostreams18mapped_file_source4dataEv
Undefined symbols for architecture x86_64:
  "boost::iostreams::mapped_file_source::open_impl(boost::iostreams::basic_mapped_file_params<boost::iostreams::detail::path> const&)", referenced from:
      void boost::iostreams::mapped_file_source::open<boost::filesystem::path>(boost::filesystem::path const&, unsigned long, long) in libOSRM.a(engine.cpp.o)
  "boost::iostreams::mapped_file_source::mapped_file_source()", referenced from:
      osrm::engine::datafacade::SharedDataFacade::CheckAndReloadFacade() in libOSRM.a(engine.cpp.o)
      osrm::engine::datafacade::InternalDataFacade::InternalDataFacade(osrm::storage::StorageConfig const&) in libOSRM.a(engine.cpp.o)
  "boost::iostreams::mapped_file_source::size() const", referenced from:
      osrm::engine::datafacade::SharedDataFacade::CheckAndReloadFacade() in libOSRM.a(engine.cpp.o)
      osrm::engine::datafacade::InternalDataFacade::InternalDataFacade(osrm::storage::StorageConfig const&) in libOSRM.a(engine.cpp.o)
  "boost::iostreams::mapped_file_source::data() const", referenced from:
      osrm::engine::datafacade::SharedDataFacade::CheckAndReloadFacade() in libOSRM.a(engine.cpp.o)
      osrm::engine::datafacade::InternalDataFacade::InternalDataFacade(osrm::storage::StorageConfig const&) in libOSRM.a(engine.cpp.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
2016-05-20 16:04:18 +02:00
Dane Springmeyer 7649187095 workaround boostorg/numeric_conversion#4 2016-05-20 16:03:19 +02:00
Dane Springmeyer fe39d0fd10 disable BOOST_TEST_DYN_LINK if Boost_USE_STATIC_LIBS 2016-05-20 00:03:37 -04:00
Patrick Niklaus 98b83b7208 Fix library test 2016-05-19 16:44:31 +02:00
Patrick Niklaus 57321979ae Remove leftover debugging code 2016-05-19 16:44:31 +02:00
Patrick Niklaus e3ce0c5887 Add fuzzy matching for bearings and intersections list 2016-05-19 16:44:31 +02:00
Patrick Niklaus 95af72c70c Make intersection backwards compatible
For `depart` and `arrive` `step.intersections[0].{bearings|entry}` will have
only one entry.
2016-05-19 16:44:31 +02:00
Patrick Niklaus 3b37769624 Use bearing_before and bearing_after in the bearings field 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch d150df1c5c format 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch a322e27e05 update changelog/docs 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch 98fe0badbe fix loading in storage 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch 44b841a25d fix storage 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch 9c8bf820de adjusted to in/out. only emit one of them for depart/arrive 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch 4d9aa65e78 intersection classes with variable degree of discretization 2016-05-19 16:44:31 +02:00
Moritz Kobitzsch 0f3942558f version using discrete values stored directly at intersection 2016-05-19 16:43:46 +02:00
Moritz Kobitzsch ba074b0116 initial version of intersection classification 2016-05-19 16:43:46 +02:00
Daniel J. Hofmann 6aa97048df Rip out custom CSV parser code and its third_party dependency 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann d9a5c79ea6 Map leaf nodes to RAM and iterate over them potentially in parallel 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann 9d7714c714 Make looping through all leaf nodes less confusing 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann 8291be375a Expose concurrency in saving files 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann 0a73737f69 Fold parsing and data loading in concurrently executing action 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann 2fd1b6c913 Expose concurrency between intern/external node map and geometries 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann ea38a1d880 Parse multiple files concurrently 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann f576e13c51 Concurrent lookup hashtables 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann ee7bb8731a Expose concurrency between segment speeds and turn penalties 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann da0c3ff394 Refactor edge weight parsing code 2016-05-19 00:01:54 +02:00
Daniel J. Hofmann 6ae559b42b Throw error if edge based graph file could not be loaded 2016-05-19 00:01:54 +02:00
Mathias Gug 95ca6ebdaa Update CHANGELOG entry. 2016-05-18 23:59:52 +02:00
Mathias Gug 0d6964d9c8 Add CHANGELOG entry. 2016-05-18 23:59:52 +02:00
Mathias Gug ba386d4b2c Document environment variable. 2016-05-18 23:59:52 +02:00
Mathias Gug b5ffb51e18 Signal the parent process when we're ready to serve requests.
This can be used for a hot reload of the process binary. The supervising
process can be told when the new process is ready to serve requests.
2016-05-18 23:59:52 +02:00
Moritz Kobitzsch a9f674497a emit turn-straight for obvious turns where the main road continues 2016-05-18 19:54:53 +02:00
Patrick Niklaus 1e8a92ccb4 Add changelog entry 2016-05-18 19:16:44 +02:00
Mathias Gug b9178bb8c7 Fix build on windows. 2016-05-18 19:13:18 +02:00
Mathias Gug 520b29d0d5 Use const for option. Include proper header files. 2016-05-18 19:13:18 +02:00
Mathias Gug fe397e6953 Support SO_REUSEPORT option
so that multiple osrm-routed processes can bind to the same port.
2016-05-18 19:13:18 +02:00
Patrick Niklaus dcb741d827 Merge pull request #2403 from oxidase/refactor/duration-parser
Refactoring of iso_8601_grammar
2016-05-17 12:26:28 -04:00
Michael Krasnyk 508c205d35 Refactoring of iso_8601_grammar
* formats 'hh:mm:ss' and ISO 8601 are merged into one grammar.
* iso_8601_grammar is changed to static const.
* iso_8601_grammar supports formats P[n]DT[n]H[n]M[n]S, P[n]W,
  and part of alternative PTHHMMSS and extended PTHH:MM:SS formats.
2016-05-17 00:39:32 +02:00
Daniel J. Hofmann d5294bb5d0 Silences warnings when running npm test 2016-05-16 14:43:54 -04:00
Patrick Niklaus 6ed9be31ca Merge pull request #2408 from oxidase/master
Remove latitude rounding in yToLat
2016-05-16 17:04:49 +02:00
Michael Krasnyk 3bbd3a8a65 Remove latitude rounding in yToLat 2016-05-16 00:53:33 +02:00
Daniel Patterson 73a608895a Merge pull request #2402 from Project-OSRM/fix_docker
Remove Ruby from docker setup, use Node.
2016-05-13 13:38:10 -07:00
Daniel Patterson 96c73baeb3 Remove Ruby from docker setup, use Node. 2016-05-13 12:32:36 -07:00
Patrick Niklaus 73113f5eb8 Fix codecov.yml 2016-05-12 17:56:40 +02:00
Patrick Niklaus 7b74b86891 Add codecov file 2016-05-12 01:17:16 +02:00
Daniel Patterson 0903b8227f Example of the annotation response value. 2016-05-12 01:11:09 +02:00
Daniel Patterson fa525ad610 Return an array with meta-data for each coordinate.
Currently supports duration and distance for each coordinate.

This is particularly useful in map-matching, comparing how
a trip progresses compared to a real GPS trace that is
map-matched.
2016-05-12 01:11:09 +02:00
Daniel J. Hofmann 0f2bb5dde5 Disable builing components tool by default until GDAL 2 compatibility #1738 lands 2016-05-12 00:25:18 +02:00
Patrick Niklaus 84dc1b6845 [skip ci] Use codecov badge 2016-05-11 22:45:07 +02:00
Patrick Niklaus 4ce1a37772 Limit osrm-extact to 3 jobs because OOM 2016-05-11 22:43:26 +02:00
Patrick Niklaus 8dd4cc5c40 Integrate codecov 2016-05-11 22:43:18 +02:00
Patrick Niklaus 6aed145dae [skip ci] Rephrased the API docs in terms of adding new types 2016-05-09 18:39:30 +02:00
Patrick Niklaus d15cc77b0b Merge pull request #2386 from oxidase/rtree-optimize-addition
Missing two commits in StaticRTree changes
2016-05-08 14:20:59 +02:00
Michael Krasnyk 24a75d37fb Approximate inverse Gudermannian function by a Padé approximant 2016-05-08 06:00:21 +02:00
Michael Krasnyk 7e80dae59b Fix MSVS build. 2016-05-08 06:00:21 +02:00
Patrick Niklaus 7316c48e9f Changelog entry for StaticRTree changes 2016-05-07 23:52:11 +02:00
Patrick Niklaus c520c7a24a Fix rtree benchmark 2016-05-07 23:52:11 +02:00
Patrick Niklaus 7564633045 Update SearchInBox to not copy TreeNode 2016-05-07 23:52:11 +02:00
Patrick Niklaus 7174c5d036 Make StaticRTree and facades const 2016-05-07 23:52:11 +02:00
Patrick Niklaus ddd128ce0e Only use const-ref for coordinate vector 2016-05-07 23:52:11 +02:00
Patrick Niklaus f5aa5c0769 Don't wrap StaticRTree in thread-specfic ptr 2016-05-07 23:52:11 +02:00
Michael Krasnyk 2acde49f0f Make LeafNode aligned to memory pages.
Changes:
* LeafNode is aligned to LEAF_PAGE_SIZE.
  Alignment brings 24 bytes memory overhead for 4096, but reduces
  cache misses rate.
* Unused m_element_count from leaf nodes file.
  The size is computed as m_leaves_region.size() / LEAF_PAGE_SIZE.
* Added try/catch for mmap exceptions messages.
2016-05-07 23:52:11 +02:00
Michael Krasnyk 8849015bbf Fix construct_multiple_levels_test
candidate_cache is removed because of failing test
make util-tests && ./unit_tests/util-tests --run_test=*/construct_multiple_levels_test
first bad commit: [9692be6f50] Add cache for CandidateSegments to reduce heap worke even more

Now SegmentIndex contains leaf index, object index and fixed_projected_coordinate
2016-05-07 23:52:11 +02:00
Michael Krasnyk 70cd7a94ec Fix memory mapping "Invalid argument" exception. 2016-05-07 23:52:11 +02:00
Patrick Niklaus 3984dea34b Use mmap in StaticRTree 2016-05-07 23:52:11 +02:00
Patrick Niklaus b11b471aa4 Move LoadLeafFromDisk to return by value 2016-05-07 23:52:11 +02:00
Patrick Niklaus 63754df4d4 Add cache for CandidateSegments to reduce heap worke even more 2016-05-07 23:52:11 +02:00
Patrick Niklaus e644424508 Only save TreeNode index in search tree x3 speedup 2016-05-07 23:52:11 +02:00
Patrick Niklaus 4f6eef3d16 Merge pull request #2376 from oxidase/fix/addition-to-2356
Addition to fix #2356
2016-05-07 12:47:28 +02:00
Michael Krasnyk e2e8104864 Addition to fix #2356
Updated unit tests for the Hint parser and
added emplacement of empty hints.
2016-05-07 09:47:32 +02:00
Patrick Niklaus 96127c289c Set OSX timeout to a minute 2016-05-06 10:36:40 +02:00
Patrick Niklaus cfed65f7ea Double timeout again 2016-05-05 21:07:38 +02:00
Patrick Niklaus c2263fec9b One TIMEOUT to rule them all 2016-05-05 18:36:30 +02:00
Patrick Niklaus 497720d060 Bump timeout and lower jobs on OSX 2016-05-05 17:12:22 +02:00
Patrick Niklaus 238366e71f Merge pull request #2373 from oxidase/master
Fix #2362 by using generic path strings
2016-05-05 15:57:51 +02:00
Michael Krasnyk 2c8cf26e74 Fix build break in MSVC
fatal error C1189: #error:  "This header can't be used in operating systems without XSI (System V) shared memory support"
2016-05-05 13:24:27 +02:00
Michael Krasnyk c87ae5612a Fix #2362 by using generic path strings
In windows native strings in Lua incorrectly
interpreted because native separators must be escaped.
Use of generic strings prevent use of backslashes and
"Generic paths are portable and independent of the operating system.".
2016-05-05 12:10:45 +02:00
Patrick Niklaus a2d83753bc Install ccmake on OSX 2016-05-05 11:39:15 +02:00
Patrick Niklaus eedf75d951 Correct path to test data 2016-05-04 20:44:05 +02:00
Patrick Niklaus 3f51a1ae2e Run tests from build directory 2016-05-04 19:46:27 +02:00
Patrick Niklaus a000f80705 [skip ci] Use 3 jobs on travis to utilize cores better 2016-05-04 19:39:52 +02:00
Patrick Niklaus 7030bff7f7 Fix typo in compiler name 2016-05-04 19:24:13 +02:00
Patrick Niklaus bb0b7fd2d1 Modify compiler name for ccache key 2016-05-04 19:22:43 +02:00
Patrick Niklaus 71e1f3679e Restructure travis run 2016-05-04 19:12:07 +02:00
Patrick Niklaus b33517b099 Remove pip from dependencies 2016-05-04 18:55:29 +02:00
Patrick Niklaus f3d5336892 Lint .travis.yml 2016-05-04 18:46:08 +02:00
Patrick Niklaus d81f25d54e Enable ccache compression 2016-05-04 18:42:47 +02:00
Patrick Niklaus 44ebdfeb2d [skip ci] Update changelog 2016-05-04 18:05:37 +02:00
Daniel J. Hofmann a5a7a03fa0 Cucumber test for destination:ref and no destination=* 2016-05-04 15:28:34 +02:00
Daniel J. Hofmann 363d2145bd Register a way's .nodes() function for use in the profile's way_function.
Can be used as in:

    function way_function(way, result)
      for node in way:get_nodes() do
        local id = node:id()
        io.write(">>> " .. id .. "\n")
      end

      -- ...
    end

Warning: we do not use libosmium's location cache, therefore .location()
on the nodes will crash at runtime. Once we switch to using libosmium's
cache this should work. Until then, you can use the node id now.
2016-05-04 15:28:34 +02:00
Daniel J. Hofmann c7e19396a4 Guard against mis-tagging: only use destination tag in combination with oneway tag 2016-05-04 15:28:34 +02:00
Daniel J. Hofmann 445e5bed49 Respect ';'-separated list in destination:ref tag 2016-05-04 15:28:34 +02:00
Daniel J. Hofmann 4cf94319df Basic destination sign handling.
This first part in our Exit Sign / Destination Sign quest re-wires
the `destination=` and `destination:ref=` tag to the `ref=` tag (in case
it's the highway does not already have a `ref=` tag).

Doing some analysis on both Berlin and San Francisco it looks like this
will add a couple of thousand `ref=` tags that we will announce in guidance.

References:
- https://github.com/Project-OSRM/osrm-backend/issues/2267#issuecomment-214771682
- http://wiki.openstreetmap.org/wiki/Key:destination
- http://wiki.openstreetmap.org/wiki/Proposed_features/Destination_details
2016-05-04 15:28:34 +02:00
Patrick Niklaus 1bb88b374e Make hint values optional, fixes issue 2356 2016-05-04 15:24:48 +02:00
Patrick Niklaus 35fac07581 Add failing test for empty hint 2016-05-04 15:24:48 +02:00
Patrick Niklaus 9287475b2a ccache needs language: cpp 2016-05-04 15:09:02 +02:00
Patrick Niklaus b4976f89f2 APT seems slow, try explicitly enabling 2016-05-04 14:27:44 +02:00
Patrick Niklaus 93c8674a40 Disable coverage builds since coveralls is broken 2016-05-04 14:02:11 +02:00
Moritz Kobitzsch d5f21fd13a fix test-case 2016-05-04 14:00:34 +02:00
Patrick Niklaus 04eef0463a Fix the second test that breaks because of phantom node 2016-05-04 14:00:34 +02:00
Patrick Niklaus 82c3bc7b0e Adapt tests to desired behaviour 2016-05-04 14:00:34 +02:00
Patrick Niklaus 1d33cb96f5 Fix missing semicolon in cucumber support code 2016-05-04 14:00:34 +02:00
Moritz Kobitzsch 648646068c additional testcase on what I would expect 2016-05-04 14:00:34 +02:00
Daniel Patterson f251f93a11 Fix summary generation when empty strings are present.
Also corrects step ordering when steps have equal durations.
2016-05-04 14:00:34 +02:00
Patrick Niklaus aab1aad8f4 Enable ccache 2016-05-04 13:54:04 +02:00
Patrick Niklaus 65a6dc704e Disable all release builds but one 2016-05-04 13:41:55 +02:00
Moritz Kobitzsch 6018fcf490 Introduce on_ramp and off_ramp, deprecate ramp 2016-05-04 12:09:54 +02:00
Moritz Kobitzsch 1e6888c0d3 fix new-name on empty strings 2016-05-04 10:52:55 +02:00
Patrick Niklaus c7303be33b [skip ci] Add specifics about how we interpret semver 2016-05-03 23:36:27 +02:00
Lauren Budorick d8acf76f2d Fix wrong assertion size in CompressedEdgeContainer::GetLastEdgeSourceID 2016-05-03 21:50:27 +02:00
Moritz Kobitzsch 08248e3853 fix 2349 2016-05-03 21:14:31 +02:00
Moritz Kobitzsch 78acc6f215 fix search with u-turn 2016-05-03 21:13:22 +02:00
Patrick Niklaus a4f1dc536d Trip plugin does not have a continue_straight parameter, use false 2016-05-03 21:13:22 +02:00
jperaltamalvar 57a30dd375 Remove more typename
Needed to compile con Windows
2016-05-03 16:00:44 +02:00
Daniel J. Hofmann 5517ee334f Remove typename prefix from non-dependent type alias
I think VS is predantic but actually right here.

References:
- http://eel.is/c++draft/namespace.udecl#19
2016-05-03 12:00:40 +02:00
Daniel J. Hofmann 30af544919 Changelog for street name assembly 2016-05-03 00:09:17 +02:00
Daniel J. Hofmann f0069d3dcc Makes bicycle and foot profile's name and ref tag handling consistent with car profile 2016-05-03 00:09:17 +02:00
Patrick Niklaus 206bdff9e7 Inline and vectorize haversine for GetPathDistance 2016-05-02 19:53:42 +02:00
Patrick Niklaus c32270b2b8 Make projectOnLine inline-able 2016-05-02 19:53:05 +02:00
Patrick Niklaus cc03402570 Use pass-by-copy for Coordinate 2016-05-02 19:51:32 +02:00
Patrick Niklaus 21a76f1867 Move coordinate constructors to header to enable inlining 2016-05-02 19:50:52 +02:00
Patrick Niklaus 212ad94c90 x2 speedup in Douglas Peucker by projecting all coordinates first 2016-05-02 19:50:33 +02:00
Patrick Niklaus 378d9f4112 Remove debug ouput from post-processing 2016-05-02 19:47:59 +02:00
Patrick Niklaus e341d367d8 Move detail:: to osrm::detail:: 2016-05-02 18:36:32 +02:00
Daniel J. Hofmann 98937b187f We require Visual Studio 2015+
References:
- https://github.com/Project-OSRM/osrm-backend/issues/2341#issuecomment-216231618
2016-05-02 17:50:54 +02:00
Moritz Kobitzsch 59168e21b4 remove unnecessary warnings, initialize correctly 2016-05-02 17:29:37 +02:00
Patrick Niklaus d12a95b4ef Fix naming convention of Percent 2016-05-02 17:25:58 +02:00
Patrick Niklaus 83482afa02 Fix naming conventions of TrajanSCC 2016-05-02 17:25:58 +02:00
Patrick Niklaus e470d1ae1c Fix naming convention in RasterSource 2016-05-02 17:25:58 +02:00
Patrick Niklaus e504128587 Fix naming convention in HiddenMarkovModell 2016-05-02 17:25:58 +02:00
Patrick Niklaus 1ab6c07bad Fix naming convention in BayesClassifier 2016-05-02 17:25:58 +02:00
Patrick Niklaus 5ce465ce23 Remove extra ; in PostProcessing 2016-05-02 17:25:58 +02:00
Patrick Niklaus a8b730576f Fix naming convention in GeospatialQuery 2016-05-02 17:25:58 +02:00
Patrick Niklaus b796033473 Clean up naming conventions in CRC32 code 2016-05-02 17:25:58 +02:00
Patrick Niklaus d078ed67ca Fix naming convention in GraphContractor 2016-05-02 17:25:58 +02:00
Lauren Budorick 346146d834 Address comments from b89164c14e (#2346) 2016-05-02 08:00:27 -07:00
Patrick Niklaus 64307ea882 Add missing headers and remove dead code 2016-04-29 20:02:08 +02:00
Patrick Niklaus 578eda7d28 [skip ci] Add release docs 2016-04-29 14:00:10 +02:00
Patrick Niklaus 505f4cb4a2 [skip ci] Add profile documentation 2016-04-29 13:10:43 +02:00
Patrick Niklaus bac6b729bf Overhault the README 2016-04-29 13:00:27 +02:00
Patrick Niklaus d3a5cadb6c [skip ci] Fix linkt to C++ library 2016-04-29 12:26:04 +02:00
Patrick Niklaus 65351faf83 [skip ci] Move correct docs. 2016-04-29 12:24:21 +02:00
Patrick Niklaus 3aa1c5f13c Link docs from README 2016-04-29 12:20:51 +02:00
Patrick Niklaus 8f3fe410b8 Import docs from the wiki 2016-04-29 12:16:19 +02:00
Patrick Niklaus ff3bf32b11 Merge pull request #2342 from Project-OSRM/publish-win-binaries
make AppVeyor publish binaries again
2016-04-29 11:16:27 +02:00
bergwerkgis 38cb01a30e [skip travis] make AppVeyor publish binaries again 2016-04-29 10:32:29 +02:00
Lauren Budorick b8f7569e93 Implement arbitrary turn penalty file IO and integration (#2306)
Closes #1830
2016-04-29 00:48:13 -07:00
Moritz Kobitzsch cf17bd38eb Revert "Revert "switched to space separated suffix/prefix only"" 2016-04-28 14:59:17 +02:00
Patrick Niklaus 930f6df2cb Fixes #2335, map matching was using shortest path with uturns disabled 2016-04-28 12:02:31 +02:00
Patrick Niklaus e88106e990 Revert "switched to space separated suffix/prefix only"
This reverts commit e9e935303c.
2016-04-27 23:20:10 +02:00
Patrick Niklaus 21f64c75eb Merge pull request #2324 from oxidase/master
Fix syntax error position indicators in parameters queries
2016-04-27 23:15:16 +02:00
Michael Krasnyk 5186b9490d Fix syntax error position indicators in parameters queries
To fix #2193 prefix_length member variable has been added to ParsedURL
that is set to the length of "/service/version/profile/" prefix
when the prefix is accepted by the parser.
Also BOOST_FUSION_ADAPT_STRUCT for osrm::server::api::ParsedURL
has been moved from header to url_parser.cpp to speed up compilation
of CUs that do not use the fusion adaption.
2016-04-27 19:52:23 +02:00
Moritz Kobitzsch e9e935303c switched to space separated suffix/prefix only 2016-04-27 19:12:24 +02:00
Moritz Kobitzsch a154d71841 enable suppression name suffix changes 2016-04-27 18:10:56 +02:00
Moritz Kobitzsch fddb035539 suppress name additions (xxx -> xxxbridge) 2016-04-27 12:13:42 +02:00
Moritz Kobitzsch 1544a08ea2 introduce roundabout-turns into instruction set 2016-04-27 12:13:42 +02:00
Moritz Kobitzsch 8d68d4c050 fix copy-paste errors in guidance tests 2016-04-26 13:43:22 +02:00
Moritz Kobitzsch 62a1290043 remove invalid assertion 2016-04-26 13:16:44 +02:00
Moritz Kobitzsch c5e1742150 fix post-processing for local paths, fixes #2310 2016-04-26 13:15:46 +02:00
Moritz Kobitzsch 754bc2d274 handle combined turns at segregated roads 2016-04-26 13:13:20 +02:00
Moritz Kobitzsch 3ac061c546 fix guidance issues / improve tests 2016-04-26 10:34:39 +02:00
Moritz Kobitzsch e59a7926a2 roundabout for segregated entry roads 2016-04-26 01:01:09 +02:00
Moritz Kobitzsch be5b49e391 Fix local path looping, fixes #2309 2016-04-25 19:37:59 +02:00
Moritz Kobitzsch 7b32d3184c remove unused instruction types 2016-04-25 19:24:59 +02:00
Moritz Kobitzsch d770c35245 refactor guidance 2016-04-25 19:24:59 +02:00
Daniel J. Hofmann e04baef3bb Do not copy geometries in loop 2016-04-25 12:12:32 +02:00
Patrick Niklaus 9d3ad22bc7 Fix path to monaco data 2016-04-25 00:46:36 +02:00
Patrick Niklaus cc35d15b2d More folds and reorder some build instructions 2016-04-25 00:19:48 +02:00
Patrick Niklaus 15e3928906 Merge pull request #2312 from oxidase/stateless-parameters-grammars
Stateless parameters grammars and fix for PhantomNode bitfields packing in MSVC
2016-04-24 23:45:51 +02:00
Michael Krasnyk 4363fd64c4 Fix for PhantomNode packing in MSVC
Changed bool to uint32_t in bit fields to have 4-byte packings for 32 bits:
"c++ compilers will allocate bit-fields in memory as follows:
several consecutive bit-field members of the same type will
be allocated sequentially. As soon as a new type needs to be allocated,
it will be aligned with the beginning of the next logical memory block."

References:
- https://msdn.microsoft.com/en-us/library/ewwyfdbe.aspx
- http://stackoverflow.com/questions/308364/c-bitfield-packing-with-bools/308383#308383
2016-04-24 14:06:48 +02:00
Michael Krasnyk dac2f93383 Refactoring of parameter garammars
* signature changed from void() to void(engine::api::Parameters&)
* performance increase due to use "static const GrammarT" and avoid
  construction and destruction of grammars during parsing
* removed code duplication in inherited grammars
* rule unlimited changed to qi::lit
* added rule size_t_
* parser accepts "&geometries=" and "&overview=" and fails at "foo"
  instead of "&geometries=foo" and &overview=foo
* added expectations checks for derived grammars
* changed rules qi::list(".") to character rules '.'
2016-04-23 21:15:21 +02:00
Patrick Niklaus 82372bb2ab Remove develop branch from appveyor 2016-04-23 17:55:18 +02:00
Patrick Niklaus b0c67c9019 Update coverall badge 2016-04-23 14:19:58 +02:00
Patrick Niklaus d83a34f72b Remove develop branch from travis 2016-04-22 14:51:38 +02:00
Patrick Niklaus a16f156203 Update README to remove develop branch 2016-04-22 14:49:27 +02:00
Patrick Niklaus 807aa71a7c Merge branch 'develop' 2016-04-22 14:35:32 +02:00
Patrick Niklaus 14d9b67b58 Update changelog with regard to 4.9.1 2016-04-22 14:28:45 +02:00
Patrick Niklaus 82df0ca766 Fix parser tests and destinations=all / sources=all 2016-04-22 11:01:15 +02:00
bergwerkgis a6c7529a4e AppVeyor: new path to test executables, add server-tests.exe 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann 202bb6d3e2 Fix accidental rebase issues 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann bc514926bf Unit test for trip across component boundaries.
Daniel's mental model, with updates from Patrick and staring at the code
(plugins/trip.cpp): Trip first snaps coordinates which in the case of
phantoms that are not only in small components with the same id
switches small components to big ones. Therefore we get either only
small or only big components. Only then the Tarjan SCC decomposes this.

Result: multiple subtrips only happen for islands or continents.
2016-04-22 10:40:03 +02:00
Daniel J. Hofmann 9fc16b6a83 Unit test for trip exclusively in big component 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann 2125e0175d Unit tests for special symbols in radiuses, sources, destination 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann 6b5982d389 Table unit test, revealing position_index -> waypoint_index mismatch 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann a4a8aa63d4 Invalid route requests 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann bedf451952 Namespace aliases 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann 93b8f1993c Split off parameters I/O from unit tests 2016-04-22 10:40:03 +02:00
Daniel J. Hofmann c693f4806b Unit tests for routing / snapping across components 2016-04-22 10:40:03 +02:00
Patrick Niklaus b07275694a Add more guidance tests 2016-04-21 23:07:29 +02:00
Patrick Niklaus 82177c101b Add changelog entry for summary 2016-04-21 22:47:05 +02:00
Patrick Niklaus da6dbd2159 Revert "Removes summary from legs property"
This adds the summary back to the RouteLeg, it now depends on if
`steps=true`.
This reverts commit eaf9993dd9.
2016-04-21 22:39:16 +02:00
Patrick Niklaus b3957d87b4 Add changelog entry 2016-04-21 22:14:01 +02:00
Patrick Niklaus 5f9ccadd6c If geometry is only one point, encode as Point not as LineString 2016-04-20 20:49:54 +02:00
karenzshea 6e04da9f8f remove movable bridge refs in bike profile 2016-04-19 14:24:16 -04:00
karenzshea 58c13d2c07 remove movable bridge travel mode references 2016-04-19 12:59:33 -04:00
karenzshea bca8593eef remove movable bridge mode from car profile 2016-04-19 10:21:46 -04:00
Patrick Niklaus 3e2e10a4c3 Add unit test for tile plugin 2016-04-15 14:48:21 +02:00
Patrick Niklaus 6979763292 Refactor the vector tile constants 2016-04-15 14:48:21 +02:00
karenzshea 324f1739e4 more table tests, break waypoint obj check into header file 2016-04-15 14:46:17 +02:00
karenzshea 1489662f57 start tests for table plugin 2016-04-15 14:46:17 +02:00
Daniel Patterson 1c1f407f67 Fix formatting. 2016-04-14 14:39:20 -07:00
Daniel Patterson 8fb631417b Abort processing if there are no snappable edges remaining. 2016-04-14 13:07:23 -07:00
Moritz Kobitzsch ae45ad1ad2 fix r-tree abort location 2016-04-14 11:40:36 +02:00
Patrick Niklaus 6b89803534 Forgot to commit a test 2016-04-13 11:24:14 +02:00
Patrick Niklaus f6116db957 Merge pull request #1902 from Project-OSRM/4.9.1
Bug fix release 4.9.1
2016-01-19 19:00:11 -05:00
Patrick Niklaus c824429458 Include the travel mode in the last instruction by copying it from the previous instruction. 2016-01-19 23:23:32 +01:00
Daniel Patterson 23b2154d98 Adds a shared/exclusive lock around queries and CheckAndReloadFacade.
Without this, it's possible for CheckAndReloadFacade to start working
while a query is still in progress, leading to undefined behaviour.
2016-01-19 21:26:30 +01:00
Daniel J. Hofmann 25c8711aad Fix shared memory non-copyable properties 2016-01-19 20:31:14 +01:00
Daniel Patterson cf30628d4e DataFacade should only remove shared segments if they're actually different from the last time they were checked. 2016-01-19 20:31:03 +01:00
Patrick Niklaus 7675c730b6 Fix wrong assertion and emplace_back bug in trip plugin 2016-01-19 17:38:02 +01:00
Patrick Niklaus 2ce74c05e1 Use a sane gps_precision multipler 2016-01-15 22:15:05 +01:00
Patrick Niklaus 88e6558da3 Fix handling unexpected errors. 2016-01-15 22:08:04 +01:00
Patrick Niklaus f1140ec903 Fix uturns at dead-end streets 2016-01-15 21:48:14 +01:00
Patrick Niklaus a2e114e852 Merge branch 'develop' 2015-12-24 11:22:16 +01:00
Patrick Niklaus 8f6fc0146b Merge branch 'develop' 2015-09-20 13:30:19 +02:00
Patrick Niklaus 6ad1cd3fb5 Merge branch 'develop' 2015-09-16 18:18:54 +02:00
Wilhelm Berg 40443d1e25 appveyor.yml update url to binary deps 2015-08-24 21:23:12 +02:00
Patrick Niklaus 4ec323c5cc Merge commit '9958937fd1c1f9dd60126a56e1c4f25ceefaf70e' 2015-08-15 00:11:31 +02:00
Patrick Niklaus 300d901618 Merge branch 'develop' 2015-06-22 13:06:50 +02:00
Patrick Niklaus fd6daa580a Merge branch 'develop' 2015-04-22 10:34:56 +02:00
Patrick Niklaus c2fc47df34 Merge branch 'develop' 2015-04-17 22:51:40 +02:00
228 changed files with 9099 additions and 4668 deletions
+1
View File
@@ -80,6 +80,7 @@ stxxl.errlog
/test/profile.lua
/test/cache
/test/speeds.csv
/test/penalties.csv
/test/data/monaco.*
node_modules
+83 -70
View File
@@ -1,7 +1,7 @@
#language: cpp
# This makes travis use the thin image which boots faster
language: generic
language: cpp
git:
depth: 10
# sudo:required is needed for trusty images
sudo: required
@@ -13,101 +13,109 @@ notifications:
branches:
only:
- master
- develop
cache:
ccache: true
apt: true
env:
global:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- JOBS=4
matrix:
fast_finish: true
# We override the compiler names here to yield better ccache behavior, which uses this as key
include:
# Debug Builds
- os: linux
compiler: gcc
compiler: "gcc-5-debug"
addons: &gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'pip']
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Debug' COVERAGE=ON
- os: linux
compiler: gcc
compiler: "gcc-4.8-debug"
addons: &gcc48
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-4.8' CXXCOMPILER='g++-4.8' BUILD_TYPE='Debug'
- os: linux
compiler: clang
compiler: "clang-3.8-debug"
addons: &clang38
apt:
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Debug' RUN_CLANG_FORMAT=ON
- os: osx
osx_image: xcode7.3
compiler: clang
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Debug'
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Debug' JOBS=1 CUCUMBER_TIMEOUT=60000
# Release Builds
- os: linux
compiler: gcc
compiler: "gcc-5-release"
addons: &gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
- os: linux
compiler: gcc
addons: &gcc48
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-4.8' CXXCOMPILER='g++-4.8' BUILD_TYPE='Release'
# Disabled because of CI slowness
#- os: linux
#- compiler: gcc
#- addons: &gcc48
#- apt:
#- sources: ['ubuntu-toolchain-r-test']
#- packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
#- env: CCOMPILER='gcc-4.8' CXXCOMPILER='g++-4.8' BUILD_TYPE='Release'
- os: linux
compiler: clang
addons: &clang38
apt:
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release'
# Disabled because of CI slowness
#- os: linux
#- compiler: clang
#- addons: &clang38
#- apt:
#- sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
#- packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release'
- os: osx
osx_image: xcode7.3
compiler: clang
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Release'
# Disabled because of CI slowness
#- os: osx
#- osx_image: xcode7.3
#- compiler: clang
#- env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Release'
# Shared Library
- os: linux
compiler: gcc
compiler: "gcc-5-release-shared"
addons: &gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
- os: linux
compiler: clang
addons: &clang38
apt:
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Disabled because CI slowness
#- os: linux
#- compiler: clang
#- addons: &clang38
#- apt:
#- sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
#- packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
before_install:
- source ./scripts/install_node.sh 4
install:
- npm install
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
- |
if [[ -n "${COVERAGE}" ]]; then
pip install --user cpp-coveralls
fi
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.1-Linux-x86_64.tar.gz"
@@ -115,10 +123,10 @@ install:
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
# implicit deps, but seem to be installed by default with recent images: libxml2 GDAL boost
brew install cmake libzip libstxxl lua51 luabind tbb md5sha1sum
brew install cmake libzip libstxxl lua51 luabind tbb md5sha1sum ccache
fi
before_script:
install:
- cd ${TRAVIS_BUILD_DIR}
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
@@ -126,41 +134,46 @@ before_script:
fi
- mkdir build && pushd build
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- export OSRM_PORT=5000 OSRM_TIMEOUT=6000
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DCOVERAGE=${COVERAGE:-OFF} -DBUILD_TOOLS=1 -DENABLE_CCACHE=0
script:
- make --jobs=2
- make tests --jobs=2
- make benchmarks
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DCOVERAGE=${COVERAGE:-OFF} -DBUILD_TOOLS=1 -DENABLE_CCACHE=ON
- echo "travis_fold:start:MAKE"
- make osrm-extract --jobs=3
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
- make benchmarks --jobs=${JOBS}
- echo "travis_fold:end:MAKE"
- ccache -s
- sudo make install
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
sudo ldconfig
fi
- echo "travis_fold:start:UNIT_TESTS"
- popd
- mkdir example/build && pushd example/build
- cmake ..
- make
- popd
script:
- echo "travis_fold:start:BENCHMARK"
- make -C test/data benchmark
- echo "travis_fold:end:BENCHMARK"
- ./example/build/osrm-example test/data/monaco.osrm
# All tests assume to be run from the build directory
- pushd build
- ./unit_tests/library-tests ../test/data/monaco.osrm
- ./unit_tests/extractor-tests
- ./unit_tests/engine-tests
- ./unit_tests/util-tests
- ./unit_tests/server-tests
- echo "travis_fold:end:UNIT_TESTS"
- popd
- echo "travis_fold:start:CUCUMBER"
- npm test
- echo "travis_fold:end:CUCUMBER"
- echo "travis_fold:start:BENCHMARK"
- make -C test/data benchmark
- echo "travis_fold:end:BENCHMARK"
- ./build/unit_tests/library-tests test/data/monaco.osrm
- mkdir example/build && pushd example/build
- cmake ..
- make
- ./osrm-example ../../test/data/monaco.osrm
- popd
after_success:
- |
if [ -n "$RUN_CLANG_FORMAT" ]; then
if [ -n "${RUN_CLANG_FORMAT}" ]; then
./scripts/format.sh || true # we don't want to fail just yet
fi
- coveralls --build-root build --exclude unit_tests --exclude third_party --exclude node_modules --gcov-options '\-lp'
- |
if [ -n "${COVERAGE}" ]; then
bash <(curl -s https://codecov.io/bash)
fi
+103
View File
@@ -1,3 +1,106 @@
# 5.2.0 RC1
Changes from 5.1.0
- API:
- new parameter `annotate` for `route` and `match` requests. Returns additional data about each
coordinate along the selected/matched route line.
- Introducing Intersections for Route Steps. This changes the API format in multiple ways.
- `bearing_before`/`bearing_after` of `StepManeuver` are now deprecated and will be removed in the next major release
- `location` of `StepManeuvers` is now deprecated and will be removed in the next major release
- every `RouteStep` now has property `intersections` containing a list of `Intersection` objects.
- Profile changes:
- duration parser now accepts P[n]DT[n]H[n]M[n]S, P[n]W, PTHHMMSS and PTHH:MM:SS ISO8601 formats.
- Infrastructure:
- Better support for osrm-routed binary upgrade on the fly [UNIX specific]:
- Open sockets with SO_REUSEPORT to allow multiple osrm-routed processes serving requests from the same port.
- Add SIGNAL_PARENT_WHEN_READY environment variable to enable osrm-routed signal its parent with USR1 when it's running and waiting for requests.
- BREAKING: Intersection Classification adds a new file to the mix (osrm.icd). This breaks the fileformat for older versions.
- Disable http access logging via DISABLE_ACCESS_LOGGING environment
variable.
- Guidance:
- improved detection of turning streets, not reporting new-name in wrong situations
# 5.1.0
Changes with regard to 5.0.0
- API:
- added StepManeuver type `roundabout turn`. The type indicates a small roundabout that is treated as an intersection
(turn right at the roundabout for first exit, go straight at the roundabout...)
- added StepManeuver type `on ramp` and `off ramp` to distinguish between ramps that enter and exit a highway.
- reduced new name instructions for trivial changes
- combined multiple turns into a single instruction at segregated roads`
- Profile Changes:
- introduced a suffix_list / get_name_suffix_list to specify name suffices to be suppressed in name change announcements
- street names are now consistently assembled for the car, bike and walk profile as: "Name (Ref)" as in "Berlin (A5)"
- new `car.lua` dependency `lib/destination.lua`
- register a way's .nodes() function for use in the profile's way_function.
- Infrastructure
- BREAKING: reordered internal instruction types. This breaks the **data format**
- BREAKING: Changed the on-disk encoding of the StaticRTree for better performance. This breaks the **data format**
- Fixes:
- Issue #2310: post-processing for local paths, fixes #2310
- Issue #2309: local path looping, fixes #2309
- Issue #2356: Make hint values optional
- Issue #2349: Segmentation fault in some requests
- Issue #2335: map matching was using shortest path with uturns disabled
- Issue #2193: Fix syntax error position indicators in parameters queries
- Fix search with u-turn
- PhantomNode packing in MSVC now the same on other platforms
- Summary is now not malformed when including unnamed roads
- Emit new-name on when changing fron unanmed road to named road
# 5.0.0
Changes with regard 5.0.0 RC2:
- API:
- if `geometry=geojson` is passed the resulting geometry can be a LineString or Point
depending on how many coordinates are present.
- the removal of the summary field was revered. for `steps=flase` the field will always be an empty string.
Changes with regard to 4.9.1:
- API:
- BREAKING: Complete rewrite of the HTTP and library API. See detailed documentation in the wiki.
- BREAKING: The default coordinate order is now `longitude, latidue`. Exception: Polyline geometry
which follow the original Google specification of `latitdue, longitude`.
- BREAKING: Polyline geometries now use precision 5, instead of previously 6
- BREAKING: Removed GPX support
- New service `tile` which serves debug vector tiles of the road network
- Completely new engine for guidance generation:
- Support for highway ramps
- Support for different intersection types (end of street, forks, merges)
- Instruction post-processing to merge unimportant instructions
- Improved handling of roundabouts
- Tools:
- BREAKING: Renamed osrm-prepare to osrm-contract
- BREAKING: Removes profiles from osrm-contract, only needed in osrm-extract.
- Abort processing in osrm-extract if there are no snappable edges remaining.
- Added .properties file to osrm-extract ouput.
- Enables the use of multiple segment-speed-files on the osrm-contract command line
- Profile changes:
- Remove movable bridge mode
- Add `maxspeed=none` tag to car profile.
- A `side_road` tag support for the OSRM car profile.
- Fixes:
- Issue #2150: Prevents routing over delivery ways and nodes
- Issue #1972: Provide uninstall target
- Issue #2072: Disable alternatives by default and if core factor < 1.0
- Issue #1999: Fix unpacking for self-loop nodes not in core.
- Infrastructure:
- Cucumber test suit is now based on cucumber-js, removes Ruby as dependency
- Updated to mapbox/variant v1.1
- Updated to libosmium v2.6.1
- Remove GeoJSON based debugging output, replaced by debug tiles
# 5.0.0 RC2
- Profiles:
- `properties.allow_uturns_at_via` -> `properties.continue_straight_at_waypoint` (value is inverted!)
+7 -6
View File
@@ -8,7 +8,7 @@ endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 0)
set(OSRM_VERSION_MINOR 2)
set(OSRM_VERSION_PATCH 0)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@@ -25,14 +25,14 @@ else()
message(WARNING "Building on a 32 bit system is unsupported")
endif()
if(WIN32 AND MSVC_VERSION LESS 1800)
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
if(WIN32 AND MSVC_VERSION LESS 1900)
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
endif()
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF)
option(BUILD_TOOLS "Build OSRM tools" OFF)
option(BUILD_COMPONENTS "Build osrm-components" ON)
option(BUILD_COMPONENTS "Build osrm-components" OFF)
option(ENABLE_ASSERTIONS OFF)
option(COVERAGE OFF)
option(SANITIZER OFF)
@@ -54,7 +54,7 @@ configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/util/version.hpp.in
${CMAKE_CURRENT_BINARY_DIR}/include/util/version.hpp
)
file(GLOB UtilGlob src/util/*.cpp)
file(GLOB UtilGlob src/util/*.cpp src/util/*/*.cpp)
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
file(GLOB ContractorGlob src/contractor/*.cpp)
file(GLOB StorageGlob src/storage/*.cpp)
@@ -140,6 +140,7 @@ if (COVERAGE)
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
message(ERROR "COVERAGE=ON only make sense with a Debug build")
endif()
message(INFO "Enabling coverage")
set(MAYBE_COVERAGE_LIBRARIES "gcov")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
endif()
@@ -232,7 +233,7 @@ include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
find_package(Boost 1.49.0 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
if(NOT WIN32)
if(NOT WIN32 AND NOT Boost_USE_STATIC_LIBS)
add_definitions(-DBOOST_TEST_DYN_LINK)
endif()
add_definitions(-DBOOST_SPIRIT_USE_PHOENIX_V3)
+45 -8
View File
@@ -4,13 +4,11 @@ The Open Source Routing Machine is a high performance routing engine written in
## Current build status
| build config | branch | status |
|:-------------|:--------|:------------|
| Linux | master | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=master)](https://travis-ci.org/Project-OSRM/osrm-backend) |
| Linux | develop | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=develop)](https://travis-ci.org/Project-OSRM/osrm-backend) |
| Windows | master/develop | [![Build status](https://ci.appveyor.com/api/projects/status/4iuo3s9gxprmcjjh)](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
| LUAbind fork | master | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
| Coverage | develop | [![Coverage Status](https://coveralls.io/repos/github/Project-OSRM/osrm-backend/badge.svg?branch=develop)](https://coveralls.io/github/Project-OSRM/osrm-backend?branch=develop) |
| build config | status |
|:-------------|:-------|
| Linux | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=master)](https://travis-ci.org/Project-OSRM/osrm-backend) |
| Windows | [![Build status](https://ci.appveyor.com/api/projects/status/4iuo3s9gxprmcjjh)](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
| Coverage | [![codecov](https://codecov.io/gh/Project-OSRM/osrm-backend/branch/master/graph/badge.svg)](https://codecov.io/gh/Project-OSRM/osrm-backend) |
## Building
@@ -20,7 +18,46 @@ To quickly try OSRM use our [free and daily updated online service](http://map.p
## Documentation
See the Wiki's [server API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Server-api) as well as the [library API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Library-api)
### Full documentation
- [osrm-routed HTTP API documentation](docs/http.md)
- [libosrm API documentation](docs/libosrm.md)
### Quick start
Building OSRM assuming all dependencies are installed:
```
mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
sudo cmake --build . --target install
```
Loading preparing a dataset and starting the server:
```
osrm-extract data.osm.pbf -p profiles/car.lua
osrm-contract data.osrm
osrm-routed data.osrm
```
Running a query on your local server:
```
curl http://127.0.0.1:5000/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
```
### Running a request against the Demo Server
First read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy).
Then run simple query with instructions and alternatives on Berlin:
```
curl https://router.project-osrm.org/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
```
## References in publications
+9 -6
View File
@@ -116,17 +116,20 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
ECHO running engine-tests.exe ...
%Configuration%\unit_tests\engine-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO running extractor-tests.exe ...
%Configuration%\unit_tests\extractor-tests.exe
unit_tests\%Configuration%\extractor-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO running engine-tests.exe ...
unit_tests\%Configuration%\engine-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO running util-tests.exe ...
%Configuration%\unit_tests\util-tests.exe
unit_tests\%Configuration%\util-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO running server-tests.exe ...
unit_tests\%Configuration%\server-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE
ECHO ========= CREATING PACKAGES ==========
CD %PROJECT_DIR%\build\%Configuration%
-1
View File
@@ -28,7 +28,6 @@ artifacts:
branches:
only:
- master
- develop
deploy:
provider: FTP
+7
View File
@@ -0,0 +1,7 @@
coverage:
ignore:
- unit_tests/.*
- third_party/.*
comment: off
+9 -1
View File
@@ -5,15 +5,23 @@ RUN apt-get install -y build-essential git-core python-pip python-software-prope
RUN apt-get -y install gcc-4.8 g++-4.8 libboost1.55-all-dev llvm-3.4
RUN apt-get -y install libbz2-dev libstxxl-dev libstxxl1 libxml2-dev
RUN apt-get -y install libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev ruby1.9
RUN apt-get -y install libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev
RUN apt-get -y install curl cmake cmake-curses-gui
RUN pip install awscli
# luabind
RUN curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
WORKDIR /opt
RUN git clone --depth 1 --branch v0.31.0 https://github.com/creationix/nvm.git
RUN /bin/bash -c "source /opt/nvm/nvm.sh && nvm install v4"
RUN useradd -ms /bin/bash mapbox
USER mapbox
ENV HOME /home/mapbox
WORKDIR /home/mapbox
RUN echo "source /opt/nvm/nvm.sh" > .bashrc
RUN echo "source /home/mapbox/.bashrc" > .profile
+1 -1
View File
@@ -8,4 +8,4 @@ docker run \
-e "CXX=clang++" \
-v `pwd`:/home/mapbox/osrm-backend \
-t mapbox/osrm:linux \
osrm-backend/docker/test.sh
/bin/bash -lc "osrm-backend/docker/test.sh"
+1 -1
View File
@@ -8,4 +8,4 @@ docker run \
-e "CXX=g++" \
-v `pwd`:/home/mapbox/osrm-backend \
-t mapbox/osrm:linux \
osrm-backend/docker/test.sh
/bin/bash -lc "osrm-backend/docker/test.sh"
+5 -6
View File
@@ -4,11 +4,8 @@ set -e
set -o pipefail
export CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
export PATH=$PATH:/home/mapbox/.gem/ruby/1.9.1/bin:/home/mapbox/osrm-backend/vendor/bundle/ruby/1.9.1/bin
cd /home/mapbox/osrm-backend
gem install --user-install bundler
bundle install --path vendor/bundle
[ -d build ] && rm -rf build
mkdir -p build
cd build
@@ -16,7 +13,9 @@ cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
make -j`nproc`
make tests -j`nproc`
./datastructure-tests
./algorithm-tests
#./unit_tests/server-tests
#./unit_tests/library-tests
#./unit_tests/extractor-tests
#./unit_tests/util-tests
cd ..
bundle exec cucumber -p verify
npm test
+592
View File
@@ -0,0 +1,592 @@
## Environent Variables
### SIGNAL_PARENT_WHEN_READY
If the SIGNAL_PARENT_WHEN_READY environment variable is set osrm-routed will
send the USR1 signal to its parent when it will be running and waiting for
requests. This could be used to upgrade osrm-routed to a new binary on the fly
without any service downtime - no incoming requests will be lost.
### DISABLE_ACCESS_LOGGING
If the DISABLE_ACCESS_LOGGING environment variable is set osrm-routed will
**not** log any http requests to standard output. This can be useful in high
traffic setup.
## HTTP API
`osrm-routed` supports only `GET` requests of the form. If you your response size
exceeds the limits of a simple URL encoding, consider using our [NodeJS bindings](https://github.com/Project-OSRM/node-osrm)
or using the [C++ library directly](libosrm.md).
### Request
```
http://{server}/{service}/{version}/{profile}/{coordinates}[.{format}]?option=value&option=value
```
- `server`: location of the server. Example: `127.0.0.1:5000` (default)
- `service`: Name of the service to be used. Support are the following services:
| Service | Description |
|-------------|-----------------------------------------------------------|
| [`route`](#service-route) | shortest path between given coordinates |
| [`nearest`](#service-nearest) | returns the nearest street segment for a given coordinate |
| [`table`](#service-table) | computes distance tables for given coordinates |
| [`match`](#service-match) | matches given coordinates to the road network |
| [`trip`](#service-trip) | Compute the shortest round trip between given coordinates |
| [`tile`](#service-tile) | Return vector tiles containing debugging info |
- `version`: Version of the protocol implemented by the service.
- `profile`: Mode of transportation, is determined by the profile that is used to prepare the data
- `coordinates`: String of format `{longitude},{latitude};{longitude},{latitude}[;{longitude},{latitude} ...]` or `polyline({polyline})`.
- `format`: Only `json` is supportest at the moment. This parameter is optional and defaults to `json`.
Passing any `option=value` is optional. `polyline` follows Google's polyline format with precision 5 and can be generated using [this package](https://www.npmjs.com/package/polyline).
To pass parameters to each location some options support an array like encoding:
```
{option}={element};{element}[;{element} ... ]
```
The number of elements must match exactly the number of locations. If you don't want to pass a value but instead use the default you can pass an empty `element`.
Example: 2nd location use the default value for `option`:
```
{option}={element};;{element}
```
## General options
| Option | Values | Description |
|------------|--------------------------------------------------------|--------------------------------------------------|
|bearings |`{bearing};{bearing}[;{bearing} ...]` |Limits the search to segments with given bearing in degrees towards true north in clockwise direction. |
|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. |
|hints |`{hint};{hint}[;{hint} ...]` |Hint to derive position in street network. |
Where the elements follow the following format:
| Element | Values |
|------------|--------------------------------------------------------|
|bearing |`{value},{range}` `integer 0 .. 360,integer 0 .. 180` |
|radius |`double >= 0` or `unlimited` (default) |
|hint |Base64 `string` |
#### Examples
Query on Berlin with three coordinates:
```
http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false
```
Using polyline:
```
http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false
```
### Response
Every response object has a `code` field.
```json
{
"code": {code},
"message": {message}
}
```
Where `code` is on one of the strings below or service dependent:
| Type | Description |
|-------------------|----------------------------------------------------------------------------------|
| `Ok` | Request could be processed as expected. |
| `InvalidUrl` | URL string is invalid. |
| `InvalidService` | Service name is invalid. |
| `InvalidVersion` | Version is not found. |
| `InvalidOptions` | Options are invalid. |
| `NoSegment` | One of the supplied input coordinates could not snap to street segment. |
| `TooBig` | The request size violates one of the service specific request size restrictions. |
`message` is a **optional** human-readable error message. All other status types are service dependent.
In case of an error the HTTP status code will be `400`. Otherwise the HTTP status code will be `200` and `code` will be `Ok`.
## Service `nearest`
Snaps a coordinate to the street network and returns the nearest n matches.
### Request
```
http://{server}/nearest/v1/{profile}/{coordinates}.json?number={number}
```
Where `coordinates` only supports a single `{longitude},{latitude}` entry.
In addition to the [general options](#general-options) the following options are supported for this service:
|Option |Values |Description |
|------------|------------------------------|----------------------------------------------------|
|number |`integer >= 1` (default `1`) |Number of nearest segments that should be returned. |
### Response
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
- `distance`: Distance in meters to the supplied input coordinate.
### Examples
Querying nearest three snapped locations of `13.388860,52.517037` with a bearing between `20° - 340°`.
```
http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?number=3&bearings=0,20
```
## Service `route`
### Request
```
http://{server}/route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|geojson}&overview={full|simplified|false}
```
In addition to the [general options](#general-options) the following options are supported for this service:
|Option |Values |Description |
|------------|------------------------------------------|-------------------------------------------------------------------------------|
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|steps |`true`, `false` (default) |Return route steps for each route leg |
|annotate |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|continue_straight |`default` (default), `true`, `false`|Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. |
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
### Response
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `waypoints`: Array of `Waypoint` objects representing all waypoints in order:
- `routes`: An array of `Route` objects, ordered by descending recommendation rank.
In case of error the following `code`s are supported in addition to the general ones:
| Type | Description |
|-------------------|-----------------|
| `NoRoute` | No route found. |
All other fields might be undefined.
## Service `table`
### Request
```
http://{server}/table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]`
```
This computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
### Coordinates
In addition to the [general options](#general-options) the following options are supported for this service:
|Option |Values |Description |
|------------|--------------------------------------------------|---------------------------------------------|
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
to number of input locations;
Example:
```
sources=0;5;7&destinations=5;1;4;2;3;6
```
|Element |Values |
|------------|-----------------------------|
|index |`0 <= integer < #locations` |
### Response
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
the i-th waypoint to the j-th waypoint. Values are given in seconds.
- `sources` array of `Waypoint` objects describing all sources in order
- `destinations` array of `Waypoint` objects describing all destinations in order
In case of error the following `code`s are supported in addition to the general ones:
| Type | Description |
|-------------------|-----------------|
| `NoTable` | No route found. |
All other fields might be undefined.
#### Examples
Returns a `3x3` matrix:
```
http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219
```
Returns a `1x3` matrix:
```
http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0
```
Returns a asymmetric 3x2 matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
```
http://router.project-osrm.org/table/v1/driving/qikdcB}~dpXkkHz?sources=0;1;3&destinations=2;4
```
## Service `match`
Map matching matches given GPS points to the road network in the most plausible way.
Please note the request might result multiple sub-traces. Large jumps in the timestamps (>60s) or improbable transitions lead to trace splits if a complete matching could not be found.
The algorithm might not be able to match all points. Outliers are removed if they can not be matched successfully.
### Request
```
http://{server}/match/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}
```
In addition to the [general options](#general-options) the following options are supported for this service:
|Option |Values |Description |
|------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|steps |`true`, `false` (default) |Return route steps for each route |
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|annotate |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamp of the input location. |
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|Parameter |Values |
|------------|------------------------------|
|timestamp |`integer` UNIX-like timestamp |
|radius |`double >= 0` (default 5m) |
### Response
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `tracepoints`: Array of `Ẁaypoint` objects representing all points of the trace in order.
If the trace point was ommited by map matching because it is an outlier, the entry will be `null`.
Each `Waypoint` object has the following additional properties:
- `matchings_index`: Index to the `Route` object in `matchings` the sub-trace was matched to.
- `waypoint_index`: Index of the waypoint inside the matched route.
- `matchings`: An array of `Route` objects that assemble the trace. Each `Route` object has the following additional properties:
- `confidence`: Confidence of the matching. `float` value between 0 and 1. 1 is very confident that the matching is correct.
In case of error the following `code`s are supported in addition to the general ones:
| Type | Description |
|-------------------|---------------------|
| `NoMatch` | No matchings found. |
All other fields might be undefined.
## Service `trip`
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm).
The returned path does not have to be the shortest path, as TSP is NP-hard it is only an approximation.
Note that if the input coordinates can not be joined by a single trip (e.g. the coordinates are on several disconnected islands)
multiple trips for each connected component are returned.
### Request
```
http://{server}/trip/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}
```
In addition to the [general options](#general-options) the following options are supported for this service:
|Option |Values |Description |
|------------|------------------------------------------------|---------------------------------------------------------------------------|
|steps |`true`, `false` (default) |Return route instructions for each trip |
|annotate |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
### Response
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `waypoints`: Array of `Waypoint` objects representing all waypoints in input order. Each `Waypoint` object has the following additional properties:
- `trips_index`: Index to `trips` of the sub-trip the point was matched to.
- `waypoint_index`: Index of the point in the trip.
- `trips`: An array of `Route` objects that assemble the trace.
In case of error the following `code`s are supported in addition to the general ones:
| Type | Description |
|-------------------|---------------------|
| `NoTrips` | No trips found. |
All other fields might be undefined.
## Result objects
### Route
Represents a route through (potentially multiple) waypoints.
#### Properties
- `distance`: The distance traveled by the route, in `float` meters.
- `duration`: The estimated travel time, in `float` number of seconds.
- `geometry`: The whole geometry of the route value depending on `overview` parameter, format depending on the `geometries` parameter. See `RouteStep`'s `geometry` field for a parameter documentation.
| overview | Description |
|------------|-----------------------------|
| simplified | Geometry is simplified according to the highest zoom level it can still be displayed on full. |
| full | Geometry is not simplified. |
| false | Geometry is not added. |
- `legs`: The legs between the given waypoints, an array of `RouteLeg` objects.
#### Example
Three input coordinates, `geometry=geojson`, `steps=false`:
```json
{
"distance": 90.0,
"duration": 300.0,
"geometry": {"type": "LineString", "coordinates": [[120., 10.], [120.1, 10.], [120.2, 10.], [120.3, 10.]]},
"legs": [
{
"distance": 30.0,
"duration": 100.0,
"steps": []
},
{
"distance": 60.0,
"duration": 200.0,
"steps": []
}
]
}
```
### RouteLeg
Represents a route between two waypoints.
#### Properties
- `distance`: The distance traveled by this route leg, in `float` meters.
- `duration`: The estimated travel time, in `float` number of seconds.
- `summary`: Summary of the route taken as `string`. Depends on the `steps` parameter:
| steps | |
|--------------|-----------------------------------------------------------------------|
| true | Names of the two major roads used. Can be empty if route is too short.|
| false | empty `string` |
- `steps`: Depends on the `steps` parameter.
| steps | |
|--------------|-----------------------------------------------------------------------|
| true | array of `RouteStep` objects describing the turn-by-turn instructions |
| false | empty array |
- `annotation`: Additional details about each coordinate along the route geometry:
| annotate | |
|--------------|-----------------------------------------------------------------------|
| true | returns distance and durations of each coordinate along the route |
| false | will not exist |
#### Example
With `steps=false` and `annotate=true`:
```json
{
"distance": 30.0,
"duration": 100.0,
"steps": []
"annotation": {
"distance": [5,5,10,5,5],
"duration": [15,15,40,15,15]
}
}
```
### RouteStep
A step consists of a maneuver such as a turn or merge, followed
by a distance of travel along a single way to the subsequent
step.
#### Properties
- `distance`: The distance of travel from the maneuver to the subsequent step, in `float` meters.
- `duration`: The estimated travel time, in `float` number of seconds.
- `geometry`: The unsimplified geometry of the route segment, depending on the `geometries` parameter.
| geometries | |
|------------|--------------------------------------------------------------------|
| polyline | [polyline](https://www.npmjs.com/package/polyline) with precision 5 in [latitude,longitude] encoding |
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
- `name`: The name of the way along which travel proceeds.
- `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver.
- `intersections`: A list of `Intersections` that are passed along the segment, the very first belonging to the StepManeuver
#### Example
```
{
"distance":152.3,
"duration":15.6,
"name":"Lortzingstraße",
"maneuver":{
"type":"depart",
"modifier":"left"
},
"geometry":"{lu_IypwpAVrAvAdI",
"mode":"driving",
"intersections":[
{"location":[13.39677,52.54366],
"out":1,
"bearings":[66,246],
"entry":["true","true"]},
{"location":[13.394718,52.543096],
"in":0,
"out":2,
"bearings":[60,150,240,330],
"entry":["false","true","true","true"]
}
]}
```
### StepManeuver
#### Properties
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
- `bearing_before`: The clockwise angle from true north to the
direction of travel immediately before the maneuver.
- `bearing_after`: The clockwise angle from true north to the
direction of travel immediately after the maneuver.
- `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change**
Types unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed.
| `type` | Description |
|-------------------|--------------------------------------------------------------|
| turn | a basic turn into direction of the `modifier` |
| new name | no turn is taken, but the road name changes. The Road can take a turn itself, following `modifier` |
| depart | indicates the departure of the leg |
| arrive | indicates the destination of the leg |
| merge | merge onto a street (e.g. getting on the highway from a ramp, the `modifier specifies the direction of the merge`) |
| ramp | **Deprecated**. Replaced by `on_ramp` and `off_ramp`. |
| on ramp | take a ramp to enter a highway (direction given my `modifier`) |
| off ramp | take a ramp to exit a highway (direction given my `modifier`) |
| fork | take the left/right side at a fork depending on `modifier` |
| end of road | road ends in a T intersection turn in direction of `modifier`|
| continue | Turn in direction of `modifier` to stay on the same road |
| roundabout | traverse roundabout, has additional field `exit` with NR if the roundabout is left. `the modifier specifies the direction of entering the roundabout` |
| rotary | a larger version of a roundabout, can offer `rotary_name` in addition to the `exit` parameter. |
| roundabout turn | Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
| notification | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
between all instructions. They only offer a fallback in case nothing else is to report.
- `modifier` An optional `string` indicating the direction change of the maneuver.
| `modifier` | Description |
|-------------------|-------------------------------------------|
| uturn | indicates reversal of direction |
| sharp right | a sharp right turn |
| right | a normal turn to the right |
| slight right | a slight turn to the right |
| straight | no relevant change in direction |
| slight left | a slight turn to the left |
| left | a normal turn to the left |
| sharp left | a sharp turn to the left |
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
The meaning depends on the `type` field.
| `type` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `turn` | `modifier` indicates the change in direction accomplished through the turn |
| `depart`/`arrive` | `modifier` indicates the position of departure point and arrival point in relation to the current direction of travel |
- `exit` An optional `integer` indicating number of the exit to take. The field exists for the following `type` field:
| `type` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `roundabout` | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout. |
| else | Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` |
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
### Intersections
An intersection gives a full representation of any cross-way the path passes bay. For every step, the very first intersection (`intersections[0]`) corresponds to the
location of the StepManeuver. Further intersections are listed for every cross-way until the next turn instruction.
#### Properties
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
- `bearings`: A list of bearing values (e.g. [0,90,180,270]) that are available at the intersection. The bearings describe all available roads at the intersection.
- `entry`: A list of entry flags, corresponding in a 1:1 relationship to the bearings. A value of `true` indicates that the respective road could be entered on a valid route.
`false` indicates that the turn onto the respective road would violate a restriction.
- `in`: index into bearings/entry array. Used to calculate the bearing just before the turn. Namely, the clockwise angle from true north to the
direction of travel immediately before the maneuver/passing the intersection. Bearings are given relative to the intersection. To get the bearing
in the direction of driving, the bearing has to be rotated by a value of 180. The value is not supplied for `depart` maneuvers.
- `out`: index into the bearings/entry array. Used to extract the bearing just after the turn. Namely, The clockwise angle from true north to the
direction of travel immediately after the maneuver/passing the intersection. The value is not supplied for `arrive` maneuvers.
#### Example
```
{
"location":[13.394718,52.543096],
"in":0,
"out":2,
"bearings":[60,150,240,330],
"entry":["false","true","true","true"]
}
```
### Waypoint
Object used to describe waypoint on a route.
#### Properties
- `name` Name of the street the coordinate snapped to
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
- `hint` Unique internal identifier of the segment (ephemeral, not constant over data updates)
This can be used on subsequent request to significantly speed up the query and to connect multiple services.
E.g. you can use the `hint` value obtained by the `nearest` query as `hint` values for `route` inputs.
## Service `tile`
This generates [Mapbox Vector Tiles](https://www.mapbox.com/developers/vector-tiles/) that can be viewed with a vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can be used to examine the routing graph. The tiles are generated directly from the data in-memory, so are in sync with actual routing results, and let you examine which roads are actually routable, and what weights they have applied.
### Request
```
http://{server}/tile/v1/{profile}/tile({x},{y},{zoom}).mvt
```
The `x`, `y`, and `zoom` values are the same as described at https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames, and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
### Response
The response object is either a binary encoded blob with a `Content-Type` of `application/x-protobuf`, or a `404` error. Note that OSRM is hard-coded to only return tiles from zoom level 12 and higher (to avoid accidentally returning extremely large vector tiles).
Vector tiles contain just a single layer named `speeds`. Within that layer, features can have `speed` (int) and `is_small` (boolean) attributes.
+26
View File
@@ -0,0 +1,26 @@
OSRM can be used as a library (libosrm) via C++ instead of using it through the HTTP interface and `osrm-routed`. This allows for fine-tuning OSRM and has much less overhead. Here is a quick introduction into how to use `libosrm` in the upcoming v5 release.
Take a look at the example code that lives in the [example directory](https://github.com/Project-OSRM/osrm-backend/tree/master/example). Here is all you ever wanted to know about `libosrm`, that is a short description of what the types do and where to find documentation on it:
- [`EngineConfig`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/engine_config.hpp) - for initializing an OSRM instance we can configure certain properties and constraints. E.g. the storage config is the base path such as `france.osm.osrm` from which we derive and load `france.osm.osrm.*` auxiliary files. This also lets you set constraints such as the maximum number of locations allowed for specific services.
- [`OSRM`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/osrm/osrm.hpp) - this is the main Routing Machine type with functions such as `Route` and `Table`. You initialize it with a `EngineConfig`. It does all the heavy lifting for you. Each function takes its own parameters, e.g. the `Route` function takes `RouteParameters`, and a out-reference to a JSON result that gets filled. The return value is a `Status`, indicating error or success.
- [`Status`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/status.hpp) - this is a type wrapping `Error` or `Ok` for indicating error or success, respectively.
- [`TableParameters`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/table_parameters.hpp) - this is an example of parameter types the Routing Machine functions expect. In this case `Table` expects its own parameters as `TableParameters`. You can see it wrapping two vectors, sources and destinations --- these are indices into your coordinates for the table service to construct a matrix from (empty sources or destinations means: use all of them). If you ask yourself where coordinates come from, you can see `TableParameters` inheriting from `BaseParameters`.
- [`BaseParameter`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/base_parameters.hpp) - this most importantly holds coordinates (and a few other optional properties that you don't need for basic usage); the specific parameter types inherit from `BaseParameters` to get these member attributes. That means your `TableParameters` type has `coordinates`, `sources` and `destination` member attributes (and a few other that we ignore for now).
- [`Coordinate`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/coordinate.hpp) - this is a wrapper around a (longitude, latitude) pair. We really don't care about (lon,lat) vs (lat, lon) but we don't want you to accidentally mix them up, so both latitude and longitude are strictly typed wrappers around integers (fixed notation such as `13423240`) and floating points (floating notation such as `13.42324`).
- [Parameters for other services](https://github.com/Project-OSRM/osrm-backend/tree/master/include/engine/api) - here are all other `*Parameters` you need for other Routing Machine services.
- [JSON](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/json_container.hpp) - this is a sum type resembling JSON. The Routing Machine service functions take a out-ref to a JSON result and fill it accordingly. It is currently implemented using [mapbox/variant](https://github.com/mapbox/variant) which is similar to [Boost.Variant](http://www.boost.org/doc/libs/1_55_0/doc/html/variant.html) (Boost documentation is great). There are two ways to work with this sum type: either provide a visitor that acts on each type on visitation or use the `get` function in case you're sure about the structure. The JSON structure is written down in the [[v5 server API|Server-API-v5,-current]].
------------------------------------------------------------------------------------------------------------------
To summarize:
- create an `OSRM` instance initialized with a `EngineConfig`
- call the service function on the `OSRM` object providing service specific `*Parameters`
- check the return code and use the JSON result
+34
View File
@@ -0,0 +1,34 @@
OSRM supports "profiles". Configurations representing different routing behaviours for (typically) different transport modes. A profile describes whether or not we route along a particular type of way, or over a particular node in the OpenStreetMap data, and also how quickly we'll be travelling when we do. This feeds into the way the routing graph is created and thus influences the output routes.
## Available profiles
Out-of-the-box OSRM comes with several different profiles, including car, bicycle and foot.
Profile configuration files have a 'lua' extension, and are found under the 'profiles' subdirectory.
Alternatively commands will take a lua profile specified with an explicit -p param, for example:
`osrm-extract -p ../profiles/car.lua planet-latest.osm.pbf`
And then **you will need to extract and contract again** (A change to the profile will typically affect the extract step as well as the contract step. See [Processing Flow](https://github.com/Project-OSRM/osrm-backend/wiki/Processing-Flow))
## lua scripts?
Profiles are not just configuration files. They are scripts written in the "lua" scripting language ( http://www.lua.org ) The reason for this, is that OpenStreetMap data is not sufficiently straightforward, to simply define tag mappings. Lua scripting offers a powerful way of coping with the complexity of different node,way,relation,tag combinations found within OpenStreetMap data.
## Basic structure of a profile
You can understand these lua scripts enough to make interesting modifications, without needing to get to grips with how they work completely.
Towards the top of the file, a profile (such as [car.lua](../profiles/car.lua)) will typically define various configurations as global variables. A lot of these are look-up hashes of one sort or another.
As you scroll down the file you'll see local variables, and then local functions, and finally...
`way_function` and `node_function` are the important functions which are called when extracting OpenStreetMap data with `osrm-extract`.
## way_function
Given an OpenStreetMap way, the way_function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
All other calculations stem from that, including the returned timings in driving directions, but also, less directly, it feeds into the actual routing decisions the engine will take (a way with a slow traversal speed, may be less favoured than a way with fast traversal speed, but it depends how long it is, and... what it connects to in the rest of the network graph)
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the way_function. Instead a way_function will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
+50
View File
@@ -0,0 +1,50 @@
# Releasing a new OSRM version
Do decide if this is a major or minor version bump use: http://semver.org/
What we guarantee on major version changes:
- Breaking changes will be in the changelog
- If we break an HTTP API we bump the version
What we guarantee on minor version changes:
- HTTP API does not include breaking changes
- C++ library API does not include breaking changes
- node-osrm API does not include breaking changes
What we DO NOT guarantee on minor version changes:
- file format comp ability. Breakage will be listed in the changelog.
- new turn types and fields may be introduced. How to handle this see [the HTTP API docs](http.md).
What we guarantee on patch version changes:
- HTTP API does not include breaking changes
- C++ library API does not include breaking changes
- node-osrm API does not include breaking changes
- full file format compatibility
## Major or Minor release x.y
1. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
2. Make sure `CHANGELOG.md` is up to date.
3. Make sure the OSRM version in `CMakeLists.txt` is up to date
4. Use an annotated tag to mark the release: `git tag vx.y.0 -a` Body of the tag description should be the changelog entries.
5. Push tags and commits: `git push; git push --tags`
6. Branch of the `vx.y.0` tag to create a release branch `x.y`:
`git branch x.y. vx.y.0; git push -u x.y:origin/x.y`
7. Modify `.travis.yml` to allow builds for the `x.y` branch.
8. Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
## Patch release x.y.z
1. Check out the appropriate release branch x.y
2. Make sure all fixes are listed in the changelog and included in the branch
3. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
4. Make sure the OSRM version in `CMakeLists.txt` is up to date
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
6. Push tags and commits: `git push; git push --tags`
7. Proceede with the `node-osrm` release as outlined in the repository.
8. Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
+3 -3
View File
@@ -19,14 +19,14 @@ else()
message(WARNING "Building on a 32 bit system is unsupported")
endif()
if(WIN32 AND MSVC_VERSION LESS 1800)
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
if(WIN32 AND MSVC_VERSION LESS 1900)
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
endif()
add_executable(osrm-example example.cpp)
find_package(LibOSRM REQUIRED)
find_package(Boost 1.49.0 COMPONENTS filesystem system thread REQUIRED)
find_package(Boost 1.49.0 COMPONENTS filesystem system thread iostreams REQUIRED)
target_link_libraries(osrm-example ${LibOSRM_LIBRARIES} ${Boost_LIBRARIES})
include_directories(SYSTEM ${LibOSRM_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
+3 -3
View File
@@ -4,7 +4,7 @@ Feature: Bike - Squares and other areas
Background:
Given the profile "bicycle"
@square @mokob @2154
@square
Scenario: Bike - Route along edge of a squares
Given the node map
| x | |
@@ -50,7 +50,7 @@ Feature: Bike - Squares and other areas
| d | a | xa,xa |
| a | d | xa,xa |
@parking @mokob @2154
@parking
Scenario: Bike - parking areas
Given the node map
| e | | | f |
@@ -78,7 +78,7 @@ Feature: Bike - Squares and other areas
| a | d | abcda,abcda |
@train @platform @mokob @2154
@train @platform
Scenario: Bike - railway platforms
Given the node map
| x | a | b | y |
+13 -13
View File
@@ -1,5 +1,5 @@
@routing @bicycle @bridge
Feature: Bicycle - Handle movable bridge
Feature: Bicycle - Handle cycling
Background:
Given the profile "bicycle"
@@ -18,14 +18,14 @@ Feature: Bicycle - Handle movable bridge
When I route I should get
| from | to | route | modes |
| a | g | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling |
| b | f | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling |
| e | c | cde,cde | movable bridge,movable bridge |
| e | b | cde,abc,abc | movable bridge,cycling,cycling |
| e | a | cde,abc,abc | movable bridge,cycling,cycling |
| c | e | cde,cde | movable bridge,movable bridge |
| c | f | cde,efg,efg | movable bridge,cycling,cycling |
| c | g | cde,efg,efg | movable bridge,cycling,cycling |
| a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
| b | f | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
| e | c | cde,cde | cycling,cycling |
| e | b | cde,abc,abc | cycling,cycling,cycling |
| e | a | cde,abc,abc | cycling,cycling,cycling |
| c | e | cde,cde | cycling,cycling |
| c | f | cde,efg,efg | cycling,cycling,cycling |
| c | g | cde,efg,efg | cycling,cycling,cycling |
Scenario: Bicycle - Properly handle durations
Given the node map
@@ -41,7 +41,7 @@ Feature: Bicycle - Handle movable bridge
When I route I should get
| from | to | route | modes | speed |
| a | g | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling | 5 km/h |
| b | f | abc,cde,efg,efg | cycling,movable bridge,cycling,cycling | 4 km/h |
| c | e | cde,cde | movable bridge,movable bridge | 2 km/h |
| e | c | cde,cde | movable bridge,movable bridge | 2 km/h |
| a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 5 km/h |
| b | f | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 4 km/h |
| c | e | cde,cde | cycling,cycling | 2 km/h |
| e | c | cde,cde | cycling,cycling | 2 km/h |
+5 -5
View File
@@ -10,13 +10,13 @@ Feature: Bike - Street names in instructions
| | c |
And the ways
| nodes | name |
| ab | My Way |
| bc | Your Way |
| nodes | name | ref |
| ab | My Way | A6 |
| bc | Your Way | A7 |
When I route I should get
| from | to | route |
| a | c | My Way,Your Way,Your Way |
| from | to | route |
| a | c | My Way (A6),Your Way (A7),Your Way (A7) |
@unnamed
Scenario: Bike - Use way type to describe unnamed ways
+1 -1
View File
@@ -14,7 +14,7 @@ Feature: Bike - Way ref
When I route I should get
| from | to | route |
| a | b | Utopia Drive / E7,Utopia Drive / E7 |
| a | b | Utopia Drive (E7),Utopia Drive (E7) |
Scenario: Bike - Way with only ref
Given the node map
-3
View File
@@ -34,7 +34,6 @@ OSRM will use 4/5 of the projected free-flow speed.
| a | b | ab,ab | 47 km/h +- 1 |
| b | c | bc,bc | 47 km/h +- 1 |
@mokob @2162
Scenario: Car - Advisory speed overwrites backwards maxspeed
Given the node map
| a | b | c |
@@ -49,7 +48,6 @@ OSRM will use 4/5 of the projected free-flow speed.
| b | a | ab,ab | 47 km/h +- 1 |
| c | b | bc,bc | 47 km/h +- 1 |
@mokob @2162 @deleteme
Scenario: Car - Advisory speed overwrites backwards maxspeed
Given the node map
| a | b | c | d |
@@ -65,7 +63,6 @@ OSRM will use 4/5 of the projected free-flow speed.
| c | b | bc,bc | 47 km/h +- 1 |
| d | c | cd,cd | 47 km/h +- 1 |
@mokob @2162
Scenario: Car - Directional advisory speeds play nice with eachother
Given the node map
| a | b | c |
+13 -13
View File
@@ -1,5 +1,5 @@
@routing @car @bridge
Feature: Car - Handle movable bridge
Feature: Car - Handle driving
Background:
Given the profile "car"
@@ -18,14 +18,14 @@ Feature: Car - Handle movable bridge
When I route I should get
| from | to | route | modes |
| a | g | abc,cde,efg,efg | driving,movable bridge,driving,driving |
| b | f | abc,cde,efg,efg | driving,movable bridge,driving,driving |
| e | c | cde,cde | movable bridge,movable bridge |
| e | b | cde,abc,abc | movable bridge,driving,driving |
| e | a | cde,abc,abc | movable bridge,driving,driving |
| c | e | cde,cde | movable bridge,movable bridge |
| c | f | cde,efg,efg | movable bridge,driving,driving |
| c | g | cde,efg,efg | movable bridge,driving,driving |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving |
| b | f | abc,cde,efg,efg | driving,driving,driving,driving |
| e | c | cde,cde | driving,driving |
| e | b | cde,abc,abc | driving,driving,driving |
| e | a | cde,abc,abc | driving,driving,driving |
| c | e | cde,cde | driving,driving |
| c | f | cde,efg,efg | driving,driving,driving |
| c | g | cde,efg,efg | driving,driving,driving |
Scenario: Car - Properly handle durations
Given the node map
@@ -41,7 +41,7 @@ Feature: Car - Handle movable bridge
When I route I should get
| from | to | route | modes | speed |
| a | g | abc,cde,efg,efg | driving,movable bridge,driving,driving | 7 km/h |
| b | f | abc,cde,efg,efg | driving,movable bridge,driving,driving | 5 km/h |
| c | e | cde,cde | movable bridge,movable bridge | 2 km/h |
| e | c | cde,cde | movable bridge,movable bridge | 2 km/h |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h |
| b | f | abc,cde,efg,efg | driving,driving,driving,driving | 5 km/h |
| c | e | cde,cde | driving,driving | 2 km/h |
| e | c | cde,cde | driving,driving | 2 km/h |
@@ -31,7 +31,7 @@ Feature: Traffic - speeds
4,1,27
"""
Scenario: Weighting not based on raster sources
Scenario: Weighting based on speed file
Given the profile "testbot"
Given the extract extra arguments "--generate-edge-lookup"
Given the contract extra arguments "--segment-speed-file speeds.csv"
@@ -0,0 +1,97 @@
@routing @speed @traffic
Feature: Traffic - turn penalties
Background: Evenly spaced grid with multiple intersections
Given the node map
| | a:1 | | b:2 | |
| c:3 | d:4 | e:5 | f:6 | g:7 |
| | h:8 | | i:9 | |
| j:10 | k:11 | l:12 | m:13 | n:14 |
| | o:15 | | p:16 | |
And the ways
| nodes | highway |
| ad | primary |
| cd | primary |
| de | primary |
| dhk | primary |
| bf | primary |
| ef | primary |
| fg | primary |
| fim | primary |
| jk | primary |
| kl | primary |
| ko | primary |
| lm | primary |
| mn | primary |
| mp | primary |
And the profile "car"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting not based on turn penalty file
When I route I should get
| from | to | route | speed | time |
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
# straight
| i | g | fim,fg,fg | 59 km/h | 12s +-1 |
# right
| a | e | ad,de,de | 57 km/h | 12.5s +-1 |
# left
| c | g | cd,de,ef,fg,fg | 63 km/h | 23s +-1 |
# double straight
| p | g | mp,fim,fg,fg | 61 km/h | 23.5s +-1 |
# straight-right
| a | l | ad,dhk,kl,kl | 60 km/h | 24s +-1 |
# straight-left
| l | e | kl,dhk,de,de | 59 km/h | 24.5s +-1 |
# double right
| g | n | fg,fim,mn,mn | 57 km/h | 25s +-1 |
# double left
Scenario: Weighting based on turn penalty file
Given the turn penalty file
"""
9,6,7,1.8
9,13,14,24.5
8,4,3,26
12,11,8,9
8,11,12,13
1,4,5,-0.2
"""
And the contract extra arguments "--turn-penalty-file penalties.csv"
When I route I should get
| from | to | route | speed | time |
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
# straight
| i | g | fim,fg,fg | 55 km/h | 13s +-1 |
# right - ifg penalty
| a | e | ad,de,de | 64 km/h | 11s +-1 |
# left - faster because of negative ade penalty
| c | g | cd,de,ef,fg,fg | 63 km/h | 23s +-1 |
# double straight
| p | g | mp,fim,fg,fg | 59 km/h | 24.5s +-1 |
# straight-right - ifg penalty
| a | l | ad,de,ef,fim,lm,lm | 61 km/h | 35.5s +-1 |
# was straight-left - forced around by hkl penalty
| l | e | lm,fim,ef,ef | 57 km/h | 25s +-1 |
# double right - forced left by lkh penalty
| g | n | fg,fim,mn,mn | 30 km/h | 47.5s +-1 |
# double left - imn penalty
| j | c | jk,kl,lm,fim,ef,de,cd,cd | 60 km/h | 48s +-1 |
# double left - hdc penalty ever so slightly higher than imn; forces all the way around
Scenario: Too-negative penalty clamps, but does not fail
Given the contract extra arguments "--turn-penalty-file penalties.csv"
And the profile "testbot"
And the turn penalty file
"""
1,4,5,-10
"""
When I route I should get
| from | to | route | time |
| a | d | ad,ad | 10s +-1 |
| a | e | ad,de,de | 10s +-1 |
| b | f | bf,bf | 10s +-1 |
| b | g | bf,fg,fg | 20s +-1 |
+5 -5
View File
@@ -10,13 +10,13 @@ Feature: Foot - Street names in instructions
| | c |
And the ways
| nodes | name |
| ab | My Way |
| bc | Your Way |
| nodes | name | ref |
| ab | My Way | A6 |
| bc | Your Way | B7 |
When I route I should get
| from | to | route |
| a | c | My Way,Your Way,Your Way |
| from | to | route |
| a | c | My Way (A6),Your Way (B7),Your Way (B7) |
@unnamed
Scenario: Foot - Use way type to describe unnamed ways
+1 -1
View File
@@ -14,7 +14,7 @@ Feature: Foot - Way ref
When I route I should get
| from | to | route |
| a | b | Utopia Drive / E7,Utopia Drive / E7 |
| a | b | Utopia Drive (E7),Utopia Drive (E7) |
Scenario: Foot - Way with only ref
Given the node map
@@ -0,0 +1,120 @@
@routing @car @bridge @tunnel @guidance
Feature: Car - Guidance - Bridges and Tunnels
Background:
Given the profile "car"
And a grid size of 100 meters
Scenario: Simple Bridge
Given the node map
| a | b | c | d |
And the ways
| nodes | highway | bridge | name |
| ab | primary | | Hauptstraße |
| bc | primary | yes | Hauptstraßenbrücke |
| cd | primary | | Hauptstraße |
When I route I should get
| from | to | route | turns |
| a | d | Hauptstraße,Hauptstraße | depart,arrive |
Scenario: Bridge with Immediate Turn
Given the node map
| | | | d |
| a | | b | c |
| | | | e |
And the ways
| nodes | highway | bridge | name |
| ab | primary | | Hauptstraße |
| bc | primary | yes | Hauptstraßenbrücke |
| dce | primary | | Nebenstraße |
When I route I should get
| from | to | route | turns |
| a | d | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road left,arrive |
| a | e | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road right,arrive |
| e | a | Nebenstraße,Hauptstraßenbrücke,Hauptstraße | depart,turn left,arrive |
| d | a | Nebenstraße,Hauptstraßenbrücke,Hauptstraße | depart,turn right,arrive |
Scenario: Bridge with Immediate Turn Front and Back
Given the node map
| f | | | d |
| a | | b | c |
| g | | | e |
And the ways
| nodes | highway | bridge | name |
| ab | primary | | Hauptstraße |
| bc | primary | yes | Hauptstraßenbrücke |
| dce | primary | | Nebenstraße |
| gaf | primary | | Anderestraße |
When I route I should get
| from | to | route | turns |
| f | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road left,arrive |
| f | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road right,arrive |
| g | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road left,arrive |
| g | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road right,arrive |
| e | f | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn left,end of road right,arrive |
| e | g | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn left,end of road left,arrive |
| d | f | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn right,end of road right,arrive |
| d | g | Nebenstraße,Hauptstraßenbrücke,Anderestraße,Anderestraße | depart,turn right,end of road left,arrive |
Scenario: Simple Tunnel
Given the node map
| a | b | c | d |
And the ways
| nodes | highway | tunnel | name |
| ab | primary | | Hauptstraße |
| bc | primary | yes | Hauptstraßentunnel |
| cd | primary | | Hauptstraße |
When I route I should get
| from | to | route | turns |
| a | d | Hauptstraße,Hauptstraße | depart,arrive |
Scenario: Tunnel with Immediate Turn
Given the node map
| | | | d |
| a | | b | c |
| | | | e |
And the ways
| nodes | highway | tunnel | name |
| ab | primary | | Hauptstraße |
| bc | primary | yes | Hauptstraßentunnel |
| dce | primary | | Nebenstraße |
When I route I should get
| from | to | route | turns |
| a | d | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road left,arrive |
| a | e | Hauptstraße,Nebenstraße,Nebenstraße | depart,end of road right,arrive |
| e | a | Nebenstraße,Hauptstraßentunnel,Hauptstraße | depart,turn left,arrive |
| d | a | Nebenstraße,Hauptstraßentunnel,Hauptstraße | depart,turn right,arrive |
Scenario: Tunnel with Immediate Turn Front and Back
Given the node map
| f | | | d |
| a | | b | c |
| g | | | e |
And the ways
| nodes | highway | bridge | name |
| ab | primary | | Hauptstraße |
| bc | primary | yes | Hauptstraßentunnel |
| dce | primary | | Nebenstraße |
| gaf | primary | | Anderestraße |
When I route I should get
| from | to | route | turns |
| f | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road left,arrive |
| f | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn left,end of road right,arrive |
| g | d | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road left,arrive |
| g | e | Anderestraße,Hauptstraße,Nebenstraße,Nebenstraße | depart,turn right,end of road right,arrive |
| e | f | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn left,end of road right,arrive |
| e | g | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn left,end of road left,arrive |
| d | f | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn right,end of road right,arrive |
| d | g | Nebenstraße,Hauptstraßentunnel,Anderestraße,Anderestraße | depart,turn right,end of road left,arrive |
+347
View File
@@ -0,0 +1,347 @@
@routing @guidance @collapsing
Feature: Collapse
Background:
Given the profile "car"
Given a grid size of 20 meters
Scenario: Segregated Intersection, Cross Belonging to Single Street
Given the node map
| | | i | l | | |
| | | | | | |
| d | | c | b | | a |
| e | | f | g | | h |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | first | yes |
| cd | primary | first | yes |
| ef | primary | first | yes |
| fg | primary | first | yes |
| gh | primary | first | yes |
| ic | primary | second | yes |
| bl | primary | second | yes |
| kg | primary | second | yes |
| fj | primary | second | yes |
| cf | primary | first | yes |
| gb | primary | first | yes |
When I route I should get
| waypoints | route | turns |
| a,l | first,second,second | depart,turn right,arrive |
| a,d | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,h | first,first,first | depart,continue uturn,arrive |
| e,j | first,second,second | depart,turn right,arrive |
| e,h | first,first | depart,arrive |
| e,l | first,second,second | depart,turn left,arrive |
| e,d | first,first,first | depart,continue uturn,arrive |
| k,h | second,first,first | depart,turn right,arrive |
| k,l | second,second | depart,arrive |
| k,d | second,first,first | depart,turn left,arrive |
| k,j | second,second,second | depart,continue uturn,arrive |
| i,d | second,first,first | depart,turn right,arrive |
| i,j | second,second | depart,arrive |
| i,h | second,first,first | depart,turn left,arrive |
| i,l | second,second,second | depart,continue uturn,arrive |
Scenario: Segregated Intersection, Cross Belonging to Correct Street
Given the node map
| | | i | l | | |
| | | | | | |
| d | | c | b | | a |
| e | | f | g | | h |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | first | yes |
| cd | primary | first | yes |
| ef | primary | first | yes |
| fg | primary | first | yes |
| gh | primary | first | yes |
| ic | primary | second | yes |
| bl | primary | second | yes |
| kg | primary | second | yes |
| fj | primary | second | yes |
| cf | primary | second | yes |
| gb | primary | second | yes |
When I route I should get
| waypoints | route | turns |
| a,l | first,second,second | depart,turn right,arrive |
| a,d | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,h | first,first,first | depart,continue uturn,arrive |
| e,j | first,second,second | depart,turn right,arrive |
| e,h | first,first | depart,arrive |
| e,l | first,second,second | depart,turn left,arrive |
| e,d | first,first,first | depart,continue uturn,arrive |
| k,h | second,first,first | depart,turn right,arrive |
| k,l | second,second | depart,arrive |
| k,d | second,first,first | depart,turn left,arrive |
| k,j | second,second,second | depart,continue uturn,arrive |
| i,d | second,first,first | depart,turn right,arrive |
| i,j | second,second | depart,arrive |
| i,h | second,first,first | depart,turn left,arrive |
| i,l | second,second,second | depart,continue uturn,arrive |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets
Given the node map
| | | i | l | | |
| | | | | | |
| d | | c | b | | a |
| e | | f | g | | h |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | second | yes |
| cd | primary | first | yes |
| ef | primary | first | yes |
| fg | primary | first | yes |
| gh | primary | first | yes |
| ic | primary | second | yes |
| bl | primary | second | yes |
| kg | primary | second | yes |
| fj | primary | second | yes |
| cf | primary | second | yes |
| gb | primary | first | yes |
When I route I should get
| waypoints | route | turns |
| a,l | first,second,second | depart,turn right,arrive |
| a,d | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,h | first,first,first | depart,continue uturn,arrive |
| e,j | first,second,second | depart,turn right,arrive |
| e,h | first,first | depart,arrive |
| e,l | first,second,second | depart,turn left,arrive |
| e,d | first,first,first | depart,continue uturn,arrive |
| k,h | second,first,first | depart,turn right,arrive |
| k,l | second,second | depart,arrive |
| k,d | second,first,first | depart,turn left,arrive |
| k,j | second,second,second | depart,continue uturn,arrive |
| i,d | second,first,first | depart,turn right,arrive |
| i,j | second,second | depart,arrive |
| i,h | second,first,first | depart,turn left,arrive |
| i,l | second,second,second | depart,continue uturn,arrive |
Scenario: Partly Segregated Intersection, Two Segregated Roads
Given the node map
| | g | | h | |
| | | | | |
| | | | | |
| c | | b | | a |
| d | | e | | f |
| | | | | |
| | | | | |
| | j | | i | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | first | yes |
| de | primary | first | yes |
| ef | primary | first | yes |
| be | primary | first | no |
| gbh | primary | second | yes |
| iej | primary | second | yes |
When I route I should get
| waypoints | route | turns |
| a,h | first,second,second | depart,turn right,arrive |
| a,c | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,f | first,first,first | depart,continue uturn,arrive |
| d,j | first,second,second | depart,turn right,arrive |
| d,f | first,first | depart,arrive |
| d,h | first,second,second | depart,turn left,arrive |
| d,c | first,first,first | depart,continue uturn,arrive |
| g,c | second,first,first | depart,turn right,arrive |
| g,j | second,second | depart,arrive |
| g,f | second,first,first | depart,turn left,arrive |
| g,h | second,second,second | depart,continue uturn,arrive |
| i,f | second,first,first | depart,turn right,arrive |
| i,h | second,second | depart,arrive |
| i,c | second,first,first | depart,turn left,arrive |
| i,j | second,second,second | depart,continue uturn,arrive |
Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second
Given the node map
| | g | | h | |
| | | | | |
| | | | | |
| c | | b | | a |
| d | | e | | f |
| | | | | |
| | | | | |
| | j | | i | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | first | yes |
| de | primary | first | yes |
| ef | primary | first | yes |
| be | primary | second | no |
| gbh | primary | second | yes |
| iej | primary | second | yes |
When I route I should get
| waypoints | route | turns |
| a,h | first,second,second | depart,turn right,arrive |
| a,c | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,f | first,first,first | depart,continue uturn,arrive |
| d,j | first,second,second | depart,turn right,arrive |
| d,f | first,first | depart,arrive |
| d,h | first,second,second | depart,turn left,arrive |
| d,c | first,first,first | depart,continue uturn,arrive |
| g,c | second,first,first | depart,turn right,arrive |
| g,j | second,second | depart,arrive |
| g,f | second,first,first | depart,turn left,arrive |
| g,h | second,second,second | depart,continue uturn,arrive |
| i,f | second,first,first | depart,turn right,arrive |
| i,h | second,second | depart,arrive |
| i,c | second,first,first | depart,turn left,arrive |
| i,j | second,second,second | depart,continue uturn,arrive |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles
Given the node map
| | | i | l | | |
| | | | | | a |
| | | c | b | | h |
| d | | f | g | | |
| e | | | | | |
| | | j | k | | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | second | yes |
| cd | primary | first | yes |
| ef | primary | first | yes |
| fg | primary | first | yes |
| gh | primary | first | yes |
| ic | primary | second | yes |
| bl | primary | second | yes |
| kg | primary | second | yes |
| fj | primary | second | yes |
| cf | primary | second | yes |
| gb | primary | first | yes |
When I route I should get
| waypoints | route | turns |
| a,l | first,second,second | depart,turn right,arrive |
| a,d | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,h | first,first,first | depart,continue uturn,arrive |
| e,j | first,second,second | depart,turn right,arrive |
| e,h | first,first | depart,arrive |
| e,l | first,second,second | depart,turn left,arrive |
| e,d | first,first,first | depart,continue uturn,arrive |
| k,h | second,first,first | depart,turn right,arrive |
| k,l | second,second | depart,arrive |
| k,d | second,first,first | depart,turn left,arrive |
| k,j | second,second,second | depart,continue uturn,arrive |
| i,d | second,first,first | depart,turn right,arrive |
| i,j | second,second | depart,arrive |
| i,h | second,first,first | depart,turn left,arrive |
| i,l | second,second,second | depart,continue uturn,arrive |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2)
Given the node map
| | | i | l | | |
| | | | | | |
| | | c | b | | |
| d | | f | g | | a |
| e | | | | | h |
| | | j | k | | |
And the ways
| nodes | highway | name | oneway |
| ab | primary | first | yes |
| bc | primary | second | yes |
| cd | primary | first | yes |
| ef | primary | first | yes |
| fg | primary | first | yes |
| gh | primary | first | yes |
| ic | primary | second | yes |
| bl | primary | second | yes |
| kg | primary | second | yes |
| fj | primary | second | yes |
| cf | primary | second | yes |
| gb | primary | first | yes |
When I route I should get
| waypoints | route | turns |
| a,l | first,second,second | depart,turn right,arrive |
| a,d | first,first | depart,arrive |
| a,j | first,second,second | depart,turn left,arrive |
| a,h | first,first,first | depart,continue uturn,arrive |
| e,j | first,second,second | depart,turn right,arrive |
| e,h | first,first | depart,arrive |
| e,l | first,second,second | depart,turn left,arrive |
| e,d | first,first,first | depart,continue uturn,arrive |
| k,h | second,first,first | depart,turn right,arrive |
| k,l | second,second | depart,arrive |
| k,d | second,first,first | depart,turn left,arrive |
| k,j | second,second,second | depart,continue uturn,arrive |
| i,d | second,first,first | depart,turn right,arrive |
| i,j | second,second | depart,arrive |
| i,h | second,first,first | depart,turn left,arrive |
| i,l | second,second,second | depart,continue uturn,arrive |
Scenario: Entering a segregated road
Given the node map
| | a | f | | |
| | | | | g |
| | b | e | | |
| | | | | |
| | | | | |
| c | d | | | |
And the ways
| nodes | highway | name | oneway |
| abc | primary | first | yes |
| def | primary | first | yes |
| be | primary | first | no |
| ge | primary | second | no |
When I route I should get
| waypoints | route | turns |
| d,c | first,first,first | depart,continue uturn,arrive |
| a,f | first,first,first | depart,continue uturn,arrive |
| a,g | first,second,second | depart,turn left,arrive |
| d,g | first,second,second | depart,turn right,arrive |
| g,f | second,first,first | depart,turn right,arrive |
| g,c | second,first,first | depart,end of road left,arrive |
Scenario: Do not collapse turning roads
Given the node map
| | | e | | |
| | | c | | d |
| a | | b | f | |
And the ways
| nodes | highway | name |
| ab | primary | first |
| bc | primary | first |
| cd | primary | first |
| ce | primary | second |
| bf | primary | third |
When I route I should get
| waypoints | route | turns |
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
| a,e | first,second,second | depart,turn left,arrive |
| a,f | first,third,third | depart,turn straight,arrive |
+39 -6
View File
@@ -16,9 +16,42 @@ Feature: Continue Instructions
| bd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,d | abc,bd,bd | depart,new name straight,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,d | abc,bd,bd | depart,turn straight,arrive |
Scenario: Road turning left and straight
Given the node map
| | | c | |
| a | | b | d |
And the ways
| nodes | highway | name |
| abc | primary | road |
| bd | primary | road |
When I route I should get
| waypoints | route | turns |
| a,c | road,road,road | depart,continue left,arrive |
| a,d | road,road | depart,arrive |
Scenario: Road turning left and straight
Given the node map
| | | c | |
| a | | b | d |
| | | e | |
And the ways
| nodes | highway | name |
| abc | primary | road |
| bd | primary | road |
| be | primary | road |
When I route I should get
| waypoints | route | turns |
| a,c | road,road,road | depart,continue left,arrive |
| a,d | road,road | depart,arrive |
| a,e | road,road,road | depart,continue right,arrive |
Scenario: Road turning right
Given the node map
@@ -31,9 +64,9 @@ Feature: Continue Instructions
| bd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue right,arrive |
| a,d | abc,bd,bd | depart,new name straight,arrive |
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,continue right,arrive |
| a,d | abc,bd,bd | depart,turn straight,arrive |
Scenario: Road turning slight left
Given the node map
@@ -0,0 +1,41 @@
@routing @guidance
Feature: Destination Signs
Background:
Given the profile "car"
Scenario: Car - route name assembly with destination signs
Given the node map
| a | b |
| c | d |
| e | f |
| g | h |
| i | j |
| k | l |
| m | n |
| o | p |
| q | r |
And the ways
| nodes | name | ref | destination | destination:ref | oneway | # |
| ab | AB | E1 | | | yes | |
| cd | CD | | Berlin | | yes | |
| ef | EF | | Berlin | A1 | yes | |
| gh | | | Berlin | A1 | yes | |
| ij | | | Berlin | | yes | |
| kl | KL | E1 | Berlin | A1 | yes | |
| mn | MN | | Berlin;Hamburg | A1;A2 | yes | |
| op | OP | | Berlin;Hamburg | A1;A2 | no | mis-tagged destination: not a oneway |
| qr | QR | | | A1;A2 | yes | |
When I route I should get
| from | to | route | # |
| a | b | AB (E1),AB (E1) | |
| c | d | CD (Berlin),CD (Berlin) | |
| e | f | EF (A1: Berlin),EF (A1: Berlin) | |
| g | h | , | |
| i | j | , | |
| k | l | KL (E1),KL (E1) | |
| m | n | MN (A1, A2: Berlin, Hamburg),MN (A1, A2: Berlin, Hamburg) | |
| o | p | OP,OP | guard against mis-tagging |
| q | r | QR (A1, A2),QR (A1, A2) | |
+18 -1
View File
@@ -21,7 +21,6 @@ Feature: End Of Road Instructions
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
Scenario: End of Road with three streets
Given the node map
| | | c |
@@ -104,3 +103,21 @@ Feature: End Of Road Instructions
| waypoints | route | turns |
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
Scenario: End of Road with two ramps - prefer ramp over end of road
Given the node map
| | | c |
| a | | b |
| | | d |
And the ways
| nodes | highway |
| ab | primary |
| bc | motorway_link |
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bc,bc | depart,on ramp left,arrive |
| a,d | ab,bd,bd | depart,on ramp right,arrive |
+70
View File
@@ -211,3 +211,73 @@ Feature: Fork Instructions
| a,c | ,, | depart,fork slight left,arrive |
| a,d | ,, | depart,fork slight right,arrive |
Scenario: Non-Fork on complex intersection - left
Given the node map
| | | | | c |
| a | | b | | |
| | e | | | d |
And the ways
| nodes | highway |
| abc | secondary |
| bd | tertiary |
| eb | tertiary |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc | depart,arrive |
| a,d | abc,bd,bd | depart,turn slight right,arrive |
Scenario: Non-Fork on complex intersection - right
Given the node map
| | e | | | c |
| a | | b | | |
| | | | | d |
And the ways
| nodes | highway |
| abd | secondary |
| bc | tertiary |
| eb | tertiary |
When I route I should get
| waypoints | route | turns |
| a,c | abd,bc,bc | depart,turn slight left,arrive |
| a,d | abd,abd | depart,arrive |
Scenario: Tripple fork
Given the node map
| | | | | | | | | c |
| a | | b | | d | | | | |
| | | | | | | | | e |
And the ways
| nodes | highway |
| ab | secondary |
| bc | secondary |
| bd | secondary |
| be | secondary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bc,bc | depart,fork slight left,arrive |
| a,d | ab,bd,bd | depart,fork straight,arrive |
| a,e | ab,be,be | depart,fork slight right,arrive |
Scenario: Tripple fork -- middle obvious
Given the node map
| | | | | c |
| a | | b | | d |
| | | | | e |
And the ways
| nodes | highway |
| abd | secondary |
| bc | secondary |
| be | secondary |
When I route I should get
| waypoints | route | turns |
| a,c | abd,bc,bc | depart,turn slight left,arrive |
| a,d | abd,abd | depart,arrive |
| a,e | abd,be,be | depart,turn slight right,arrive |
+153
View File
@@ -0,0 +1,153 @@
@routing @guidance @intersections
Feature: Intersections Data
Background:
Given the profile "car"
Given a grid size of 10 meters
Scenario: Passing Three Way South
Given the node map
| a | | b | | c |
| | | d | | |
And the ways
| nodes | name |
| ab | through |
| bc | through |
| bd | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,true:90 true:180 false:270;true:270 |
Scenario: Passing Three Way North
Given the node map
| | | d | | |
| a | | b | | c |
And the ways
| nodes | name |
| ab | through |
| bc | through |
| bd | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,true:0 true:90 false:270;true:270 |
Scenario: Passing Oneway Street In
Given the node map
| | | d | | |
| a | | b | | c |
And the ways
| nodes | name | oneway |
| ab | through | no |
| bc | through | no |
| db | corner | yes |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,false:0 true:90 false:270;true:270 |
Scenario: Passing Oneway Street Out
Given the node map
| | | d | | |
| a | | b | | c |
And the ways
| nodes | name | oneway |
| ab | through | no |
| bc | through | no |
| bd | corner | yes |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,true:0 true:90 false:270;true:270 |
Scenario: Passing Two Intersections
Given the node map
| | | e | | | | |
| a | | b | | c | | d |
| | | | | f | | |
And the ways
| nodes | name |
| ab | through |
| bc | through |
| cd | through |
| be | corner |
| cf | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
Scenario: Regression test #2424
Given the node map
| | | e | | | | | | i | | | | |
| a | | b | | c | | d | | h | | k | | m |
| | | | | f | | | | | | l | | |
And the ways
| nodes | name |
| abcd | Fritz-Elsas-Straße |
| hkm | Fritz-Elsas-Straße |
| dhi | Martin-Luther-Straße |
| be | corner |
| kl | corner |
| cf | corner |
When I route I should get
| waypoints | route | turns |
| a,m | Fritz-Elsas-Straße,Fritz-Elsas-Straße| depart,arrive |
Scenario: Passing Two Intersections, Collapsing
Given the node map
| | | e | | | | |
| a | | b | | c | | d |
| | | | | f | | |
And the ways
| nodes | name |
| ab | through |
| bc | throughbridge |
| cd | through |
| be | corner |
| cf | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
| f,a | corner,throughbridge,through | depart,end of road left,arrive | true:0;true:90 false:180 true:270,true:0 false:90 true:270;true:90 |
Scenario: Roundabouts
Given the node map
| | | | | e | | | | |
| | | | | | | | | |
| | | | | a | | | | |
| | | | 1 | | 4 | | | |
| | | | | | | | | |
| f | | b | | | | d | | h |
| | | | | | | | | |
| | | | 2 | | 3 | | | |
| | | | | c | | | | |
| | | | | | | | | |
| | | | | g | | | | |
And the ways
| nodes | junction |
| abcda | roundabout |
| ea | |
| fb | |
| gc | |
| hd | |
When I route I should get
| waypoints | route | turns | intersections |
| e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 |
| e,g | ea,gc,gc | depart,abcda-exit-2,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0|
| e,h | ea,hd,hd | depart,abcda-exit-3,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 |
| e,2 | ea,abcda,abcda | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1|
| 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:0|
| 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214|
+28 -28
View File
@@ -16,9 +16,9 @@ Feature: Motorway Guidance
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,ramp slight right,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,off ramp slight right,arrive |
Scenario: Ramp Exit Right Curved Right
Given the node map
@@ -32,9 +32,9 @@ Feature: Motorway Guidance
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,ramp right,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,off ramp right,arrive |
Scenario: Ramp Exit Right Curved Left
Given the node map
@@ -49,9 +49,9 @@ Feature: Motorway Guidance
| cfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,cfg,cfg | depart,ramp slight right,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,cfg,cfg | depart,off ramp slight right,arrive |
Scenario: Ramp Exit Left
@@ -65,9 +65,9 @@ Feature: Motorway Guidance
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,ramp slight left,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,off ramp slight left,arrive |
Scenario: Ramp Exit Left Curved Left
Given the node map
@@ -81,9 +81,9 @@ Feature: Motorway Guidance
| bfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,ramp left,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,bfg,bfg | depart,off ramp left,arrive |
Scenario: Ramp Exit Left Curved Right
Given the node map
@@ -97,9 +97,9 @@ Feature: Motorway Guidance
| cfg | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,cfg,cfg | depart,ramp slight left,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| a,g | abcde,cfg,cfg | depart,off ramp slight left,arrive |
Scenario: On Ramp Right
Given the node map
@@ -176,11 +176,11 @@ Feature: Motorway Guidance
| chi | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
| a,i | abcde,chi,chi | depart,ramp slight right,arrive |
| f,i | fgc,chi,chi | depart,ramp right,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
| a,i | abcde,chi,chi | depart,off ramp slight right,arrive |
| f,i | fgc,chi,chi | depart,off ramp right,arrive |
Scenario: On And Off Ramp Left
Given the node map
@@ -194,11 +194,11 @@ Feature: Motorway Guidance
| chi | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
| a,i | abcde,chi,chi | depart,ramp slight left,arrive |
| f,i | fgc,chi,chi | depart,ramp left,arrive |
| waypoints | route | turns |
| a,e | abcde,abcde | depart,arrive |
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
| a,i | abcde,chi,chi | depart,off ramp slight left,arrive |
| f,i | fgc,chi,chi | depart,off ramp left,arrive |
Scenario: Merging Motorways
Given the node map
+31
View File
@@ -133,3 +133,34 @@ Feature: New-Name Instructions
When I route I should get
| waypoints | route | turns |
| a,c | ab,bc,bc | depart,new name slight right,arrive |
Scenario: Empty road names - Announce Change From, suppress Change To
Given the node map
| a | | b | | c | | d |
And the ways
| nodes | name |
| ab | ab |
| bc | |
| cd | cd |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,new name straight,arrive |
| a,c | ab, | depart,arrive |
Scenario: Empty road names - Loose name shortly
Given the node map
| a | | b | | c | | d | | e |
And the ways
| nodes | name |
| ab | name |
| bc | with-name |
| cd | |
| de | with-name |
When I route I should get
| waypoints | route | turns |
| a,e | name,with-name,with-name | depart,new name straight,arrive |
| b,e | with-name,with-name | depart,arrive |
+32 -32
View File
@@ -16,8 +16,8 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp right,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp right,arrive |
Scenario: Ramp On Through Street Left
Given the node map
@@ -30,8 +30,8 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp left,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp left,arrive |
Scenario: Ramp On Through Street Left and Right
Given the node map
@@ -46,9 +46,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp right,arrive |
| a,e | abc,be,be | depart,ramp left,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp right,arrive |
| a,e | abc,be,be | depart,on ramp left,arrive |
Scenario: Ramp On Three Way Intersection Right
Given the node map
@@ -62,8 +62,8 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,ramp right,arrive |
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,on ramp right,arrive |
Scenario: Ramp On Three Way Intersection Right
Given the node map
@@ -78,8 +78,8 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,ramp right,arrive |
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,on ramp right,arrive |
Scenario: Ramp Off Though Street
Given the node map
@@ -93,9 +93,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp right,arrive |
| a,c | abc,abc | depart,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp right,arrive |
| a,c | abc,abc | depart,arrive |
Scenario: Straight Ramp Off Turning Though Street
Given the node map
@@ -108,9 +108,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp straight,arrive |
| a,c | abc,abc,abc | depart,continue left,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp straight,arrive |
| a,c | abc,abc,abc | depart,continue left,arrive |
Scenario: Fork Ramp Off Turning Though Street
Given the node map
@@ -124,9 +124,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp right,arrive |
| a,c | abc,abc,abc | depart,continue left,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp right,arrive |
| a,c | abc,abc,abc | depart,continue left,arrive |
Scenario: Fork Ramp
Given the node map
@@ -141,9 +141,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,ramp right,arrive |
| a,c | ab,bc,bc | depart,turn left,arrive |
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,on ramp right,arrive |
| a,c | ab,bc,bc | depart,turn left,arrive |
Scenario: Fork Slight Ramp
Given the node map
@@ -158,9 +158,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,ramp slight right,arrive |
| a,c | ab,bc,bc | depart,turn slight left,arrive |
| waypoints | route | turns |
| a,d | ab,bd,bd | depart,on ramp slight right,arrive |
| a,c | ab,bc,bc | depart,turn slight left,arrive |
Scenario: Fork Slight Ramp on Through Street
Given the node map
@@ -174,9 +174,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp slight right,arrive |
| a,c | abc,abc,abc | depart,continue slight left,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp slight right,arrive |
| a,c | abc,abc,abc | depart,continue slight left,arrive |
Scenario: Fork Slight Ramp on Obvious Through Street
Given the node map
@@ -190,9 +190,9 @@ Feature: Ramp Guidance
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,ramp slight right,arrive |
| a,c | abc,abc | depart,arrive |
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp slight right,arrive |
| a,c | abc,abc | depart,arrive |
Scenario: Two Ramps Joining into common Motorway
Given the node map
+10 -10
View File
@@ -194,15 +194,15 @@ Feature: Rotary
And the ways
| nodes | junction |
| ab | |
| ad | |
| bcdb | roundabout |
| ce | |
| df | |
| be | |
| cf | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
| a,e | ad,be,be | depart,bcdb-exit-1,arrive |
| a,f | ad,cf,cf | depart,bcdb-exit-2,arrive |
Scenario: Collinear in X,Y
Given the node map
@@ -213,15 +213,15 @@ Feature: Rotary
And the ways
| nodes | junction |
| ab | |
| ac | |
| bcdb | roundabout |
| ce | |
| df | |
| de | |
| bf | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,bcdb-exit-1,arrive |
| a,f | ab,df,df | depart,bcdb-exit-2,arrive |
| a,e | ac,de,de | depart,bcdb-exit-1,arrive |
| a,f | ac,bf,bf | depart,bcdb-exit-2,arrive |
Scenario: Collinear in X,Y
Given the node map
+369
View File
@@ -0,0 +1,369 @@
@routing @guidance
Feature: Basic Roundabout
Background:
Given the profile "car"
Given a grid size of 3 meters
Scenario: Enter and Exit
Given the node map
| | | a | | |
| | | b | | |
| h | g | | c | d |
| | | e | | |
| | | f | | |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bgecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
Scenario: Enter and Exit - Rotated
Given the node map
| a | | | d |
| | b | c | |
| | g | e | |
| h | | | f |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bgecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout turn left exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout turn straight exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout turn left exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
Scenario: Only Enter
Given the node map
| | | a | | |
| | | b | | |
| d | c | | g | h |
| | | e | | |
| | | f | | |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| a,e | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| a,g | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| d,e | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| d,g | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| d,b | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| f,g | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| f,b | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| f,c | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| h,b | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| h,c | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| h,e | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
Scenario: Only Exit
Given the node map
| | | a | | |
| | | b | | |
| d | c | | g | h |
| | | e | | |
| | | f | | |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| b,d | bcegb,cd,cd | depart,roundabout-exit-1,arrive |
| b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive |
| b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive |
| c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive |
| c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive |
| c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive |
| e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive |
| e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive |
| e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive |
| g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive |
| g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive |
| g,f | bcegb,ef,ef | depart,roundabout-exit-3,arrive |
#phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits
Scenario: Drive Around
Given the node map
| | | a | | |
| | | b | | |
| d | c | | g | h |
| | | e | | |
| | | f | | |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| b,c | bcegb,bcegb | depart,arrive |
| b,e | bcegb,bcegb | depart,arrive |
| b,g | bcegb,bcegb | depart,arrive |
| c,e | bcegb,bcegb | depart,arrive |
| c,g | bcegb,bcegb | depart,arrive |
| c,b | bcegb,bcegb | depart,arrive |
| e,g | bcegb,bcegb | depart,arrive |
| e,b | bcegb,bcegb | depart,arrive |
| e,c | bcegb,bcegb | depart,arrive |
| g,b | bcegb,bcegb | depart,arrive |
| g,c | bcegb,bcegb | depart,arrive |
| g,e | bcegb,bcegb | depart,arrive |
Scenario: Mixed Entry and Exit - Not an Intersection
Given the node map
| | c | | a | |
| j | | b | | f |
| | k | | e | |
| l | | h | | d |
| | g | | i | |
And the ways
| nodes | junction | oneway |
| abc | | yes |
| def | | yes |
| ghi | | yes |
| jkl | | yes |
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-1,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive |
| a,f | abc,def,def | depart,roundabout-exit-4,arrive |
| d,f | def,def,def | depart,roundabout-exit-1,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-2,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-2,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
Scenario: Segregated roads - Not an intersection
Given the node map
| | a | | c | |
| l | | b | | d |
| | k | | e | |
| j | | h | | f |
| | i | | g | |
And the ways
| nodes | junction | oneway |
| abc | | yes |
| def | | yes |
| ghi | | yes |
| jkl | | yes |
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
Scenario: Collinear in X
Given the node map
| a | b | c | d | f |
| | | e | | |
And the ways
| nodes | junction |
| ab | |
| bcdb | roundabout |
| ce | |
| df | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
| a,f | ab,df,df | depart,roundabout-exit-2,arrive |
Scenario: Collinear in X,Y
Given the node map
| a | | |
| b | | |
| c | d | f |
| e | | |
And the ways
| nodes | junction |
| ab | |
| bcdb | roundabout |
| ce | |
| df | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout turn straight exit-1,arrive |
| a,f | ab,df,df | depart,roundabout turn left exit-2,arrive |
Scenario: Collinear in X,Y
Given the node map
| a | | |
| d | | |
| b | c | f |
| e | | |
And the ways
| nodes | junction |
| ad | |
| bcdb | roundabout |
| be | |
| cf | |
When I route I should get
| waypoints | route | turns |
| a,e | ad,be,be | depart,roundabout turn straight exit-1,arrive |
| a,f | ad,cf,cf | depart,roundabout turn left exit-2,arrive |
Scenario: Collinear in X,Y
Given the node map
| a | | |
| c | | |
| d | b | f |
| e | | |
And the ways
| nodes | junction |
| ac | |
| bcdb | roundabout |
| de | |
| bf | |
When I route I should get
| waypoints | route | turns |
| a,e | ac,de,de | depart,roundabout turn straight exit-1,arrive |
| a,f | ac,bf,bf | depart,roundabout turn left exit-2,arrive |
Scenario: Enter and Exit -- too complex
Given the node map
| j | | a | | |
| | i | b | | |
| | g | | c | d |
| h | | e | | |
| | | f | | |
And the ways
| nodes | junction |
| ab | |
| ij | |
| cd | |
| ef | |
| gh | |
| bigecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout-exit-4,arrive |
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
| a,h | ab,gh,gh | depart,roundabout-exit-2,arrive |
| d,f | cd,ef,ef | depart,roundabout-exit-4,arrive |
| d,h | cd,gh,gh | depart,roundabout-exit-3,arrive |
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout-exit-4,arrive |
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
Scenario: Enter and Exit -- Non-Distinct
Given the node map
| | | a | | |
| | | b | | |
| | g | | c | d |
| | | e | | |
| h | | f | | |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bgecb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout-exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout-exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout-exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout-exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout-exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
+93 -15
View File
@@ -165,6 +165,84 @@ Feature: Basic Roundabout
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
Scenario: Mixed Entry and Exit - segregated roads
Given the node map
| | | a | | c | | |
| | | | | | | |
| l | | | b | | | d |
| | | k | | e | | |
| j | | | h | | | f |
| | | | | | | |
| | | i | | g | | |
And the ways
| nodes | junction | oneway |
| abc | | yes |
| def | | yes |
| ghi | | yes |
| jkl | | yes |
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
Scenario: Mixed Entry and Exit - segregated roads, different names
Given the node map
| | | a | | c | | |
| | | | | | | |
| l | | | b | | | d |
| | | k | | e | | |
| j | | | h | | | f |
| | | | | | | |
| | | i | | g | | |
And the ways
| nodes | junction | oneway |
| ab | | yes |
| bc | | yes |
| de | | yes |
| ef | | yes |
| gh | | yes |
| hi | | yes |
| jk | | yes |
| kl | | yes |
| bkheb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bc,bc | depart,roundabout-exit-4,arrive |
| a,l | ab,kl,kl | depart,roundabout-exit-1,arrive |
| a,i | ab,hi,hi | depart,roundabout-exit-2,arrive |
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
| d,f | de,ef,ef | depart,roundabout-exit-4,arrive |
| d,c | de,bc,bc | depart,roundabout-exit-1,arrive |
| d,l | de,kl,kl | depart,roundabout-exit-2,arrive |
| d,i | de,hi,hi | depart,roundabout-exit-3,arrive |
| g,i | gh,hi,hi | depart,roundabout-exit-4,arrive |
| g,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
| g,c | gh,bc,bc | depart,roundabout-exit-2,arrive |
| g,l | gh,kl,kl | depart,roundabout-exit-3,arrive |
| j,l | jk,kl,kl | depart,roundabout-exit-4,arrive |
| j,i | jk,hi,hi | depart,roundabout-exit-1,arrive |
| j,f | jk,ef,ef | depart,roundabout-exit-2,arrive |
| j,c | jk,bc,bc | depart,roundabout-exit-3,arrive |
Scenario: Collinear in X
Given the node map
| a | b | c | d | f |
@@ -184,11 +262,11 @@ Feature: Basic Roundabout
Scenario: Collinear in Y
Given the node map
| a | |
| b | |
| c | e |
| d | |
| f | |
| | a |
| | b |
| e | c |
| | d |
| | f |
And the ways
| nodes | junction |
@@ -230,15 +308,15 @@ Feature: Basic Roundabout
And the ways
| nodes | junction |
| ab | |
| ad | |
| bcdb | roundabout |
| ce | |
| df | |
| be | |
| cf | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
| a,f | ab,df,df | depart,roundabout-exit-2,arrive |
| a,e | ad,be,be | depart,roundabout-exit-1,arrive |
| a,f | ad,cf,cf | depart,roundabout-exit-2,arrive |
Scenario: Collinear in X,Y
Given the node map
@@ -249,13 +327,13 @@ Feature: Basic Roundabout
And the ways
| nodes | junction |
| ab | |
| ac | |
| bcdb | roundabout |
| ce | |
| df | |
| de | |
| bf | |
When I route I should get
| waypoints | route | turns |
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
| a,f | ab,df,df | depart,roundabout-exit-2,arrive |
| a,e | ac,de,de | depart,roundabout-exit-1,arrive |
| a,f | ac,bf,bf | depart,roundabout-exit-2,arrive |
+101
View File
@@ -0,0 +1,101 @@
@routing @guidance
Feature: Suppress New Names on dedicated Suffices
Background:
Given the profile "car"
Given a grid size of 10 meters
Scenario: Suffix To Suffix
Given the node map
| a | | b | | c |
And the ways
| nodes | name |
| ab | 42 N |
| bc | 42 S |
When I route I should get
| waypoints | route | turns |
| a,c | 42 N,42 S | depart,arrive |
Scenario: Suffix To Suffix Ref
Given the node map
| a | | b | | c |
And the ways
| nodes | name | ref |
| ab | 42 N | |
| bc | 42 S | 101 |
When I route I should get
| waypoints | route | turns |
| a,c | 42 N,42 S (101) | depart,arrive |
Scenario: Prefix Change
Given the node map
| a | | b | | c |
And the ways
| nodes | name |
| ab | West 42 |
| bc | East 42 |
When I route I should get
| waypoints | route | turns |
| a,c | West 42,East 42 | depart,arrive |
Scenario: Prefix Change and Reference
Given the node map
| a | | b | | c |
And the ways
| nodes | name | ref |
| ab | West 42 | 101 |
| bc | East 42 | |
When I route I should get
| waypoints | route | turns |
| a,c | West 42 (101),East 42 | depart,arrive |
Scenario: Suffix To Suffix - Turn
Given the node map
| a | | b | | c |
| | | d | | |
And the ways
| nodes | name |
| ab | 42 N |
| bc | 42 S |
| bd | 42 E |
When I route I should get
| waypoints | route | turns |
| a,c | 42 N,42 S | depart,arrive |
| a,d | 42 N,42 E,42 E | depart,turn right,arrive |
Scenario: Suffix To No Suffix
Given the node map
| a | | b | | c |
And the ways
| nodes | name |
| ab | 42 N |
| bc | 42 |
When I route I should get
| waypoints | route | turns |
| a,c | 42 N,42 | depart,arrive |
Scenario: No Suffix To Suffix
Given the node map
| a | | b | | c |
And the ways
| nodes | name |
| ab | 42 |
| bc | 42 S |
When I route I should get
| waypoints | route | turns |
| a,c | 42,42 S | depart,arrive |
+524
View File
@@ -282,3 +282,527 @@ Feature: Simple Turns
| h,c | first,second,second | depart,turn left,arrive |
| h,i | first,first,first | depart,continue uturn,arrive |
Scenario: Three Way Similar Sharp Turns
Given the node map
| a | | | | b |
| c | | | | |
| | d | | | |
And the ways
| nodes | highway |
| ab | primary |
| bc | primary |
| bd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bc,bc | depart,turn sharp right,arrive |
| a,d | ab,bd,bd | depart,turn sharp right,arrive |
| d,c | bd,bc,bc | depart,turn sharp left,arrive |
| d,a | bd,ab,ab | depart,turn sharp left,arrive |
Scenario: Left Turn Assignment (1)
Given the node map
| | | | | d |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn slight left,arrive |
Scenario: Left Turn Assignment (2)
Given the node map
| | | | | d |
| | | | | |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn left,arrive |
Scenario: Left Turn Assignment (3)
Given the node map
| | | | d | |
| | | | | |
| | | | | |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn left,arrive |
Scenario: Left Turn Assignment (4)
Given the node map
| | | d | | |
| | | | | |
| | | | | |
| | | | | |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn left,arrive |
Scenario: Left Turn Assignment (5)
Given the node map
| | d | | | |
| | | | | |
| | | | | |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn left,arrive |
Scenario: Left Turn Assignment (6)
Given the node map
| d | | | | |
| | | | | |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp left,arrive |
Scenario: Left Turn Assignment (7)
Given the node map
| d | | | | |
| a | | b | | c |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp left,arrive |
Scenario: Right Turn Assignment (1)
Given the node map
| | | e | | |
| a | | b | | c |
| | | | | d |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn slight right,arrive |
Scenario: Right Turn Assignment (2)
Given the node map
| | | e | | |
| a | | b | | c |
| | | | | |
| | | | | d |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
Scenario: Right Turn Assignment (3)
Given the node map
| | | e | | |
| a | | b | | c |
| | | | | |
| | | | | |
| | | | d | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
Scenario: Right Turn Assignment (4)
Given the node map
| | | e | | |
| a | | b | | c |
| | | | | |
| | | | | |
| | | | | |
| | | d | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
Scenario: Right Turn Assignment (5)
Given the node map
| | | e | | |
| a | | b | | c |
| | | | | |
| | | | | |
| | d | | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
Scenario: Right Turn Assignment (6)
Given the node map
| | | e | | |
| a | | b | | c |
| | | | | |
| d | | | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
Scenario: Right Turn Assignment (7)
Given the node map
| | | e | | |
| a | | b | | c |
| d | | | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
Scenario: Right Turn Assignment Two Turns
Given the node map
| | | f | | |
| a | | b | | c |
| | | | | |
| d | e | | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
| a,e | abc,be,be | depart,turn right,arrive |
Scenario: Right Turn Assignment Two Turns (2)
Given the node map
| | | f | | c |
| a | | b | | |
| | | | | e |
| | | | d | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
| a,e | abc,be,be | depart,turn slight right,arrive |
Scenario: Right Turn Assignment Two Turns (3)
Given the node map
| | | f | | |
| a | | b | | c |
| | | | | e |
| | | | d | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
| a,e | abc,be,be | depart,turn slight right,arrive |
Scenario: Right Turn Assignment Two Turns (4)
Given the node map
| | | f | | |
| a | | b | | c |
| | | | | |
| | | d | | e |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn right,arrive |
| a,e | abc,be,be | depart,turn slight right,arrive |
Scenario: Right Turn Assignment Three Turns
Given the node map
| | | g | | |
| a | | b | | c |
| | d | | f | |
| | | e | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
| bg | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
| a,e | abc,be,be | depart,turn right,arrive |
| a,f | abc,bf,bf | depart,turn slight right,arrive |
Scenario: Slight Turn involving Oneways
Given the node map
| | | a | | |
| | | | | |
| | | b | | e |
| d | | | | |
| | | c | | |
And the ways
| nodes | highway | oneway |
| abc | primary | yes |
| dbe | primary | no |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc | depart,arrive |
| d,e | dbe,dbe | depart,arrive |
| e,d | dbe,dbe | depart,arrive |
Scenario: Slight Turn involving Oneways
Given the node map
| | | | a | |
| | | | | |
| | | | | |
| | | b | | e |
| d | | | | |
| | | c | | |
And the ways
| nodes | highway | oneway |
| abc | primary | yes |
| dbe | primary | no |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc | depart,arrive |
| d,e | dbe,dbe | depart,arrive |
| e,d | dbe,dbe | depart,arrive |
Scenario: Slight Turn involving Oneways - Name Change
Given the node map
| | | a | | |
| | | | | |
| | | b | | e |
| d | | | | |
| | | c | | |
And the ways
| nodes | highway | oneway |
| abc | primary | yes |
| db | primary | no |
| be | primary | no |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc | depart,arrive |
| d,e | db,be,be | depart,new name slight right,arrive |
| e,d | be,db,db | depart,new name slight left,arrive |
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 1
Given the node map
| | | g | | |
| a | | b | | c |
| | | | | |
| | d | e | f | |
And the ways
| nodes | highway | oneway |
| abc | primary | no |
| db | primary | yes |
| eb | primary | no |
| fb | primary | no |
| bg | primary | no |
When I route I should get
| waypoints | route | turns |
| a,e | abc,eb,eb | depart,turn right,arrive |
| a,f | abc,fb,fb | depart,turn slight right,arrive |
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 2
Given the node map
| | | g | | |
| a | | b | | c |
| | | | | |
| | d | e | f | |
And the ways
| nodes | highway | oneway |
| abc | primary | no |
| db | primary | no |
| eb | primary | yes |
| fb | primary | no |
| bg | primary | no |
When I route I should get
| waypoints | route | turns |
| a,d | abc,db,db | depart,turn sharp right,arrive |
| a,f | abc,fb,fb | depart,turn right,arrive |
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 3
Given the node map
| | | g | | |
| a | | b | | c |
| | | | | |
| | d | e | f | |
And the ways
| nodes | highway | oneway |
| abc | primary | no |
| db | primary | no |
| be | primary | no |
| fb | primary | yes |
| bg | primary | no |
When I route I should get
| waypoints | route | turns |
| a,d | abc,db,db | depart,turn sharp right,arrive |
| a,e | abc,be,be | depart,turn right,arrive |
Scenario: Conflicting Turns with well distinguished turn
Given the node map
| a | | | b | | | c |
| | | | | | | |
| f | | | | | | d |
| | | | | | | e |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn slight right,arrive |
| a,e | abc,be,be | depart,turn right,arrive |
| a,f | abc,bf,bf | depart,turn sharp right,arrive |
Scenario: Conflicting Turns with well distinguished turn (back)
Given the node map
| a | | | b | | | c |
| | | | | | | |
| d | | | | | | f |
| | e | | | | | |
And the ways
| nodes | highway |
| abc | primary |
| bd | primary |
| be | primary |
| bf | primary |
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp right,arrive |
| a,e | abc,be,be | depart,turn right,arrive |
| a,f | abc,bf,bf | depart,turn slight right,arrive |
+25 -14
View File
@@ -10,13 +10,11 @@ module.exports = function () {
});
this.Given(/^the extract extra arguments "(.*?)"$/, (args, callback) => {
this.setExtractArgs(args);
callback();
this.setExtractArgs(args, callback);
});
this.Given(/^the contract extra arguments "(.*?)"$/, (args, callback) => {
this.setContractArgs(args);
callback();
this.setContractArgs(args, callback);
});
this.Given(/^a grid size of (\d+) meters$/, (meters, callback) => {
@@ -49,18 +47,27 @@ module.exports = function () {
var addNode = (name, ri, ci, cb) => {
if (name) {
if (name.length !== 1) throw new Error(util.format('*** node invalid name %s, must be single characters', name));
if (!name.match(/[a-z0-9]/)) throw new Error(util.format('*** invalid node name %s, must me alphanumeric', name));
var lonLat;
if (name.match(/[a-z]/)) {
if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name));
var nodeWithID = name.match(/([a-z])\:([0-9]*)/);
if (nodeWithID) {
var nodeName = nodeWithID[1],
nodeID = nodeWithID[2];
if (this.nameNodeHash[nodeName]) throw new Error(util.format('*** duplicate node %s', name));
lonLat = this.tableCoordToLonLat(ci, ri);
this.addOSMNode(name, lonLat[0], lonLat[1], null);
this.addOSMNode(nodeName, lonLat[0], lonLat[1], nodeID);
} else {
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name);
lonLat = this.tableCoordToLonLat(ci, ri);
this.addLocation(name, lonLat[0], lonLat[1], null);
if (name.length !== 1) throw new Error(util.format('*** node invalid name %s, must be single characters', name));
if (!name.match(/[a-z0-9]/)) throw new Error(util.format('*** invalid node name %s, must me alphanumeric', name));
var lonLat;
if (name.match(/[a-z]/)) {
if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name));
lonLat = this.tableCoordToLonLat(ci, ri);
this.addOSMNode(name, lonLat[0], lonLat[1], null);
} else {
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name);
lonLat = this.tableCoordToLonLat(ci, ri);
this.addLocation(name, lonLat[0], lonLat[1], null);
}
}
cb();
@@ -228,6 +235,10 @@ module.exports = function () {
fs.writeFile(path.resolve(this.TEST_FOLDER, 'speeds.csv'), data, callback);
});
this.Given(/^the turn penalty file$/, (data, callback) => {
fs.writeFile(path.resolve(this.TEST_FOLDER, 'penalties.csv'), data, callback);
});
this.Given(/^the data has been saved to disk$/, (callback) => {
try {
this.reprocess(callback);
+13 -1
View File
@@ -33,7 +33,9 @@ module.exports = function () {
var subMatchings = [],
turns = '',
route = '',
duration = '';
duration = '',
annotation = '';
if (res.statusCode === 200) {
if (headers.has('matchings')) {
@@ -54,6 +56,11 @@ module.exports = function () {
if (json.matchings.length != 1) throw new Error('*** Checking duration only supported for matchings with one subtrace');
duration = json.matchings[0].duration;
}
if (headers.has('annotation')) {
if (json.matchings.length != 1) throw new Error('*** Checking annotation only supported for matchings with one subtrace');
annotation = this.annotationList(json.matchings[0]);
}
}
if (headers.has('turns')) {
@@ -68,6 +75,10 @@ module.exports = function () {
got.duration = duration.toString();
}
if (headers.has('annotation')) {
got.annotation = annotation.toString();
}
var ok = true;
var encodedResult = '',
extendedTarget = '';
@@ -134,6 +145,7 @@ module.exports = function () {
this.requestUrl(row.request, afterRequest);
} else {
var params = this.queryParams;
params['annotate'] = 'true';
got = {};
for (var k in row) {
var match = k.match(/param:(.*)/);
+1 -1
View File
@@ -1,7 +1,7 @@
var assert = require('assert');
module.exports = function () {
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.SHUTDOWN_TIMEOUT }, (options, callback) => {
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
this.runBin('osrm-routed', options, () => {
callback();
});
+1
View File
@@ -71,6 +71,7 @@ module.exports = function () {
r.status = res.statusCode === 200 ? 'x' : null;
if (r.status) {
r.route = this.wayList(r.json.routes[0]);
r.summary = r.json.routes[0].legs.map(l => l.summary).join(',');
if (r.route.split(',')[0] === util.format('w%d', i)) {
r.time = r.json.routes[0].duration;
+1 -2
View File
@@ -3,8 +3,7 @@ var d3 = require('d3-queue');
module.exports = function () {
this.When(/^I route I should get$/, this.WhenIRouteIShouldGet);
// This is used to route 100 times; timeout for entire step is therefore set to 100 * STRESS_TIMEOUT
this.When(/^I route (\d+) times I should get$/, { timeout: 30000 }, (n, table, callback) => {
this.When(/^I route (\d+) times I should get$/, { timeout: 100 * this.TIMEOUT }, (n, table, callback) => {
var q = d3.queue(1);
for (var i=0; i<n; i++) {
+2 -2
View File
@@ -46,8 +46,8 @@ module.exports = function () {
if (headers.has('trips')) {
subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => {
var toAdd = [];
if (i === 0) toAdd.push(sl.steps[0].maneuver.location);
toAdd.push(sl.steps[sl.steps.length-1].maneuver.location);
if (i === 0) toAdd.push(sl.steps[0].intersections[0].location);
toAdd.push(sl.steps[sl.steps.length-1].intersections[0].location);
return toAdd;
})));
}
+7 -4
View File
@@ -19,8 +19,6 @@ module.exports = function () {
this.osmData = new classes.osmData(this);
this.STRESS_TIMEOUT = 300;
this.OSRMLoader = this._OSRMLoader();
this.PREPROCESS_LOG_FILE = path.resolve(this.TEST_FOLDER, 'preprocessing.log');
@@ -105,11 +103,16 @@ module.exports = function () {
} else cb();
};
this.setExtractArgs = (args) => {
this.setExtractArgs = (args, callback) => {
this.extractArgs = args;
this.forceExtract = true;
this.forceContract = true;
callback();
};
this.setContractArgs = (args) => {
this.setContractArgs = (args, callback) => {
this.contractArgs = args;
this.forceContract = true;
callback();
};
};
+6 -4
View File
@@ -222,7 +222,7 @@ module.exports = function () {
});
};
['osrm','osrm.names','osrm.restrictions','osrm.ebg','osrm.enw','osrm.edges','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.properties'].forEach(file => {
['osrm','osrm.names','osrm.restrictions','osrm.ebg','osrm.enw','osrm.edges','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.properties','osrm.icd'].forEach(file => {
q.defer(rename, file);
});
@@ -273,7 +273,7 @@ module.exports = function () {
var q = d3.queue();
['osrm.hsgr','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.core','osrm.edges','osrm.datasource_indexes','osrm.datasource_names','osrm.level'].forEach((file) => {
['osrm.hsgr','osrm.fileIndex','osrm.geometry','osrm.nodes','osrm.ramIndex','osrm.core','osrm.edges','osrm.datasource_indexes','osrm.datasource_names','osrm.level','osrm.icd'].forEach((file) => {
q.defer(rename, file);
});
@@ -295,9 +295,10 @@ module.exports = function () {
this.writeAndExtract((e) => {
if (e) return callback(e);
this.isContracted((isContracted) => {
var contractFn = isContracted ? noop : this.contractData;
var contractFn = (isContracted && !this.forceContract) ? noop : this.contractData;
if (isContracted) this.log('Already contracted ' + this.osmData.contractedFile, 'preprocess');
contractFn((e) => {
this.forceContract = false;
if (e) return callback(e);
this.logPreprocessDone();
callback();
@@ -311,9 +312,10 @@ module.exports = function () {
this.writeInputData((e) => {
if (e) return callback(e);
this.isExtracted((isExtracted) => {
var extractFn = isExtracted ? noop : this.extractData;
var extractFn = (isExtracted && !this.forceExtract) ? noop : this.extractData;
if (isExtracted) this.log('Already extracted ' + this.osmData.extractedFile, 'preprocess');
extractFn((e) => {
this.forceExtract = false;
callback(e);
});
});
+73 -6
View File
@@ -52,24 +52,91 @@ module.exports = {
match (got, want) {
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
matchAbs = want.match(/(.*)\s+\+\-(.+)$/),
matchRe = want.match(/^\/(.*)\/$/);
matchRe = want.match(/^\/(.*)\/$/),
// we use this for matching before/after bearing
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/);
function inRange(margin, got, want) {
var fromR = parseFloat(want) - margin,
toR = parseFloat(want) + margin;
return parseFloat(got) >= fromR && parseFloat(got) <= toR;
}
function parseIntersectionString(str) {
return str.split(';')
.map((turn_intersections) => turn_intersections
.split(',')
.map((intersection) => intersection
.split(' ')
.map((entry_bearing_pair) => entry_bearing_pair
.split(':'))));
}
if (got === want) {
return true;
} else if (matchBearingListAbs) {
let want_and_margin = want.split('+-'),
margin = parseFloat(want_and_margin[1].trim()),
want_pairs = want_and_margin[0].trim().split(',').map((pair) => pair.split('->')),
got_pairs = got.split(',').map((pair) => pair.split('->'));
if (want_pairs.length != got_pairs.length)
{
return false;
}
for (var i = 0; i < want_pairs.length; ++i)
{
if (!inRange(margin, got_pairs[i][0], want_pairs[i][0]) ||
!inRange(margin, got_pairs[i][1], want_pairs[i][1]))
{
return false;
}
}
return true;
} else if (matchIntersectionListAbs) {
let margin = parseFloat(want.split('+-')[1]),
want_intersections = parseIntersectionString(want.split('+-')[0].trim()),
got_intersections = parseIntersectionString(got);
if (want_intersections.length != got_intersections.length)
{
return false;
}
for (let step_idx = 0; step_idx < want_intersections.length; ++step_idx)
{
if (want_intersections[step_idx].length != got_intersections[step_idx].length)
{
return false;
}
for (let intersection_idx = 0; intersection_idx < want_intersections[step_idx].length; ++intersection_idx)
{
if (want_intersections[step_idx][intersection_idx].length != got_intersections[step_idx][intersection_idx].length)
{
return false;
}
for (let pair_idx = 0; pair_idx < want_intersections[step_idx][intersection_idx].length; ++pair_idx)
{
let want_pair = want_intersections[step_idx][intersection_idx][pair_idx],
got_pair = got_intersections[step_idx][intersection_idx][pair_idx];
if (got_pair[0] != want_pair[0] ||
!inRange(margin, got_pair[1], want_pair[1]))
{
return false;
}
}
}
}
return true;
} else if (matchPercent) { // percentage range: 100 ~ 5%
var target = parseFloat(matchPercent[1]),
percentage = parseFloat(matchPercent[2]);
if (target === 0) {
return true;
} else {
var ratio = Math.abs(1 - parseFloat(got) / target);
let ratio = Math.abs(1 - parseFloat(got) / target);
return 100 * ratio < percentage;
}
} else if (matchAbs) { // absolute range: 100 +-5
var margin = parseFloat(matchAbs[2]),
fromR = parseFloat(matchAbs[1]) - margin,
toR = parseFloat(matchAbs[1]) + margin;
return parseFloat(got) >= fromR && parseFloat(got) <= toR;
let margin = parseFloat(matchAbs[2]);
return inRange(margin, got, matchAbs[1]);
} else if (matchRe) { // regex: /a,b,.*/
return got.match(matchRe[1]);
} else {
+3 -26
View File
@@ -6,10 +6,9 @@ var d3 = require('d3-queue');
module.exports = function () {
this.initializeEnv = (callback) => {
this.DEFAULT_PORT = 5000;
// OSX builds on Travis hit a timeout of ~2000 from time to time
this.DEFAULT_TIMEOUT = 5000;
this.setDefaultTimeout(this.DEFAULT_TIMEOUT);
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
this.TIMEOUT = process.env.CUCUMBER_TIMEOUT && parseInt(process.env.CUCUMBER_TIMEOUT) || 3000;
this.setDefaultTimeout(this.TIMEOUT);
this.ROOT_FOLDER = process.cwd();
this.OSM_USER = 'osrm';
this.OSM_GENERATOR = 'osrm-test';
@@ -25,8 +24,6 @@ module.exports = function () {
this.BIN_PATH = path.resolve(this.ROOT_FOLDER, 'build');
this.DEFAULT_INPUT_FORMAT = 'osm';
this.DEFAULT_ORIGIN = [1,1];
this.LAUNCH_TIMEOUT = 1000;
this.SHUTDOWN_TIMEOUT = 10000;
this.DEFAULT_LOAD_METHOD = 'datastore';
this.OSRM_ROUTED_LOG_FILE = path.resolve(this.TEST_FOLDER, 'osrm-routed.log');
this.ERROR_LOG_FILE = path.resolve(this.TEST_FOLDER, 'error.log');
@@ -51,26 +48,6 @@ module.exports = function () {
console.info(util.format('Node Version', process.version));
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** PLease upgrade to Node 4.+ to run OSRM cucumber tests');
if (process.env.OSRM_PORT) {
this.OSRM_PORT = parseInt(process.env.OSRM_PORT);
// eslint-disable-next-line no-console
console.info(util.format('Port set to %d', this.OSRM_PORT));
} else {
this.OSRM_PORT = this.DEFAULT_PORT;
// eslint-disable-next-line no-console
console.info(util.format('Using default port %d', this.OSRM_PORT));
}
if (process.env.OSRM_TIMEOUT) {
this.OSRM_TIMEOUT = parseInt(process.env.OSRM_TIMEOUT);
// eslint-disable-next-line no-console
console.info(util.format('Timeout set to %d', this.OSRM_TIMEOUT));
} else {
this.OSRM_TIMEOUT = this.DEFAULT_TIMEOUT;
// eslint-disable-next-line no-console
console.info(util.format('Using default timeout %d', this.OSRM_TIMEOUT));
}
fs.exists(this.TEST_FOLDER, (exists) => {
if (!exists) throw new Error(util.format('*** Test folder %s doesn\'t exist.', this.TEST_FOLDER));
callback();
+6 -4
View File
@@ -24,10 +24,12 @@ module.exports = function () {
});
this.After((scenario, callback) => {
this.setExtractArgs('');
this.setContractArgs('');
if (this.loadMethod === 'directly' && !!this.OSRMLoader.loader) this.OSRMLoader.shutdown(callback);
else callback();
this.setExtractArgs('', () => {
this.setContractArgs('', () => {
if (this.loadMethod === 'directly' && !!this.OSRMLoader.loader) this.OSRMLoader.shutdown(callback);
else callback();
});
});
});
this.Around('@stress', (scenario, callback) => {
+1 -1
View File
@@ -20,7 +20,7 @@ module.exports = function () {
};
this.sendRequest = (baseUri, parameters, callback) => {
var limit = Timeout(this.OSRM_TIMEOUT, { err: { statusCode: 408 } });
var limit = Timeout(this.TIMEOUT, { err: { statusCode: 408 } });
var runRequest = (cb) => {
var params = this.paramsToString(parameters);
+2 -2
View File
@@ -12,7 +12,7 @@ var OSRMBaseLoader = class {
}
launch (callback) {
var limit = Timeout(this.scope.LAUNCH_TIMEOUT, { err: this.scope.RoutedError('Launching osrm-routed timed out.') });
var limit = Timeout(this.scope.TIMEOUT, { err: this.scope.RoutedError('Launching osrm-routed timed out.') });
var runLaunch = (cb) => {
this.osrmUp(() => {
@@ -24,7 +24,7 @@ var OSRMBaseLoader = class {
}
shutdown (callback) {
var limit = Timeout(this.scope.SHUTDOWN_TIMEOUT, { err: this.scope.RoutedError('Shutting down osrm-routed timed out.')});
var limit = Timeout(this.scope.TIMEOUT, { err: this.scope.RoutedError('Shutting down osrm-routed timed out.')});
var runShutdown = (cb) => {
this.osrmDown(cb);
+36 -2
View File
@@ -15,7 +15,7 @@ module.exports = function () {
this.requestUrl = (path, callback) => {
var uri = this.query = [this.HOST, path].join('/'),
limit = Timeout(this.OSRM_TIMEOUT, { err: { statusCode: 408 } });
limit = Timeout(this.TIMEOUT, { err: { statusCode: 408 } });
function runRequest (cb) {
request(uri, cb);
@@ -127,12 +127,28 @@ module.exports = function () {
}
};
this.summary = (instructions) => {
if (instructions) {
return instructions.legs.map(l => l.summary).join(',');
}
};
this.wayList = (instructions) => {
return this.extractInstructionList(instructions, s => s.name);
};
this.bearingList = (instructions) => {
return this.extractInstructionList(instructions, s => s.maneuver.bearing_after);
return this.extractInstructionList(instructions, s => s.maneuver.bearing_before + '->' + s.maneuver.bearing_after);
};
this.annotationList = (instructions) => {
// Pull out all the distinct segment distances, skipping the arrive
// instructions, and the leading 0 on all timestamps arrays.
var pairs = [];
for (var i in instructions.annotation.duration) {
pairs.push(instructions.annotation.duration[i]+':'+instructions.annotation.distance[i]);
}
return pairs.join(',');
};
this.turnList = (instructions) => {
@@ -142,6 +158,9 @@ module.exports = function () {
case 'depart':
case 'arrive':
return v.maneuver.type;
case 'on ramp':
case 'off ramp':
return v.maneuver.type + ' ' + v.maneuver.modifier;
case 'roundabout':
return 'roundabout-exit-' + v.maneuver.exit;
case 'rotary':
@@ -149,6 +168,8 @@ module.exports = function () {
return v.rotary_name + '-exit-' + v.maneuver.exit;
else
return 'rotary-exit-' + v.maneuver.exit;
case 'roundabout turn':
return v.maneuver.type + ' ' + v.maneuver.modifier + ' exit-' + v.maneuver.exit;
// FIXME this is a little bit over-simplistic for merge/fork instructions
default:
return v.maneuver.type + ' ' + v.maneuver.modifier;
@@ -157,6 +178,19 @@ module.exports = function () {
.join(',');
};
this.intersectionList = (instructions) => {
return instructions.legs.reduce((m, v) => m.concat(v.steps), [])
.map( v => {
return v.intersections
.map( intersection => {
var string = intersection.entry[0]+':'+intersection.bearings[0], i;
for( i = 1; i < intersection.bearings.length; ++i )
string = string + ' ' + intersection.entry[i]+':'+intersection.bearings[i];
return string;
}).join(',');
}).join(';');
};
this.modeList = (instructions) => {
return this.extractInstructionList(instructions, s => s.mode);
};
+11 -1
View File
@@ -31,7 +31,7 @@ module.exports = function () {
var afterRequest = (err, res, body) => {
if (err) return cb(err);
if (body && body.length) {
var instructions, bearings, turns, modes, times, distances;
var instructions, bearings, turns, modes, times, distances, summary, intersections;
var json = JSON.parse(body);
@@ -41,9 +41,11 @@ module.exports = function () {
instructions = this.wayList(json.routes[0]);
bearings = this.bearingList(json.routes[0]);
turns = this.turnList(json.routes[0]);
intersections = this.intersectionList(json.routes[0]);
modes = this.modeList(json.routes[0]);
times = this.timeList(json.routes[0]);
distances = this.distanceList(json.routes[0]);
summary = this.summary(json.routes[0]);
}
if (headers.has('status')) {
@@ -66,6 +68,10 @@ module.exports = function () {
if (headers.has('route')) {
got.route = (instructions || '').trim();
if (headers.has('summary')) {
got.summary = (summary || '').trim();
}
if (headers.has('alternative')) {
// TODO examine more than first alternative?
got.alternative ='';
@@ -103,6 +109,10 @@ module.exports = function () {
}
}
if (headers.has('intersections')) {
got.intersections = (intersections || '').trim();
}
var putValue = (key, value) => {
if (headers.has(key)) got[key] = instructions ? value : '';
};
+73 -73
View File
@@ -14,8 +14,8 @@ Feature: Compass bearing
| ab |
When I route I should get
| from | to | route | bearing |
| a | b | ab,ab | 315,0 |
| from | to | route | bearing |
| a | b | ab,ab | 0->315,315->0|
Scenario: Bearing when going west
Given the node map
@@ -26,8 +26,8 @@ Feature: Compass bearing
| ab |
When I route I should get
| from | to | route | bearing |
| a | b | ab,ab | 270,0 |
| from | to | route | bearing |
| a | b | ab,ab | 0->270,270->0|
Scenario: Bearing af 45 degree intervals
Given the node map
@@ -48,14 +48,14 @@ Feature: Compass bearing
When I route I should get
| from | to | route | bearing |
| x | a | xa,xa | 0,0 |
| x | b | xb,xb | 315,0 |
| x | c | xc,xc | 270,0 |
| x | d | xd,xd | 225,0 |
| x | e | xe,xe | 180,0 |
| x | f | xf,xf | 135,0 |
| x | g | xg,xg | 90,0 |
| x | h | xh,xh | 45,0 |
| x | a | xa,xa | 0->0,0->0|
| x | b | xb,xb | 0->315,315->0|
| x | c | xc,xc | 0->270,270->0|
| x | d | xd,xd | 0->225,225->0|
| x | e | xe,xe | 0->180,180->0|
| x | f | xf,xf | 0->135,135->0|
| x | g | xg,xg | 0->90,90->0|
| x | h | xh,xh | 0->45,45->0|
Scenario: Bearing in a roundabout
Given the node map
@@ -76,9 +76,9 @@ Feature: Compass bearing
| ha | yes |
When I route I should get
| from | to | route | bearing |
| c | b | cd,de,ef,fg,gh,ha,ab,ab | 270,225,180,135,90,45,0,0 |
| g | f | gh,ha,ab,bc,cd,de,ef,ef | 90,45,0,315,270,225,180,0 |
| from | to | route | bearing |
| c | b | cd,de,ef,fg,gh,ha,ab,ab | 0->270,270->225,225->180,180->135,135->90,90->45,45->0,0->0 |
| g | f | gh,ha,ab,bc,cd,de,ef,ef | 0->90,90->45,45->0,0->315,315->270,270->225,225->180,180->0 |
Scenario: Bearing should stay constant when zig-zagging
Given the node map
@@ -97,7 +97,7 @@ Feature: Compass bearing
When I route I should get
| from | to | route | bearing |
| a | h | ab,bc,cd,de,ef,fg,gh,gh | 0,135,0,135,0,135,0,0 |
| a | h | ab,bc,cd,de,ef,fg,gh,gh | 0->0,0->135,135->0,0->135,135->0,0->135,135->0,0->0 |
Scenario: Bearings on an east-west way.
Given the node map
@@ -108,37 +108,37 @@ Feature: Compass bearing
| abcdef |
When I route I should get
| from | to | route | bearing |
| a | b | abcdef,abcdef | 90,0 |
| a | c | abcdef,abcdef | 90,0 |
| a | d | abcdef,abcdef | 90,0 |
| a | e | abcdef,abcdef | 90,0 |
| a | f | abcdef,abcdef | 90,0 |
| b | a | abcdef,abcdef | 270,0 |
| b | c | abcdef,abcdef | 90,0 |
| b | d | abcdef,abcdef | 90,0 |
| b | e | abcdef,abcdef | 90,0 |
| b | f | abcdef,abcdef | 90,0 |
| c | a | abcdef,abcdef | 270,0 |
| c | b | abcdef,abcdef | 270,0 |
| c | d | abcdef,abcdef | 90,0 |
| c | e | abcdef,abcdef | 90,0 |
| c | f | abcdef,abcdef | 90,0 |
| d | a | abcdef,abcdef | 270,0 |
| d | b | abcdef,abcdef | 270,0 |
| d | c | abcdef,abcdef | 270,0 |
| d | e | abcdef,abcdef | 90,0 |
| d | f | abcdef,abcdef | 90,0 |
| e | a | abcdef,abcdef | 270,0 |
| e | b | abcdef,abcdef | 270,0 |
| e | c | abcdef,abcdef | 270,0 |
| e | d | abcdef,abcdef | 270,0 |
| e | f | abcdef,abcdef | 90,0 |
| f | a | abcdef,abcdef | 270,0 |
| f | b | abcdef,abcdef | 270,0 |
| f | c | abcdef,abcdef | 270,0 |
| f | d | abcdef,abcdef | 270,0 |
| f | e | abcdef,abcdef | 270,0 |
| from | to | route | bearing |
| a | b | abcdef,abcdef | 0->90,90->0 |
| a | c | abcdef,abcdef | 0->90,90->0 |
| a | d | abcdef,abcdef | 0->90,90->0 |
| a | e | abcdef,abcdef | 0->90,90->0 |
| a | f | abcdef,abcdef | 0->90,90->0 |
| b | a | abcdef,abcdef | 0->270,270->0 |
| b | c | abcdef,abcdef | 0->90,90->0 |
| b | d | abcdef,abcdef | 0->90,90->0 |
| b | e | abcdef,abcdef | 0->90,90->0 |
| b | f | abcdef,abcdef | 0->90,90->0 |
| c | a | abcdef,abcdef | 0->270,270->0 |
| c | b | abcdef,abcdef | 0->270,270->0 |
| c | d | abcdef,abcdef | 0->90,90->0 |
| c | e | abcdef,abcdef | 0->90,90->0 |
| c | f | abcdef,abcdef | 0->90,90->0 |
| d | a | abcdef,abcdef | 0->270,270->0 |
| d | b | abcdef,abcdef | 0->270,270->0 |
| d | c | abcdef,abcdef | 0->270,270->0 |
| d | e | abcdef,abcdef | 0->90,90->0 |
| d | f | abcdef,abcdef | 0->90,90->0 |
| e | a | abcdef,abcdef | 0->270,270->0 |
| e | b | abcdef,abcdef | 0->270,270->0 |
| e | c | abcdef,abcdef | 0->270,270->0 |
| e | d | abcdef,abcdef | 0->270,270->0 |
| e | f | abcdef,abcdef | 0->90,90->0 |
| f | a | abcdef,abcdef | 0->270,270->0 |
| f | b | abcdef,abcdef | 0->270,270->0 |
| f | c | abcdef,abcdef | 0->270,270->0 |
| f | d | abcdef,abcdef | 0->270,270->0 |
| f | e | abcdef,abcdef | 0->270,270->0 |
Scenario: Bearings at high latitudes
# The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html,
@@ -161,19 +161,19 @@ Feature: Compass bearing
| bd |
When I route I should get
| from | to | route | bearing |
| a | b | ab,ab | 0,0 |
| b | c | bc,bc | 90,0 |
| c | d | cd,cd | 180,0 |
| d | a | da,da | 270,0 |
| b | a | ab,ab | 180,0 |
| c | b | bc,bc | 270,0 |
| d | c | cd,cd | 0,0 |
| a | d | da,da | 90,0 |
| a | c | ac,ac | 45,0 |
| c | a | ac,ac | 225,0 |
| b | d | bd,bd | 135,0 |
| d | b | bd,bd | 315,0 |
| from | to | route | bearing |
| a | b | ab,ab | 0->0,0->0 |
| b | c | bc,bc | 0->90,90->0 |
| c | d | cd,cd | 0->180,180->0 |
| d | a | da,da | 0->270,270->0 |
| b | a | ab,ab | 0->180,180->0 |
| c | b | bc,bc | 0->270,270->0 |
| d | c | cd,cd | 0->0,0->0 |
| a | d | da,da | 0->90,90->0 |
| a | c | ac,ac | 0->45,45->0 |
| c | a | ac,ac | 0->225,225->0 |
| b | d | bd,bd | 0->135,135->0 |
| d | b | bd,bd | 0->315,315->0 |
Scenario: Bearings at high negative latitudes
# The coordinas below was calculated using http://www.movable-type.co.uk/scripts/latlong.html,
@@ -196,16 +196,16 @@ Feature: Compass bearing
| bd |
When I route I should get
| from | to | route | bearing |
| a | b | ab,ab | 180,0 |
| b | c | bc,bc | 90,0 |
| c | d | cd,cd | 0,0 |
| d | a | da,da | 270,0 |
| b | a | ab,ab | 0,0 |
| c | b | bc,bc | 270,0 |
| d | c | cd,cd | 180,0 |
| a | d | da,da | 90,0 |
| a | c | ac,ac | 135,0 |
| c | a | ac,ac | 315,0 |
| b | d | bd,bd | 45,0 |
| d | b | bd,bd | 225,0 |
| from | to | route | bearing |
| a | b | ab,ab | 0->180,180->0 |
| b | c | bc,bc | 0->90,90->0 |
| c | d | cd,cd | 0->0,0->0 |
| d | a | da,da | 0->270,270->0 |
| b | a | ab,ab | 0->0,0->0 |
| c | b | bc,bc | 0->270,270->0 |
| d | c | cd,cd | 0->180,180->0 |
| a | d | da,da | 0->90,90->0 |
| a | c | ac,ac | 0->135,135->0 |
| c | a | ac,ac | 0->315,315->0 |
| b | d | bd,bd | 0->45,45->0 |
| d | b | bd,bd | 0->225,225->0 |
+20 -20
View File
@@ -15,11 +15,11 @@ Feature: Bearing parameter
When I route I should get
| from | to | bearings | route | bearing |
| b | c | 90 90 | ad,ad | 90,0 |
| b | c | 90 90 | ad,ad | 0->90,90->0|
| b | c | 180 90 | | |
| b | c | 80 100 | ad,ad | 90,0 |
| b | c | 80 100 | ad,ad | 0->90,90->0|
| b | c | 79 100 | | |
| b | c | 79,11 100 | ad,ad | 90,0 |
| b | c | 79,11 100 | ad,ad | 0->90,90->0|
Scenario: Testbot - Intial bearing in simple case
Given the node map
@@ -35,10 +35,10 @@ Feature: Bearing parameter
When I route I should get
| from | to | bearings | route | bearing |
| 0 | c | 0 0 | | |
| 0 | c | 45 45 | bc,bc | 45 ~3% |
| 0 | c | 45 45 | bc,bc | 0->44,44->0 +- 1|
| 0 | c | 85 85 | | |
| 0 | c | 95 95 | | |
| 0 | c | 135 135 | ac,ac | 135 ~1% |
| 0 | c | 135 135 | ac,ac | 0->135,135->0 +- 1|
| 0 | c | 180 180 | | |
Scenario: Testbot - Initial bearing on split way
@@ -55,19 +55,19 @@ Feature: Bearing parameter
When I route I should get
| from | to | bearings | route | bearing |
| 0 | b | 10 10 | bc,bc | 0,0 |
| 0 | b | 90 90 | ab,ab | 90,0 |
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
# The returned bearing is wrong here, it's based on the snapped
# coordinates, not the acutal edge bearing. This should be
# fixed one day, but it's only a problem when we snap two vias
# to the same point - DP
#| 0 | b | 170 170 | da | 180 |
#| 0 | b | 189 189 | da | 180 |
| 0 | 1 | 90 270 | ab,bc,cd,cd | 90,0,270,0 |
| 1 | d | 10 10 | bc,bc | 0,0 |
| 1 | d | 90 90 | ab,bc,cd,da,da | 90,0,270,180,0 |
| 1 | 0 | 189 189 | da,da | 180,0 |
| 1 | d | 270 270 | cd,cd | 270,0 |
| 0 | 1 | 90 270 | ab,bc,cd,cd | 0->90,90->0,0->270,270->0 |
| 1 | d | 10 10 | bc,bc | 0->0,0->0 |
| 1 | d | 90 90 | ab,bc,cd,da,da | 0->90,90->0,0->270,270->180,180->0 |
| 1 | 0 | 189 189 | da,da | 0->180,180->0 |
| 1 | d | 270 270 | cd,cd | 0->270,270->0 |
| 1 | d | 349 349 | | |
Scenario: Testbot - Initial bearing in all direction
@@ -101,11 +101,11 @@ Feature: Bearing parameter
When I route I should get
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ab,bc,cd,de,ef,fg,gh,ha,ha | 0,90,180,180,270,270,0,0,90,0 |
| 0 | a | 45 90 | jb,bc,cd,de,ef,fg,gh,ha,ha | 45,180,180,270,270,0,0,90,0 |
| 0 | q | 90 90 | kc,cd,de,ef,fg,gh,ha,ha | 90,180,270,270,0,0,90,0 |
| 0 | a | 135 90 | ld,de,ef,fg,gh,ha,ha | 135,270,270,0,0,90,0 |
| 0 | a | 180 90 | me,ef,fg,gh,ha,ha | 180,270,0,0,90,0 |
| 0 | a | 225 90 | nf,fg,gh,ha,ha | 225,0,0,90,0 |
| 0 | a | 270 90 | og,gh,ha,ha | 270,0,90,0 |
| 0 | a | 315 90 | ph,ha,ha | 315,90,0 |
| 0 | q | 0 90 | ia,ab,bc,cd,de,ef,fg,gh,ha,ha | 0->0,0->90,90->180,180->180,180->270,270->270,270->0,0->0,0->90,90->0 |
| 0 | a | 45 90 | jb,bc,cd,de,ef,fg,gh,ha,ha | 0->45,45->180,180->180,180->270,270->270,270->0,0->0,0->90,90->0 |
| 0 | q | 90 90 | kc,cd,de,ef,fg,gh,ha,ha | 0->90,90->180,180->270,270->270,270->0,0->0,0->90,90->0 |
| 0 | a | 135 90 | ld,de,ef,fg,gh,ha,ha | 0->135,135->270,270->270,270->0,0->0,0->90,90->0 |
| 0 | a | 180 90 | me,ef,fg,gh,ha,ha | 0->180,180->270,270->0,0->0,0->90,90->0 |
| 0 | a | 225 90 | nf,fg,gh,ha,ha | 0->225,225->0,0->0,0->90,90->0 |
| 0 | a | 270 90 | og,gh,ha,ha | 0->270,270->0,0->90,90->0 |
| 0 | a | 315 90 | ph,ha,ha | 0->315,315->90,90->0 |
+2 -2
View File
@@ -18,5 +18,5 @@ Feature: Geometry Compression
When I route I should get
| from | to | route | distance | speed |
| b | e | abcdef,abcdef | 589m | 36 km/h |
| e | b | abcdef,abcdef | 589m | 36 km/h |
| b | e | abcdef,abcdef | 588.8m | 36 km/h |
| e | b | abcdef,abcdef | 588.8m | 36 km/h |
@@ -0,0 +1,92 @@
@routing @continue_straight @via @testbot
Feature: U-turns at via points
Background:
Given the profile "testbot"
Scenario: Continue straight at waypoints enabled by default
Given the node map
| a | b | c | d |
| | e | f | g |
And the ways
| nodes |
| ab |
| bc |
| cd |
| be |
| dg |
| ef |
| fg |
When I route I should get
| waypoints | route |
| a,e,c | ab,be,be,ef,fg,dg,cd,cd |
Scenario: Query parameter to disallow changing direction at all waypoints
Given the node map
| a | b | c | d |
| | e | f | g |
And the query options
| continue_straight | false |
And the ways
| nodes |
| ab |
| bc |
| cd |
| be |
| dg |
| ef |
| fg |
When I route I should get
| waypoints | route |
| a,e,c | ab,be,be,be,bc,bc |
Scenario: Instructions at waypoints at u-turns
Given the node map
| a | b | c | d |
| | e | f | g |
And the query options
| continue_straight | false |
And the ways
| nodes |
| ab |
| bc |
| cd |
| be |
| dg |
| ef |
| fg |
When I route I should get
| waypoints | route |
| a,e,c | ab,be,be,be,bc,bc |
Scenario: u-turn mixed with non-uturn vias
Given the node map
| a | 1 | b | 3 | c | 5 | d |
| | | 2 | | | | 4 |
| | | e | | f | | g |
And the query options
| continue_straight | false |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cd | no |
| be | yes |
| dg | no |
| ef | no |
| fg | no |
When I route I should get
| waypoints | route |
| 1,2,3,4,5 | ab,be,be,be,ef,fg,dg,cd,bc,bc,bc,cd,dg,dg,dg,cd,cd |
+15
View File
@@ -104,3 +104,18 @@ Feature: Basic Map Matching
| trace | matchings |
| dcba | hg,gf,fe |
| efgh | ab,bc,cd |
Scenario: Testbot - Duration details
Given the node map
| a | b | c | d | e | | g | h |
| | | i | | | | | |
And the ways
| nodes | oneway |
| abcdegh | no |
| ci | no |
When I match I should get
| trace | matchings | annotation |
| abeh | abcedgh | 1:9.897633,0:0,1:10.008842,1:10.008842,1:10.008842,0:0,2:20.017685,1:10.008842 |
| abci | abc,ci | 1:9.897633,0:0,1:10.008842,0:0.111209,1:10.010367 |
+3 -10
View File
@@ -12,7 +12,6 @@ Feature: Testbot - Travel mode
Background:
Given the profile "testbot"
@mokob @2166
Scenario: Testbot - Always announce mode change
Given the node map
| a | b | c | d |
@@ -28,7 +27,6 @@ Feature: Testbot - Travel mode
| a | d | foo,foo,foo,foo | driving,river downstream,driving,driving |
| b | d | foo,foo,foo | river downstream,driving,driving |
@mokob @2166
Scenario: Testbot - Compressed Modes
Given the node map
| a | b | c | d | e | f | g |
@@ -44,7 +42,6 @@ Feature: Testbot - Travel mode
| a | g | road,liquid,solid,solid | driving,river downstream,driving,driving |
| c | g | liquid,solid,solid | river downstream,driving,driving |
@mokob @2166
Scenario: Testbot - Modes in each direction, different forward/backward speeds
Given the node map
| | 0 | 1 | |
@@ -79,7 +76,7 @@ Feature: Testbot - Travel mode
| 0 | 1 | ab,ab | steps down,steps down | 60s +-1 |
| 1 | 0 | ab,ab | steps up,steps up | 60s +-1 |
@oneway @mokob @2166
@oneway
Scenario: Testbot - Modes for oneway, different forward/backward speeds
Given the node map
| a | b |
@@ -107,7 +104,7 @@ Feature: Testbot - Travel mode
| a | b | ab,ab | steps down,steps down |
| b | a | | |
@oneway @mokob @2166
@oneway
Scenario: Testbot - Modes for reverse oneway, different forward/backward speeds
Given the node map
| a | b |
@@ -135,7 +132,7 @@ Feature: Testbot - Travel mode
| a | b | | |
| b | a | ab,ab | steps up,steps up |
@via @mokob @2166
@via
Scenario: Testbot - Mode should be set at via points
Given the node map
| a | 1 | b |
@@ -149,7 +146,6 @@ Feature: Testbot - Travel mode
| a,1,b | ab,ab,ab,ab | river downstream,river downstream,river downstream,river downstream |
| b,1,a | ab,ab,ab,ab | river upstream,river upstream,river upstream,river upstream |
@mokob @2166
Scenario: Testbot - Starting at a tricky node
Given the node map
| | a | | | |
@@ -164,7 +160,6 @@ Feature: Testbot - Travel mode
| from | to | route | modes |
| b | a | ab,ab | river upstream,river upstream |
@mokob @2166
Scenario: Testbot - Mode changes on straight way without name change
Given the node map
| a | 1 | b | 2 | c |
@@ -204,7 +199,6 @@ Feature: Testbot - Travel mode
| b | d | bc,cd,cd | route,driving,driving |
| a | f | ab,bc,cd,de,ef,ef | driving,route,driving,driving,driving,driving |
@mokob @2166
Scenario: Testbot - Modes, triangle map
Given the node map
| | | | | | | d |
@@ -239,7 +233,6 @@ Feature: Testbot - Travel mode
| a | d | abc,cd,cd | driving,driving,driving |
| d | a | de,ce,abc,abc | driving,river upstream,driving,driving |
@mokob @2166
Scenario: Testbot - River in the middle
Given the node map
| a | b | c | | |
+6 -6
View File
@@ -24,12 +24,12 @@ Feature: Projection to nearest point on road
Scenario: Projection onto way at high latitudes, 1km distance
When I route I should get
| from | to | route | bearing | distance |
| b | a | abc,abc | 225,0 +-1 | 1000m +- 7 |
| b | c | abc,abc | 45,0 +-1 | 1000m +- 7 |
| a | d | abc,abc | 45,0 +-1 | 1000m +- 7 |
| d | a | abc,abc | 225,0 +-1 | 1000m +- 7 |
| c | d | abc,abc | 225,0 +-1 | 1000m +- 8 |
| d | c | abc,abc | 45 +-1 | 1000m +- 8 |
| b | a | abc,abc | 0->225,225->0 | 1000m +- 7 |
| b | c | abc,abc | 0->45,45->0 | 1000m +- 7 |
| a | d | abc,abc | 0->45,45->0 | 1000m +- 7 |
| d | a | abc,abc | 0->225,225->0 | 1000m +- 7 |
| c | d | abc,abc | 0->225,224->0 | 1000m +- 8 |
| d | c | abc,abc | 0->44,45->0 | 1000m +- 8 |
Scenario: Projection onto way at high latitudes, no distance
When I route I should get
+9 -9
View File
@@ -55,13 +55,13 @@ Feature: Status messages
| ? | 400 | URL string malformed close to position 1: "/?" |
| route/v1/driving | 400 | URL string malformed close to position 17: "ing" |
| route/v1/driving/ | 400 | URL string malformed close to position 18: "ng/" |
| route/v1/driving/1 | 400 | Query string malformed close to position 1 |
| route/v1/driving/1 | 400 | Query string malformed close to position 19 |
| route/v1/driving/1,1 | 400 | Number of coordinates needs to be at least two. |
| route/v1/driving/1,1,1 | 400 | Query string malformed close to position 3 |
| route/v1/driving/x | 400 | Query string malformed close to position 0 |
| route/v1/driving/x,y | 400 | Query string malformed close to position 0 |
| route/v1/driving/1,1; | 400 | Query string malformed close to position 3 |
| route/v1/driving/1,1;1 | 400 | Query string malformed close to position 5 |
| route/v1/driving/1,1;1,1,1 | 400 | Query string malformed close to position 7 |
| route/v1/driving/1,1;x | 400 | Query string malformed close to position 3 |
| route/v1/driving/1,1;x,y | 400 | Query string malformed close to position 3 |
| route/v1/driving/1,1,1 | 400 | Query string malformed close to position 21 |
| route/v1/driving/x | 400 | Query string malformed close to position 18 |
| route/v1/driving/x,y | 400 | Query string malformed close to position 18 |
| route/v1/driving/1,1; | 400 | Query string malformed close to position 21 |
| route/v1/driving/1,1;1 | 400 | Query string malformed close to position 23 |
| route/v1/driving/1,1;1,1,1 | 400 | Query string malformed close to position 25 |
| route/v1/driving/1,1;x | 400 | Query string malformed close to position 21 |
| route/v1/driving/1,1;x,y | 400 | Query string malformed close to position 21 |
+77
View File
@@ -0,0 +1,77 @@
@routing @basic @testbot
Feature: Basic Routing
Background:
Given the profile "testbot"
@smallest
Scenario: Checking
Given the node map
| a | b | | c | d | e |
And the ways
| nodes |
| ab |
| bc |
| cd |
| de |
When I route I should get
| from | to | route | summary |
| a | e | ab,bc,cd,de,de | ab, bc |
| e | a | de,cd,bc,ab,ab | de, bc |
| a | b | ab,ab | ab |
| b | d | bc,cd,cd | bc, cd |
@smallest
Scenario: Check handling empty values
Given the node map
| a | b | | c | | d | f |
| | | | | | e |
And the ways
| nodes | name |
| ab | ab |
| bc | bc |
| cd | |
| de | de |
| df | df |
When I route I should get
| from | to | route | summary |
| e | a | de,,bc,ab,ab | de, bc |
@smallest @todo
Scenario: Summaries when routing on a simple network
Given the node map
| a | b |
And the ways
| nodes |
| ab |
When I route I should get
| from | to | route | summary |
| a | b | ab,ab | ab |
| b | a | ab,ab | ab |
@repeated
Scenario: Check handling empty values
Given the node map
| f | | | x | | |
| b | c | d | e | 1 | g |
| a | | | y | | |
And the ways
| nodes | name | # |
| ab | first | |
| bc | first | |
| cd | first | |
| deg | second | |
| bf | third | |
| xey | cross |we need this because phantom node segments are not considered for the summary |
When I route I should get
| from | to | route | summary |
| a | 1 | first,first,second,second | first, second |
@@ -0,0 +1,37 @@
@routing @speed @traffic
Feature: Traffic - turn penalties applied to turn onto which a phantom node snaps
Background: Simple map with phantom nodes
Given the node map
| | 1 | | 2 | | 3 | |
| a:1 | | b:2 | | c:3 | | d:4 |
| | | | | | | |
| | | e:5 | | f:6 | | g:7 |
And the ways
| nodes | highway |
| ab | primary |
| bc | primary |
| cd | primary |
| be | primary |
| cf | primary |
| dg | primary |
And the profile "testbot"
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
Given the turn penalty file
"""
1,2,5,0
3,4,7,-20
"""
And the contract extra arguments "--turn-penalty-file penalties.csv"
When I route I should get
| from | to | route | speed | time |
| a | e | ab,be,be | 36 km/h | 40s +-1 |
| 1 | e | ab,be,be | 36 km/h | 30s +-1 |
| b | f | bc,cf,cf | 36 km/h | 40s +-1 |
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 |
| c | g | cd,dg,dg | 71 km/h | 20s +-1 |
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 |
+41 -1
View File
@@ -46,7 +46,6 @@ Feature: Via points
| a,d,c | abc,bd,bd,bd,abc,abc |
| c,d,a | abc,bd,bd,bd,abc,abc |
@mokob
Scenario: Multiple via points
Given the node map
| a | | | | e | f | g | |
@@ -149,6 +148,47 @@ Feature: Via points
| a,d,c | abc,bd,bd,bd,abc,abc |
| c,d,a | abc,bd,bd,bd,abc,abc |
# See issue #2349
Scenario: Via point at a dead end with oneway
Given the node map
| a | b | c |
| | d | |
| | e | |
And the ways
| nodes | oneway |
| abc | no |
| bd | no |
| ed | yes |
When I route I should get
| waypoints | route |
| a,d,c | abc,bd,bd,bd,abc,abc |
| c,d,a | abc,bd,bd,bd,abc,abc |
# See issue #2349
@bug
Scenario: Via point at a dead end with oneway
Given the node map
| a | b | c |
| | d | |
| | e | g |
| | f | |
And the ways
| nodes | oneway |
| abc | no |
| bd | no |
| ed | yes |
| dg | yes |
| ef | no |
| fg | yes |
When I route I should get
| waypoints | route |
| a,d,c | abc,bd,bd,bd,abc,abc |
| c,d,a | abc,bd,bd,bd,abc,abc |
# See issue #1896
Scenario: Via point at a dead end with barrier
Given the profile "car"
+1
View File
@@ -84,6 +84,7 @@ class Contractor
const std::string &edge_segment_lookup_path,
const std::string &edge_penalty_path,
const std::vector<std::string> &segment_speed_path,
const std::vector<std::string> &turn_penalty_path,
const std::string &nodes_filename,
const std::string &geometry_filename,
const std::string &datasource_names_filename,
+1
View File
@@ -81,6 +81,7 @@ struct ContractorConfig
double core_factor;
std::vector<std::string> segment_speed_lookup_paths;
std::vector<std::string> turn_penalty_lookup_paths;
std::string datasource_indexes_path;
std::string datasource_names_path;
};
+8 -8
View File
@@ -17,9 +17,9 @@ namespace contractor
class IteratorbasedCRC32
{
public:
bool using_hardware() const { return use_hardware_implementation; }
bool UsingHardware() const { return use_hardware_implementation; }
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); }
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = DetectHardwareSupport(); }
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
{
@@ -31,11 +31,11 @@ class IteratorbasedCRC32
if (use_hardware_implementation)
{
crc = compute_in_hardware(data, sizeof(value_type));
crc = ComputeInHardware(data, sizeof(value_type));
}
else
{
crc = compute_in_software(data, sizeof(value_type));
crc = ComputeInSoftware(data, sizeof(value_type));
}
++iter;
}
@@ -43,7 +43,7 @@ class IteratorbasedCRC32
}
private:
bool detect_hardware_support() const
bool DetectHardwareSupport() const
{
static const int sse42_bit = 0x00100000;
const unsigned ecx = cpuid();
@@ -51,14 +51,14 @@ class IteratorbasedCRC32
return sse42_found;
}
unsigned compute_in_software(const char *str, unsigned len)
unsigned ComputeInSoftware(const char *str, unsigned len)
{
crc_processor.process_bytes(str, len);
return crc_processor.checksum();
}
// adapted from http://byteworm.com/2010/10/13/crc32/
unsigned compute_in_hardware(const char *str, unsigned len)
unsigned ComputeInHardware(const char *str, unsigned len)
{
#if defined(__x86_64__)
unsigned q = len / sizeof(unsigned);
@@ -114,7 +114,7 @@ struct RangebasedCRC32
return crc32(std::begin(iterable), std::end(iterable));
}
bool using_hardware() const { return crc32.using_hardware(); }
bool UsingHardware() const { return crc32.UsingHardware(); }
private:
IteratorbasedCRC32 crc32;
+15 -15
View File
@@ -115,7 +115,7 @@ class GraphContractor
{
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
inline ContractorThreadData *getThreadData()
inline ContractorThreadData *GetThreadData()
{
bool exists = false;
auto &ref = data.local(exists);
@@ -302,7 +302,7 @@ class GraphContractor
[this, &node_priorities, &node_depth,
&thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
ContractorThreadData *data = thread_data_list.GetThreadData();
for (int x = range.begin(), end = range.end(); x != end; ++x)
{
node_priorities[x] =
@@ -424,7 +424,7 @@ class GraphContractor
[this, &node_priorities, &remaining_nodes,
&thread_data_list](const tbb::blocked_range<std::size_t> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
ContractorThreadData *data = thread_data_list.GetThreadData();
// determine independent node set
for (auto i = range.begin(), end = range.end(); i != end; ++i)
{
@@ -481,7 +481,7 @@ class GraphContractor
[this, &remaining_nodes,
&thread_data_list](const tbb::blocked_range<std::size_t> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
ContractorThreadData *data = thread_data_list.GetThreadData();
for (int position = range.begin(), end = range.end();
position != end; ++position)
{
@@ -495,7 +495,7 @@ class GraphContractor
DeleteGrainSize),
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
ContractorThreadData *data = thread_data_list.GetThreadData();
for (int position = range.begin(), end = range.end(); position != end;
++position)
{
@@ -547,7 +547,7 @@ class GraphContractor
[this, &node_priorities, &remaining_nodes, &node_depth,
&thread_data_list](const tbb::blocked_range<int> &range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
ContractorThreadData *data = thread_data_list.GetThreadData();
for (int position = range.begin(), end = range.end(); position != end;
++position)
{
@@ -561,7 +561,7 @@ class GraphContractor
number_of_contracted_nodes += end_independent_nodes_idx - begin_independent_nodes_idx;
remaining_nodes.resize(begin_independent_nodes_idx);
p.printStatus(number_of_contracted_nodes);
p.PrintStatus(number_of_contracted_nodes);
++current_level;
}
@@ -627,7 +627,7 @@ class GraphContractor
Edge new_edge;
for (const auto node : util::irange(0u, number_of_nodes))
{
p.printStatus(node);
p.PrintStatus(node);
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const NodeID target = contractor_graph->GetTarget(edge);
@@ -710,9 +710,9 @@ class GraphContractor
inline void Dijkstra(const int max_distance,
const unsigned number_of_targets,
const int maxNodes,
const int max_nodes,
ContractorThreadData &data,
const NodeID middleNode)
const NodeID middle_node)
{
ContractorHeap &heap = data.heap;
@@ -723,7 +723,7 @@ class GraphContractor
{
const NodeID node = heap.DeleteMin();
const auto distance = heap.GetKey(node);
if (++nodes > maxNodes)
if (++nodes > max_nodes)
{
return;
}
@@ -742,7 +742,7 @@ class GraphContractor
}
}
RelaxNode(node, middleNode, distance, heap);
RelaxNode(node, middle_node, distance, heap);
}
}
@@ -1032,7 +1032,7 @@ class GraphContractor
}
// tie breaking
if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
bias(node, target))
Bias(node, target))
{
return false;
}
@@ -1061,7 +1061,7 @@ class GraphContractor
}
// tie breaking
if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
bias(node, target))
Bias(node, target))
{
return false;
}
@@ -1071,7 +1071,7 @@ class GraphContractor
}
// This bias function takes up 22 assembly instructions in total on X86
inline bool bias(const NodeID a, const NodeID b) const
inline bool Bias(const NodeID a, const NodeID b) const
{
const unsigned short hasha = fast_hash(a);
const unsigned short hashb = fast_hash(b);
+19 -7
View File
@@ -33,8 +33,8 @@ namespace json
namespace detail
{
std::string instructionTypeToString(extractor::guidance::TurnType type);
std::string instructionModifierToString(extractor::guidance::DirectionModifier modifier);
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
@@ -48,13 +48,25 @@ template <typename ForwardIter> util::json::String makePolyline(ForwardIter begi
}
template <typename ForwardIter>
util::json::Object makeGeoJSONLineString(ForwardIter begin, ForwardIter end)
util::json::Object makeGeoJSONGeometry(ForwardIter begin, ForwardIter end)
{
auto num_coordinates = std::distance(begin, end);
BOOST_ASSERT(num_coordinates != 0);
util::json::Object geojson;
geojson.values["type"] = "LineString";
util::json::Array coordinates;
std::transform(begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
geojson.values["coordinates"] = std::move(coordinates);
if (num_coordinates > 1)
{
geojson.values["type"] = "LineString";
util::json::Array coordinates;
std::transform(begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
geojson.values["coordinates"] = std::move(coordinates);
}
else if (num_coordinates > 0)
{
geojson.values["type"] = "Point";
util::json::Array coordinates;
coordinates.values.push_back(detail::coordinateToLonLat(*begin));
geojson.values["coordinates"] = std::move(coordinates);
}
return geojson;
}
+1
View File
@@ -52,6 +52,7 @@ struct MatchParameters : public RouteParameters
{
MatchParameters()
: RouteParameters(false,
false,
false,
RouteParameters::GeometriesType::Polyline,
RouteParameters::OverviewType::Simplified,
+30 -5
View File
@@ -69,7 +69,7 @@ class RouteAPI : public BaseAPI
}
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
return json::makeGeoJSONLineString(begin, end);
return json::makeGeoJSONGeometry(begin, end);
}
util::json::Object MakeRoute(const std::vector<PhantomNodes> &segment_end_coordinates,
@@ -93,8 +93,8 @@ class RouteAPI : public BaseAPI
auto leg_geometry = guidance::assembleGeometry(
BaseAPI::facade, path_data, phantoms.source_phantom, phantoms.target_phantom);
auto leg = guidance::assembleLeg(path_data, leg_geometry, phantoms.source_phantom,
phantoms.target_phantom, reversed_target);
auto leg = guidance::assembleLeg(facade, path_data, leg_geometry, phantoms.source_phantom,
phantoms.target_phantom, reversed_target, parameters.steps);
if (parameters.steps)
{
@@ -132,6 +132,7 @@ class RouteAPI : public BaseAPI
guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::postProcess(std::move(steps));
leg.steps = guidance::collapseTurns(std::move(leg.steps));
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom);
@@ -169,15 +170,39 @@ class RouteAPI : public BaseAPI
leg_geometry.locations.begin() + step.geometry_end));
}
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
return static_cast<util::json::Value>(json::makeGeoJSONLineString(
return static_cast<util::json::Value>(json::makeGeoJSONGeometry(
leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end));
});
}
return json::makeRoute(route,
auto result = json::makeRoute(route,
json::makeRouteLegs(std::move(legs), std::move(step_geometries)),
std::move(json_overview));
if (parameters.annotation)
{
util::json::Array durations;
util::json::Array distances;
for (const auto idx : util::irange<std::size_t>(0UL, leg_geometries.size()))
{
auto &leg_geometry = leg_geometries[idx];
std::for_each(leg_geometry.annotations.begin(),
leg_geometry.annotations.end(),
[this, &durations, &distances](const guidance::LegGeometry::Annotation &step) {
durations.values.push_back(step.duration);
distances.values.push_back(step.distance);
});
}
util::json::Object details;
details.values["distance"] = std::move(distances);
details.values["duration"] = std::move(durations);
result.values["annotation"] = std::move(details);
}
return result;
}
const RouteParameters &parameters;
+4 -1
View File
@@ -72,17 +72,20 @@ struct RouteParameters : public BaseParameters
template <typename... Args>
RouteParameters(const bool steps_,
const bool alternatives_,
const bool annotation_,
const GeometriesType geometries_,
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
geometries{geometries_}, overview{overview_}, continue_straight{continue_straight_}
annotation{annotation_}, geometries{geometries_}, overview{overview_},
continue_straight{continue_straight_}
{
}
bool steps = false;
bool alternatives = false;
bool annotation = false;
GeometriesType geometries = GeometriesType::Polyline;
OverviewType overview = OverviewType::Simplified;
boost::optional<bool> continue_straight;
+3 -3
View File
@@ -15,6 +15,9 @@
#include <boost/algorithm/string/trim.hpp>
#include <boost/range/algorithm/copy.hpp>
namespace osrm
{
// RFC 4648 "The Base16, Base32, and Base64 Data Encodings"
// See: https://tools.ietf.org/html/rfc4648
@@ -36,9 +39,6 @@ using BinaryFromBase64 = boost::archive::iterators::transform_width<
6 // from a sequence of 6 bit
>;
} // ns detail
namespace osrm
{
namespace engine
{
+27 -16
View File
@@ -3,13 +3,15 @@
// Exposes all data access interfaces to the algorithms via base class ptr
#include "extractor/edge_based_node.hpp"
#include "extractor/external_memory_node.hpp"
#include "contractor/query_edge.hpp"
#include "engine/phantom_node.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/integer_range.hpp"
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/integer_range.hpp"
#include "util/string_util.hpp"
#include "util/typedefs.hpp"
@@ -17,9 +19,9 @@
#include <cstddef>
#include <vector>
#include <utility>
#include <string>
#include <utility>
#include <vector>
namespace osrm
{
@@ -90,47 +92,47 @@ class BaseDataFacade
virtual extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0;
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) = 0;
const util::Coordinate north_east) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) = 0;
const float max_distance) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) = 0;
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) = 0;
const double max_distance) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) = 0;
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) = 0;
const double max_distance) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) = 0;
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const = 0;
virtual unsigned GetCheckSum() const = 0;
@@ -145,6 +147,15 @@ class BaseDataFacade
virtual std::string GetTimestamp() const = 0;
virtual bool GetContinueStraightDefault() const = 0;
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
virtual util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const = 0;
virtual EntryClassID GetEntryClassID(const EdgeID eid) const = 0;
virtual util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const = 0;
};
}
}
+158 -102
View File
@@ -6,20 +6,24 @@
#include "engine/datafacade/datafacade_base.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "engine/geospatial_query.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "contractor/query_edge.hpp"
#include "storage/storage_config.hpp"
#include "util/graph_loader.hpp"
#include "util/io.hpp"
#include "util/range_table.hpp"
#include "util/rectangle.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include "util/static_rtree.hpp"
#include "util/range_table.hpp"
#include "util/graph_loader.hpp"
#include "util/simple_logger.hpp"
#include "util/rectangle.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/typedefs.hpp"
#include "osrm/coordinate.hpp"
@@ -55,8 +59,8 @@ class InternalDataFacade final : public BaseDataFacade
private:
using super = BaseDataFacade;
using QueryGraph = util::StaticGraph<typename super::EdgeData>;
using InputEdge = typename QueryGraph::InputEdge;
using RTreeLeaf = typename super::RTreeLeaf;
using InputEdge = QueryGraph::InputEdge;
using RTreeLeaf = super::RTreeLeaf;
using InternalRTree =
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, false>::vector, false>;
using InternalGeospatialQuery = GeospatialQuery<InternalRTree, BaseDataFacade>;
@@ -68,7 +72,7 @@ class InternalDataFacade final : public BaseDataFacade
std::unique_ptr<QueryGraph> m_query_graph;
std::string m_timestamp;
std::shared_ptr<util::ShM<util::Coordinate, false>::vector> m_coordinate_list;
util::ShM<util::Coordinate, false>::vector m_coordinate_list;
util::ShM<NodeID, false>::vector m_via_node_list;
util::ShM<unsigned, false>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_list;
@@ -82,12 +86,24 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<std::string, false>::vector m_datasource_names;
extractor::ProfileProperties m_profile_properties;
boost::thread_specific_ptr<InternalRTree> m_static_rtree;
boost::thread_specific_ptr<InternalGeospatialQuery> m_geospatial_query;
std::unique_ptr<InternalRTree> m_static_rtree;
std::unique_ptr<InternalGeospatialQuery> m_geospatial_query;
boost::filesystem::path ram_index_path;
boost::filesystem::path file_index_path;
util::RangeTable<16, false> m_name_table;
// bearing classes by node based node
util::ShM<BearingClassID, false>::vector m_bearing_class_id_table;
// entry class IDs by edge based egde
util::ShM<EntryClassID, false>::vector m_entry_class_id_list;
// the look-up table for entry classes. An entry class lists the possibility of entry for all
// available turns. For every turn, there is an associated entry class.
util::ShM<util::guidance::EntryClass, false>::vector m_entry_class_table;
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
// at an intersection
util::RangeTable<16, false> m_bearing_ranges_table;
util::ShM<DiscreteBearing, false>::vector m_bearing_values_table;
void LoadProfileProperties(const boost::filesystem::path &properties_path)
{
boost::filesystem::ifstream in_stream(properties_path);
@@ -96,7 +112,8 @@ class InternalDataFacade final : public BaseDataFacade
throw util::exception("Could not open " + properties_path.string() + " for reading.");
}
in_stream.read(reinterpret_cast<char*>(&m_profile_properties), sizeof(m_profile_properties));
in_stream.read(reinterpret_cast<char *>(&m_profile_properties),
sizeof(m_profile_properties));
}
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
@@ -112,8 +129,8 @@ class InternalDataFacade final : public BaseDataFacade
void LoadGraph(const boost::filesystem::path &hsgr_path)
{
typename util::ShM<typename QueryGraph::NodeArrayEntry, false>::vector node_list;
typename util::ShM<typename QueryGraph::EdgeArrayEntry, false>::vector edge_list;
util::ShM<QueryGraph::NodeArrayEntry, false>::vector node_list;
util::ShM<QueryGraph::EdgeArrayEntry, false>::vector edge_list;
util::SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
@@ -138,12 +155,12 @@ class InternalDataFacade final : public BaseDataFacade
extractor::QueryNode current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
m_coordinate_list = std::make_shared<std::vector<util::Coordinate>>(number_of_coordinates);
m_coordinate_list.resize(number_of_coordinates);
for (unsigned i = 0; i < number_of_coordinates; ++i)
{
nodes_input_stream.read((char *)&current_node, sizeof(extractor::QueryNode));
m_coordinate_list->at(i) = util::Coordinate(current_node.lon, current_node.lat);
BOOST_ASSERT(m_coordinate_list->at(i).IsValid());
m_coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
BOOST_ASSERT(m_coordinate_list[i].IsValid());
}
boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
@@ -153,6 +170,7 @@ class InternalDataFacade final : public BaseDataFacade
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_entry_class_id_list.resize(number_of_edges);
extractor::OriginalEdgeData current_edge_data;
for (unsigned i = 0; i < number_of_edges; ++i)
@@ -163,6 +181,7 @@ class InternalDataFacade final : public BaseDataFacade
m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
m_travel_mode_list[i] = current_edge_data.travel_mode;
m_entry_class_id_list[i] = current_edge_data.entry_classid;
}
}
@@ -223,7 +242,8 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::ifstream datasources_stream(datasource_indexes_file, std::ios::binary);
if (!datasources_stream)
{
throw util::exception("Could not open " + datasource_indexes_file.string() + " for reading!");
throw util::exception("Could not open " + datasource_indexes_file.string() +
" for reading!");
}
BOOST_ASSERT(datasources_stream);
@@ -240,7 +260,8 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::ifstream datasourcenames_stream(datasource_names_file, std::ios::binary);
if (!datasourcenames_stream)
{
throw util::exception("Could not open " + datasource_names_file.string() + " for reading!");
throw util::exception("Could not open " + datasource_names_file.string() +
" for reading!");
}
BOOST_ASSERT(datasourcenames_stream);
std::string name;
@@ -252,7 +273,7 @@ class InternalDataFacade final : public BaseDataFacade
void LoadRTree()
{
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
m_static_rtree.reset(new InternalRTree(ram_index_path, file_index_path, m_coordinate_list));
m_geospatial_query.reset(
@@ -276,6 +297,52 @@ class InternalDataFacade final : public BaseDataFacade
}
}
void LoadIntersectionClasses(const boost::filesystem::path &intersection_class_file)
{
std::ifstream intersection_stream(intersection_class_file.string(), std::ios::binary);
if (!intersection_stream)
throw util::exception("Could not open " + intersection_class_file.string() +
" for reading.");
if (!util::readAndCheckFingerprint(intersection_stream))
throw util::exception("Fingeprint does not match in " +
intersection_class_file.string());
{
util::SimpleLogger().Write(logINFO) << "Loading Bearing Class IDs";
std::vector<BearingClassID> bearing_class_id;
if (!util::deserializeVector(intersection_stream, bearing_class_id))
throw util::exception("Reading from " + intersection_class_file.string() + " failed.");
m_bearing_class_id_table.resize(bearing_class_id.size());
std::copy(bearing_class_id.begin(), bearing_class_id.end(),
&m_bearing_class_id_table[0]);
}
{
util::SimpleLogger().Write(logINFO) << "Loading Bearing Classes";
// read the range table
intersection_stream >> m_bearing_ranges_table;
std::vector<util::guidance::BearingClass> bearing_classes;
// and the actual bearing values
std::uint64_t num_bearings;
intersection_stream >> num_bearings;
m_bearing_values_table.resize(num_bearings);
intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]),
sizeof(m_bearing_values_table[0]) * num_bearings);
if (!static_cast<bool>(intersection_stream))
throw util::exception("Reading from " + intersection_class_file.string() + " failed.");
}
{
util::SimpleLogger().Write(logINFO) << "Loading Entry Classes";
std::vector<util::guidance::EntryClass> entry_classes;
if (!util::deserializeVector(intersection_stream, entry_classes))
throw util::exception("Reading from " + intersection_class_file.string() + " failed.");
m_entry_class_table.resize(entry_classes.size());
std::copy(entry_classes.begin(), entry_classes.end(), &m_entry_class_table[0]);
}
}
public:
virtual ~InternalDataFacade()
{
@@ -283,7 +350,7 @@ class InternalDataFacade final : public BaseDataFacade
m_geospatial_query.reset();
}
explicit InternalDataFacade(const storage::StorageConfig& config)
explicit InternalDataFacade(const storage::StorageConfig &config)
{
ram_index_path = config.ram_index_path;
file_index_path = config.file_index_path;
@@ -301,8 +368,7 @@ class InternalDataFacade final : public BaseDataFacade
LoadGeometries(config.geometries_path);
util::SimpleLogger().Write() << "loading datasource info";
LoadDatasourceInfo(config.datasource_names_path,
config.datasource_indexes_path);
LoadDatasourceInfo(config.datasource_names_path, config.datasource_indexes_path);
util::SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(config.timestamp_path);
@@ -312,6 +378,12 @@ class InternalDataFacade final : public BaseDataFacade
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
util::SimpleLogger().Write() << "loading intersection class data";
LoadIntersectionClasses(config.intersection_class_path);
}
// search graph access
@@ -360,7 +432,7 @@ class InternalDataFacade final : public BaseDataFacade
// node and edge information access
util::Coordinate GetCoordinateOfNode(const unsigned id) const override final
{
return m_coordinate_list->at(id);
return m_coordinate_list[id];
}
extractor::guidance::TurnInstruction
@@ -375,13 +447,9 @@ class InternalDataFacade final : public BaseDataFacade
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) override final
const util::Coordinate north_east) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
const util::RectangleInt2D bbox{south_west.lon, north_east.lon, south_west.lat,
north_east.lat};
return m_geospatial_query->Search(bbox);
@@ -389,13 +457,9 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) override final
const float max_distance) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
}
@@ -404,13 +468,9 @@ class InternalDataFacade final : public BaseDataFacade
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance,
bearing, bearing_range);
@@ -418,13 +478,9 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results) override final
const unsigned max_results) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
}
@@ -432,13 +488,9 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
}
@@ -447,13 +499,9 @@ class InternalDataFacade final : public BaseDataFacade
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, bearing,
bearing_range);
@@ -464,40 +512,27 @@ class InternalDataFacade final : public BaseDataFacade
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance,
bearing, bearing_range);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) override final
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const double max_distance) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance);
}
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate) override final
const util::Coordinate input_coordinate) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate);
@@ -507,13 +542,9 @@ class InternalDataFacade final : public BaseDataFacade
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range);
@@ -522,13 +553,9 @@ class InternalDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range);
@@ -588,8 +615,7 @@ class InternalDataFacade final : public BaseDataFacade
result_nodes.clear();
result_nodes.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_nodes.emplace_back(edge.node_id);
});
}
@@ -604,8 +630,7 @@ class InternalDataFacade final : public BaseDataFacade
result_weights.clear();
result_weights.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_weights.emplace_back(edge.weight);
});
}
@@ -632,11 +657,9 @@ class InternalDataFacade final : public BaseDataFacade
}
else
{
std::for_each(m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id)
{
result_datasources.push_back(datasource_id);
});
std::for_each(
m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id) { result_datasources.push_back(datasource_id); });
}
}
@@ -649,7 +672,40 @@ class InternalDataFacade final : public BaseDataFacade
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetContinueStraightDefault() const override final { return m_profile_properties.continue_straight_at_waypoint; }
bool GetContinueStraightDefault() const override final
{
return m_profile_properties.continue_straight_at_waypoint;
}
BearingClassID GetBearingClassID(const NodeID nid) const override final
{
return m_bearing_class_id_table.at(nid);
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const override final
{
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
auto range = m_bearing_ranges_table.GetRange(bearing_class_id);
util::guidance::BearingClass result;
for (auto itr = m_bearing_values_table.begin() + range.front();
itr != m_bearing_values_table.begin() + range.back() + 1; ++itr)
result.add(*itr);
return result;
}
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return m_entry_class_id_list.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
return m_entry_class_table.at(entry_class_id);
}
};
}
}
+165 -132
View File
@@ -7,16 +7,20 @@
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/profile_properties.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "engine/geospatial_query.hpp"
#include "util/make_unique.hpp"
#include "util/range_table.hpp"
#include "util/rectangle.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include "util/static_rtree.hpp"
#include "util/make_unique.hpp"
#include "util/simple_logger.hpp"
#include "util/rectangle.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
@@ -29,9 +33,9 @@
#include <vector>
#include <boost/assert.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/tss.hpp>
namespace osrm
{
@@ -46,16 +50,15 @@ class SharedDataFacade final : public BaseDataFacade
private:
using super = BaseDataFacade;
using QueryGraph = util::StaticGraph<EdgeData, true>;
using GraphNode = typename QueryGraph::NodeArrayEntry;
using GraphEdge = typename QueryGraph::EdgeArrayEntry;
using NameIndexBlock = typename util::RangeTable<16, true>::BlockT;
using InputEdge = typename QueryGraph::InputEdge;
using RTreeLeaf = typename super::RTreeLeaf;
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
using IndexBlock = util::RangeTable<16, true>::BlockT;
using InputEdge = QueryGraph::InputEdge;
using RTreeLeaf = super::RTreeLeaf;
using SharedRTree =
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using TimeStampedRTreePair = std::pair<unsigned, std::shared_ptr<SharedRTree>>;
using RTreeNode = typename SharedRTree::TreeNode;
using RTreeNode = SharedRTree::TreeNode;
storage::SharedDataLayout *data_layout;
char *shared_memory;
@@ -70,9 +73,9 @@ class SharedDataFacade final : public BaseDataFacade
std::unique_ptr<storage::SharedMemory> m_layout_memory;
std::unique_ptr<storage::SharedMemory> m_large_memory;
std::string m_timestamp;
extractor::ProfileProperties* m_profile_properties;
extractor::ProfileProperties *m_profile_properties;
std::shared_ptr<util::ShM<util::Coordinate, true>::vector> m_coordinate_list;
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
util::ShM<NodeID, true>::vector m_via_node_list;
util::ShM<unsigned, true>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
@@ -88,12 +91,24 @@ class SharedDataFacade final : public BaseDataFacade
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
boost::thread_specific_ptr<std::pair<unsigned, std::shared_ptr<SharedRTree>>> m_static_rtree;
boost::thread_specific_ptr<SharedGeospatialQuery> m_geospatial_query;
std::unique_ptr<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
boost::filesystem::path file_index_path;
std::shared_ptr<util::RangeTable<16, true>> m_name_table;
// bearing classes by node based node
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
// entry class IDs
util::ShM<EntryClassID, true>::vector m_entry_class_id_list;
// the look-up table for entry classes. An entry class lists the possibility of entry for all
// available turns. Such a class id is stored with every edge.
util::ShM<util::guidance::EntryClass, true>::vector m_entry_class_table;
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
// at an intersection
std::shared_ptr<util::RangeTable<16, true>> m_bearing_ranges_table;
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
void LoadChecksum()
{
m_check_sum = *data_layout->GetBlockPtr<unsigned>(shared_memory,
@@ -103,8 +118,8 @@ class SharedDataFacade final : public BaseDataFacade
void LoadProfileProperties()
{
m_profile_properties =
data_layout->GetBlockPtr<extractor::ProfileProperties>(shared_memory, storage::SharedDataLayout::PROPERTIES);
m_profile_properties = data_layout->GetBlockPtr<extractor::ProfileProperties>(
shared_memory, storage::SharedDataLayout::PROPERTIES);
}
void LoadTimestamp()
@@ -119,17 +134,15 @@ class SharedDataFacade final : public BaseDataFacade
void LoadRTree()
{
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
auto tree_ptr = data_layout->GetBlockPtr<RTreeNode>(
shared_memory, storage::SharedDataLayout::R_SEARCH_TREE);
m_static_rtree.reset(new TimeStampedRTreePair(
CURRENT_TIMESTAMP,
util::make_unique<SharedRTree>(
tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
file_index_path, m_coordinate_list)));
m_static_rtree.reset(new SharedRTree(
tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
file_index_path, m_coordinate_list));
m_geospatial_query.reset(
new SharedGeospatialQuery(*m_static_rtree->second, m_coordinate_list, *this));
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadGraph()
@@ -140,9 +153,9 @@ class SharedDataFacade final : public BaseDataFacade
auto graph_edges_ptr = data_layout->GetBlockPtr<GraphEdge>(
shared_memory, storage::SharedDataLayout::GRAPH_EDGE_LIST);
typename util::ShM<GraphNode, true>::vector node_list(
util::ShM<GraphNode, true>::vector node_list(
graph_nodes_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_NODE_LIST]);
typename util::ShM<GraphEdge, true>::vector edge_list(
util::ShM<GraphEdge, true>::vector edge_list(
graph_edges_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_EDGE_LIST]);
m_query_graph.reset(new QueryGraph(node_list, edge_list));
}
@@ -151,37 +164,42 @@ class SharedDataFacade final : public BaseDataFacade
{
auto coordinate_list_ptr = data_layout->GetBlockPtr<util::Coordinate>(
shared_memory, storage::SharedDataLayout::COORDINATE_LIST);
m_coordinate_list = util::make_unique<util::ShM<util::Coordinate, true>::vector>(
coordinate_list_ptr,
m_coordinate_list.reset(coordinate_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
shared_memory, storage::SharedDataLayout::TRAVEL_MODE);
typename util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list);
auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
typename util::ShM<extractor::guidance::TurnInstruction, true>::vector
turn_instruction_list(
turn_instruction_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list = std::move(turn_instruction_list);
auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::NAME_ID_LIST);
typename util::ShM<unsigned, true>::vector name_id_list(
util::ShM<unsigned, true>::vector name_id_list(
name_id_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_ID_LIST]);
m_name_ID_list = std::move(name_id_list);
auto entry_class_id_list_ptr = data_layout->GetBlockPtr<EntryClassID>(
shared_memory, storage::SharedDataLayout::ENTRY_CLASSID);
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
entry_class_id_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASSID]);
m_entry_class_id_list = std::move(entry_class_id_list);
}
void LoadViaNodeList()
{
auto via_node_list_ptr = data_layout->GetBlockPtr<NodeID>(
shared_memory, storage::SharedDataLayout::VIA_NODE_LIST);
typename util::ShM<NodeID, true>::vector via_node_list(
util::ShM<NodeID, true>::vector via_node_list(
via_node_list_ptr, data_layout->num_entries[storage::SharedDataLayout::VIA_NODE_LIST]);
m_via_node_list = std::move(via_node_list);
}
@@ -190,16 +208,16 @@ class SharedDataFacade final : public BaseDataFacade
{
auto offsets_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::NAME_OFFSETS);
auto blocks_ptr = data_layout->GetBlockPtr<NameIndexBlock>(
auto blocks_ptr = data_layout->GetBlockPtr<IndexBlock>(
shared_memory, storage::SharedDataLayout::NAME_BLOCKS);
typename util::ShM<unsigned, true>::vector name_offsets(
util::ShM<unsigned, true>::vector name_offsets(
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_OFFSETS]);
typename util::ShM<NameIndexBlock, true>::vector name_blocks(
util::ShM<IndexBlock, true>::vector name_blocks(
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_BLOCKS]);
auto names_list_ptr = data_layout->GetBlockPtr<char>(
shared_memory, storage::SharedDataLayout::NAME_CHAR_LIST);
typename util::ShM<char, true>::vector names_char_list(
util::ShM<char, true>::vector names_char_list(
names_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_CHAR_LIST]);
m_name_table = util::make_unique<util::RangeTable<16, true>>(
name_offsets, name_blocks, static_cast<unsigned>(names_char_list.size()));
@@ -216,7 +234,7 @@ class SharedDataFacade final : public BaseDataFacade
auto core_marker_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::CORE_MARKER);
typename util::ShM<bool, true>::vector is_core_node(
util::ShM<bool, true>::vector is_core_node(
core_marker_ptr, data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER]);
m_is_core_node = std::move(is_core_node);
}
@@ -225,7 +243,7 @@ class SharedDataFacade final : public BaseDataFacade
{
auto geometries_index_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_INDEX);
typename util::ShM<unsigned, true>::vector geometry_begin_indices(
util::ShM<unsigned, true>::vector geometry_begin_indices(
geometries_index_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_INDEX]);
m_geometry_indices = std::move(geometry_begin_indices);
@@ -233,40 +251,74 @@ class SharedDataFacade final : public BaseDataFacade
auto geometries_list_ptr =
data_layout->GetBlockPtr<extractor::CompressedEdgeContainer::CompressedEdge>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_LIST);
typename util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector
geometry_list(geometries_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]);
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector geometry_list(
geometries_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]);
m_geometry_list = std::move(geometry_list);
auto datasources_list_ptr = data_layout->GetBlockPtr<uint8_t>(
shared_memory, storage::SharedDataLayout::DATASOURCES_LIST);
typename util::ShM<uint8_t, true>::vector datasources_list(
util::ShM<uint8_t, true>::vector datasources_list(
datasources_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::DATASOURCES_LIST]);
m_datasource_list = std::move(datasources_list);
auto datasource_name_data_ptr = data_layout->GetBlockPtr<char>(
shared_memory, storage::SharedDataLayout::DATASOURCE_NAME_DATA);
typename util::ShM<char, true>::vector datasource_name_data(
util::ShM<char, true>::vector datasource_name_data(
datasource_name_data_ptr,
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_DATA]);
m_datasource_name_data = std::move(datasource_name_data);
auto datasource_name_offsets_ptr = data_layout->GetBlockPtr<std::size_t>(
shared_memory, storage::SharedDataLayout::DATASOURCE_NAME_OFFSETS);
typename util::ShM<std::size_t, true>::vector datasource_name_offsets(
util::ShM<std::size_t, true>::vector datasource_name_offsets(
datasource_name_offsets_ptr,
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_OFFSETS]);
m_datasource_name_offsets = std::move(datasource_name_offsets);
auto datasource_name_lengths_ptr = data_layout->GetBlockPtr<std::size_t>(
shared_memory, storage::SharedDataLayout::DATASOURCE_NAME_LENGTHS);
typename util::ShM<std::size_t, true>::vector datasource_name_lengths(
util::ShM<std::size_t, true>::vector datasource_name_lengths(
datasource_name_lengths_ptr,
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_LENGTHS]);
m_datasource_name_lengths = std::move(datasource_name_lengths);
}
void LoadIntersectionClasses()
{
auto bearing_class_id_ptr = data_layout->GetBlockPtr<BearingClassID>(
shared_memory, storage::SharedDataLayout::BEARING_CLASSID);
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
bearing_class_id_ptr,
data_layout->num_entries[storage::SharedDataLayout::BEARING_CLASSID]);
m_bearing_class_id_table = std::move(bearing_class_id_table);
auto bearing_class_ptr = data_layout->GetBlockPtr<DiscreteBearing>(
shared_memory, storage::SharedDataLayout::BEARING_VALUES);
typename util::ShM<DiscreteBearing, true>::vector bearing_class_table(
bearing_class_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_VALUES]);
m_bearing_values_table = std::move(bearing_class_table);
auto offsets_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::BEARING_OFFSETS);
auto blocks_ptr = data_layout->GetBlockPtr<IndexBlock>(
shared_memory, storage::SharedDataLayout::BEARING_BLOCKS);
util::ShM<unsigned, true>::vector bearing_offsets(
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_OFFSETS]);
util::ShM<IndexBlock, true>::vector bearing_blocks(
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_BLOCKS]);
m_bearing_ranges_table = util::make_unique<util::RangeTable<16, true>>(
bearing_offsets, bearing_blocks, static_cast<unsigned>(m_bearing_values_table.size()));
auto entry_class_ptr = data_layout->GetBlockPtr<util::guidance::EntryClass>(
shared_memory, storage::SharedDataLayout::ENTRY_CLASS);
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
entry_class_ptr, data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASS]);
m_entry_class_table = std::move(entry_class_table);
}
public:
virtual ~SharedDataFacade() {}
@@ -353,15 +405,14 @@ class SharedDataFacade final : public BaseDataFacade
LoadNames();
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
LoadIntersectionClasses();
util::SimpleLogger().Write() << "number of geometries: "
<< m_coordinate_list->size();
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
<< m_coordinate_list.size();
for (unsigned i = 0; i < m_coordinate_list.size(); ++i)
{
if (!GetCoordinateOfNode(i).IsValid())
{
util::SimpleLogger().Write() << "coordinate " << i << " not valid";
}
BOOST_ASSERT(GetCoordinateOfNode(i).IsValid());
}
}
util::SimpleLogger().Write(logDEBUG) << "Releasing exclusive lock";
@@ -414,7 +465,7 @@ class SharedDataFacade final : public BaseDataFacade
// node and edge information access
util::Coordinate GetCoordinateOfNode(const NodeID id) const override final
{
return m_coordinate_list->at(id);
return m_coordinate_list[id];
}
virtual void GetUncompressedGeometry(const EdgeID id,
@@ -426,8 +477,7 @@ class SharedDataFacade final : public BaseDataFacade
result_nodes.clear();
result_nodes.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_nodes.emplace_back(edge.node_id);
});
}
@@ -442,8 +492,7 @@ class SharedDataFacade final : public BaseDataFacade
result_weights.clear();
result_weights.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_weights.emplace_back(edge.weight);
});
}
@@ -465,13 +514,9 @@ class SharedDataFacade final : public BaseDataFacade
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) override final
const util::Coordinate north_east) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
const util::RectangleInt2D bbox{south_west.lon, north_east.lon, south_west.lat,
north_east.lat};
return m_geospatial_query->Search(bbox);
@@ -479,13 +524,9 @@ class SharedDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) override final
const float max_distance) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
}
@@ -494,13 +535,9 @@ class SharedDataFacade final : public BaseDataFacade
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance,
bearing, bearing_range);
@@ -508,13 +545,9 @@ class SharedDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results) override final
const unsigned max_results) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
}
@@ -522,13 +555,9 @@ class SharedDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
}
@@ -537,13 +566,9 @@ class SharedDataFacade final : public BaseDataFacade
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, bearing,
bearing_range);
@@ -554,26 +579,18 @@ class SharedDataFacade final : public BaseDataFacade
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance,
bearing, bearing_range);
}
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate) override final
const util::Coordinate input_coordinate) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate);
@@ -581,13 +598,9 @@ class SharedDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance);
@@ -597,13 +610,9 @@ class SharedDataFacade final : public BaseDataFacade
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range);
@@ -612,13 +621,9 @@ class SharedDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range);
@@ -684,11 +689,9 @@ class SharedDataFacade final : public BaseDataFacade
}
else
{
std::for_each(m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id)
{
result_datasources.push_back(datasource_id);
});
std::for_each(
m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id) { result_datasources.push_back(datasource_id); });
}
}
@@ -709,7 +712,37 @@ class SharedDataFacade final : public BaseDataFacade
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetContinueStraightDefault() const override final { return m_profile_properties->continue_straight_at_waypoint; }
bool GetContinueStraightDefault() const override final
{
return m_profile_properties->continue_straight_at_waypoint;
}
BearingClassID GetBearingClassID(const NodeID id) const override final
{
return m_bearing_class_id_table.at(id);
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const override final
{
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
auto range = m_bearing_ranges_table->GetRange(bearing_class_id);
util::guidance::BearingClass result;
for (auto itr = m_bearing_values_table.begin() + range.front();
itr != m_bearing_values_table.begin() + range.back() + 1; ++itr)
result.add(*itr);
return result;
}
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return m_entry_class_id_list.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
return m_entry_class_table.at(entry_class_id);
}
};
}
}
+32 -32
View File
@@ -22,7 +22,7 @@ namespace engine
// Implements complex queries on top of an RTree and builds PhantomNodes from it.
//
// Only holds a weak reference on the RTree!
// Only holds a weak reference on the RTree and coordinates!
template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
{
using EdgeData = typename RTreeT::EdgeData;
@@ -31,9 +31,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
public:
GeospatialQuery(RTreeT &rtree_,
std::shared_ptr<CoordinateList> coordinates_,
const CoordinateList &coordinates_,
DataFacadeT &datafacade_)
: rtree(rtree_), coordinates(std::move(coordinates_)), datafacade(datafacade_)
: rtree(rtree_), coordinates(coordinates_), datafacade(datafacade_)
{
}
@@ -45,7 +45,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns nearest PhantomNodes in the given bearing range within max_distance.
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance)
NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -56,7 +56,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment)
{
return checkSegmentDistance(input_coordinate, segment, max_distance);
return CheckSegmentDistance(input_coordinate, segment, max_distance);
});
return MakePhantomNodes(input_coordinate, results);
@@ -68,18 +68,18 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range, max_distance](const CandidateSegment &segment)
{
return checkSegmentBearing(segment, bearing, bearing_range);
return CheckSegmentBearing(segment, bearing, bearing_range);
},
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment)
{
return checkSegmentDistance(input_coordinate, segment, max_distance);
return CheckSegmentDistance(input_coordinate, segment, max_distance);
});
return MakePhantomNodes(input_coordinate, results);
@@ -91,13 +91,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
auto results =
rtree.Nearest(input_coordinate,
[this, bearing, bearing_range](const CandidateSegment &segment)
{
return checkSegmentBearing(segment, bearing, bearing_range);
return CheckSegmentBearing(segment, bearing, bearing_range);
},
[max_results](const std::size_t num_results, const CandidateSegment &)
{
@@ -115,19 +115,19 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
auto results =
rtree.Nearest(input_coordinate,
[this, bearing, bearing_range](const CandidateSegment &segment)
{
return checkSegmentBearing(segment, bearing, bearing_range);
return CheckSegmentBearing(segment, bearing, bearing_range);
},
[this, max_distance, max_results, input_coordinate](
const std::size_t num_results, const CandidateSegment &segment)
{
return num_results >= max_results ||
checkSegmentDistance(input_coordinate, segment, max_distance);
CheckSegmentDistance(input_coordinate, segment, max_distance);
});
return MakePhantomNodes(input_coordinate, results);
@@ -136,7 +136,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns max_results nearest PhantomNodes.
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results)
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -157,7 +157,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance)
const double max_distance) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -169,7 +169,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const std::size_t num_results, const CandidateSegment &segment)
{
return num_results >= max_results ||
checkSegmentDistance(input_coordinate, segment, max_distance);
CheckSegmentDistance(input_coordinate, segment, max_distance);
});
return MakePhantomNodes(input_coordinate, results);
@@ -179,7 +179,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance)
const double max_distance) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -200,7 +200,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
input_coordinate](const std::size_t num_results, const CandidateSegment &segment)
{
return (num_results > 0 && has_big_component) ||
checkSegmentDistance(input_coordinate, segment, max_distance);
CheckSegmentDistance(input_coordinate, segment, max_distance);
});
if (results.size() == 0)
@@ -216,7 +216,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns the nearest phantom node. If this phantom node is not from a big component
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate)
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -251,7 +251,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns the nearest phantom node. If this phantom node is not from a big component
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const int bearing, const int bearing_range)
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -266,7 +266,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
if (use_segment)
{
use_directions = checkSegmentBearing(segment, bearing, bearing_range);
use_directions = CheckSegmentBearing(segment, bearing, bearing_range);
if (use_directions.first || use_directions.second)
{
has_big_component = has_big_component || !segment.data.component.is_tiny;
@@ -297,7 +297,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -312,7 +312,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
if (use_segment)
{
use_directions = checkSegmentBearing(segment, bearing, bearing_range);
use_directions = CheckSegmentBearing(segment, bearing, bearing_range);
if (use_directions.first || use_directions.second)
{
has_big_component = has_big_component || !segment.data.component.is_tiny;
@@ -326,7 +326,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
input_coordinate](const std::size_t num_results, const CandidateSegment &segment)
{
return (num_results > 0 && has_big_component) ||
checkSegmentDistance(input_coordinate, segment, max_distance);
CheckSegmentDistance(input_coordinate, segment, max_distance);
});
if (results.size() == 0)
@@ -360,7 +360,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
double ratio;
const auto current_perpendicular_distance =
util::coordinate_calculation::perpendicularDistance(
coordinates->at(data.u), coordinates->at(data.v), input_coordinate,
coordinates[data.u], coordinates[data.v], input_coordinate,
point_on_segment, ratio);
// Find the node-based-edge that this belongs to, and directly
@@ -416,9 +416,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return transformed;
}
bool checkSegmentDistance(const Coordinate input_coordinate,
bool CheckSegmentDistance(const Coordinate input_coordinate,
const CandidateSegment &segment,
const double max_distance)
const double max_distance) const
{
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
!segment.data.forward_segment_id.enabled);
@@ -432,9 +432,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
max_distance;
}
std::pair<bool, bool> checkSegmentBearing(const CandidateSegment &segment,
std::pair<bool, bool> CheckSegmentBearing(const CandidateSegment &segment,
const int filter_bearing,
const int filter_bearing_range)
const int filter_bearing_range) const
{
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
!segment.data.forward_segment_id.enabled);
@@ -442,7 +442,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
!segment.data.reverse_segment_id.enabled);
const double forward_edge_bearing = util::coordinate_calculation::bearing(
coordinates->at(segment.data.u), coordinates->at(segment.data.v));
coordinates[segment.data.u], coordinates[segment.data.v]);
const double backward_edge_bearing = (forward_edge_bearing + 180) > 360
? (forward_edge_bearing - 180)
@@ -459,8 +459,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return std::make_pair(forward_bearing_valid, backward_bearing_valid);
}
RTreeT &rtree;
const std::shared_ptr<CoordinateList> coordinates;
const RTreeT &rtree;
const CoordinateList &coordinates;
DataFacadeT &datafacade;
};
}
+11 -5
View File
@@ -43,34 +43,40 @@ LegGeometry assembleGeometry(const DataFacadeT &facade,
geometry.segment_offsets.push_back(0);
geometry.locations.push_back(source_node.location);
auto cumulative_distance = 0.;
auto current_distance = 0.;
auto prev_coordinate = geometry.locations.front();
for (const auto &path_point : leg_data)
{
auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node);
current_distance +=
current_distance =
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
cumulative_distance += current_distance;
// all changes to this check have to be matched with assemble_steps
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
{
geometry.segment_distances.push_back(current_distance);
geometry.segment_distances.push_back(cumulative_distance);
geometry.segment_offsets.push_back(geometry.locations.size());
current_distance = 0.;
cumulative_distance = 0.;
}
prev_coordinate = coordinate;
geometry.annotations.emplace_back(LegGeometry::Annotation{current_distance, path_point.duration_until_turn / 10.});
geometry.locations.push_back(std::move(coordinate));
}
current_distance +=
current_distance =
util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location);
cumulative_distance += current_distance;
// segment leading to the target node
geometry.segment_distances.push_back(current_distance);
geometry.segment_distances.push_back(cumulative_distance);
geometry.annotations.emplace_back(LegGeometry::Annotation{current_distance, target_node.forward_weight / 10.});
geometry.segment_offsets.push_back(geometry.locations.size());
geometry.locations.push_back(target_node.location);
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1);
return geometry;
}
+115 -3
View File
@@ -1,6 +1,7 @@
#ifndef ENGINE_GUIDANCE_ASSEMBLE_LEG_HPP_
#define ENGINE_GUIDANCE_ASSEMBLE_LEG_HPP_
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_leg.hpp"
#include "engine/guidance/route_step.hpp"
@@ -22,12 +23,104 @@ namespace engine
{
namespace guidance
{
namespace detail
{
const constexpr std::size_t MAX_USED_SEGMENTS = 2;
struct NamedSegment
{
EdgeWeight duration;
std::uint32_t position;
std::uint32_t name_id;
};
inline RouteLeg assembleLeg(const std::vector<PathData> &route_data,
template <std::size_t SegmentNumber>
std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathData> &route_data)
{
// merges segments with same name id
const auto collapse_segments = [](std::vector<NamedSegment> &segments)
{
auto out = segments.begin();
auto end = segments.end();
// Do nothing if we were given an empty array
if (out == end)
{
return end;
}
for (auto in = std::next(out); in != end; ++in)
{
if (in->name_id == out->name_id)
{
out->duration += in->duration;
}
else
{
++out;
BOOST_ASSERT(out != end);
*out = *in;
}
}
BOOST_ASSERT(out != end);
return ++out;
};
std::vector<NamedSegment> segments(route_data.size());
std::uint32_t index = 0;
std::transform(
route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point)
{
return NamedSegment{point.duration_until_turn, index++, point.name_id};
});
// this makes sure that the segment with the lowest position comes first
std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
{
return lhs.name_id < rhs.name_id ||
(lhs.name_id == rhs.name_id && lhs.position < rhs.position);
});
auto new_end = collapse_segments(segments);
segments.resize(new_end - segments.begin());
// Filter out segments with an empty name (name_id == 0)
new_end = std::remove_if(segments.begin(), segments.end(), [](const NamedSegment &segment)
{
return segment.name_id == 0;
});
segments.resize(new_end - segments.begin());
// sort descending
std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
{
return lhs.duration > rhs.duration ||
(lhs.duration == rhs.duration && lhs.position < rhs.position);
});
// make sure the segments are sorted by position
segments.resize(std::min(segments.size(), SegmentNumber));
std::sort(segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs)
{
return lhs.position < rhs.position;
});
std::array<std::uint32_t, SegmentNumber> summary;
std::fill(summary.begin(), summary.end(), 0);
std::transform(segments.begin(), segments.end(), summary.begin(),
[](const NamedSegment &segment)
{
return segment.name_id;
});
return summary;
}
}
inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
const std::vector<PathData> &route_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node,
const PhantomNode &target_node,
const bool target_traversed_in_reverse)
const bool target_traversed_in_reverse,
const bool needs_summary)
{
const auto target_duration =
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight) /
@@ -70,7 +163,26 @@ inline RouteLeg assembleLeg(const std::vector<PathData> &route_data,
10.0;
}
return RouteLeg{duration, distance, {}};
std::string summary;
if (needs_summary)
{
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(route_data);
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
BOOST_ASSERT(summary_array.begin() != summary_array.end());
summary = std::accumulate(std::next(summary_array.begin()), summary_array.end(),
facade.GetNameForID(summary_array.front()),
[&facade](std::string previous, const std::uint32_t name_id)
{
if (name_id != 0)
{
previous += ", " + facade.GetNameForID(name_id);
}
return previous;
});
}
return RouteLeg{duration, distance, summary, {}};
}
} // namespace guidance
+82 -36
View File
@@ -12,8 +12,12 @@
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
#include <cstddef>
#include <vector>
namespace osrm
@@ -24,14 +28,10 @@ namespace guidance
{
namespace detail
{
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const LegGeometry &leg_geometry,
const std::size_t segment_index);
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const WaypointType waypoint_type,
const LegGeometry &leg_geometry);
std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry);
std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry);
std::pair<short, short> getIntermediateBearings(const LegGeometry &leg_geometry,
const std::size_t segment_index);
} // ns detail
template <typename DataFacadeT>
@@ -63,34 +63,67 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
std::size_t segment_index = 0;
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
auto bearings = detail::getDepartBearings(leg_geometry);
StepManeuver maneuver{source_node.location, bearings.first,
bearings.second, extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Depart, 0};
Intersection intersection{
source_node.location,
std::vector<short>({bearings.second}),
std::vector<bool>({true}), Intersection::NO_INDEX, 0};
if (leg_data.size() > 0)
{
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
maneuver.location = source_node.location;
// PathData saves the information we need of the segment _before_ the turn,
// but a RouteStep is with regard to the segment after the turn.
// We need to skip the first segment because it is already covered by the
// initial start of a route
int segment_duration = 0;
for (const auto &path_point : leg_data)
// some name changes are not announced in our processing. For these, we have to keep the
// first name on the segment
auto step_name_id = source_node.name_id;
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
{
const auto &path_point = leg_data[leg_data_index];
segment_duration += path_point.duration_until_turn;
// all changes to this check have to be matched with assemble_geometry
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
{
BOOST_ASSERT(segment_duration >= 0);
const auto name = facade.GetNameForID(path_point.name_id);
const auto name = facade.GetNameForID(step_name_id);
const auto distance = leg_geometry.segment_distances[segment_index];
steps.push_back(RouteStep{path_point.name_id, name, NO_ROTARY_NAME,
segment_duration / 10.0, distance, path_point.travel_mode,
maneuver, leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
leg_geometry, segment_index);
if (leg_data_index + 1 < leg_data.size())
{
step_name_id = leg_data[leg_data_index + 1].name_id;
}
else
{
step_name_id = target_node.name_id;
}
steps.push_back(RouteStep{
step_name_id, name, NO_ROTARY_NAME, segment_duration / 10.0, distance,
path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
bearings = detail::getIntermediateBearings(leg_geometry, segment_index);
const auto entry_class = facade.GetEntryClass(path_point.entry_classid);
const auto bearing_class = facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node));
intersection.in = bearing_class.findMatchingBearing(util::bearing::reverseBearing(bearings.first));
intersection.out = bearing_class.findMatchingBearing(bearings.second);
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
intersection.bearings.clear();
std::copy(bearing_class.getAvailableBearings().begin(), bearing_class.getAvailableBearings().end(),
std::back_inserter(intersection.bearings));
intersection.entry.clear();
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
{
intersection.entry.push_back(entry_class.allowsEntry(idx));
}
maneuver = {intersection.location, bearings.first, bearings.second, path_point.turn_instruction, WaypointType::None, 0};
segment_index++;
segment_duration = 0;
}
@@ -98,10 +131,10 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const auto distance = leg_geometry.segment_distances[segment_index];
const int duration = segment_duration + target_duration;
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
NO_ROTARY_NAME, duration / 10., distance, target_mode, maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
steps.push_back(RouteStep{
step_name_id, facade.GetNameForID(step_name_id), NO_ROTARY_NAME, duration / 10.,
distance, target_mode, maneuver, leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
}
// In this case the source + target are on the same edge segment
else
@@ -112,29 +145,42 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
// |---| source_duration
// |---------| target_duration
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
int duration = target_duration - source_duration;
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{source_node.name_id, facade.GetNameForID(source_node.name_id),
NO_ROTARY_NAME, duration / 10.,
leg_geometry.segment_distances[segment_index], source_mode,
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
steps.push_back(RouteStep{
source_node.name_id, facade.GetNameForID(source_node.name_id), NO_ROTARY_NAME,
duration / 10., leg_geometry.segment_distances[segment_index], source_mode,
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
}
BOOST_ASSERT(segment_index == number_of_segments - 1);
bearings = detail::getArriveBearings(leg_geometry);
// This step has length zero, the only reason we need it is the target location
auto final_maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, leg_geometry);
maneuver = {intersection.location, bearings.first, bearings.second, extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, 0};
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
std::vector<bool>({true}), 0, Intersection::NO_INDEX};
BOOST_ASSERT(!leg_geometry.locations.empty());
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode,
final_maneuver, leg_geometry.locations.size()-1,
leg_geometry.locations.size()});
std::move(maneuver), leg_geometry.locations.size() - 1,
leg_geometry.locations.size(),
{intersection}});
BOOST_ASSERT(steps.front().intersections.size() == 1);
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart);
BOOST_ASSERT(steps.back().intersections.size() == 1);
BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1);
BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1);
BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive);
return steps;
}
+7
View File
@@ -31,6 +31,13 @@ struct LegGeometry
// length of the segment in meters
std::vector<double> segment_distances;
// Per-coordinate metadata
struct Annotation {
double distance;
double duration;
};
std::vector<Annotation> annotations;
std::size_t FrontIndex(std::size_t segment_index) const
{
return segment_offsets[segment_index];
@@ -17,6 +17,13 @@ namespace guidance
// passed as none-reference to modify in-place and move out again
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps);
// Multiple possible reasons can result in unnecessary/confusing instructions
// A prime example would be a segregated intersection. Turning around at this
// intersection would result in two instructions to turn left.
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructionst that is not cluttered by unnecessary turns/name changes.
std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps);
// trim initial/final segment of very short length.
// This function uses in/out parameter passing to modify both steps and geometry in place.
// We use this method since both steps and geometry are closely coupled logically but
@@ -30,6 +37,9 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
const PhantomNode &source_node,
const PhantomNode &target_node);
//remove steps invalidated by post-processing
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
// postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself.
+4
View File
@@ -3,6 +3,9 @@
#include "engine/guidance/route_step.hpp"
#include <boost/optional.hpp>
#include <string>
#include <vector>
namespace osrm
@@ -16,6 +19,7 @@ struct RouteLeg
{
double duration;
double distance;
std::string summary;
std::vector<RouteStep> steps;
};
}
+39
View File
@@ -3,6 +3,9 @@
#include "engine/guidance/step_maneuver.hpp"
#include "extractor/travel_mode.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include <cstddef>
@@ -21,6 +24,27 @@ namespace guidance
// Notable exceptions are Departure and Arrival steps.
// Departue: s --> a --> b. Represents the segment s,a with location being s.
// Arrive: a --> b --> t. The segment (b,t) is already covered by the previous segment.
// A represenetation of intermediate intersections
struct Intersection
{
static const constexpr std::size_t NO_INDEX = std::numeric_limits<std::size_t>::max();
util::Coordinate location;
std::vector<short> bearings;
std::vector<bool> entry;
std::size_t in;
std::size_t out;
};
inline Intersection getInvalidIntersection()
{
return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}},
{},
{},
Intersection::NO_INDEX,
Intersection::NO_INDEX};
}
struct RouteStep
{
unsigned name_id;
@@ -33,7 +57,22 @@ struct RouteStep
// indices into the locations array stored the LegGeometry
std::size_t geometry_begin;
std::size_t geometry_end;
std::vector<Intersection> intersections;
};
inline RouteStep getInvalidRouteStep()
{
return {0,
"",
"",
0,
0,
TRAVEL_MODE_INACCESSIBLE,
getInvalidStepManeuver(),
0,
0,
{getInvalidIntersection()}};
}
}
}
}
+14 -12
View File
@@ -1,8 +1,8 @@
#ifndef ENGINE_GUIDANCE_STEP_MANEUVER_HPP
#define ENGINE_GUIDANCE_STEP_MANEUVER_HPP
#include "util/coordinate.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/coordinate.hpp"
#include <cstdint>
#include <vector>
@@ -21,24 +21,26 @@ enum class WaypointType : std::uint8_t
Depart,
};
//A represenetation of intermediate intersections
struct IntermediateIntersection
{
double duration;
double distance;
util::Coordinate location;
};
struct StepManeuver
{
util::Coordinate location;
double bearing_before;
double bearing_after;
short bearing_before;
short bearing_after;
extractor::guidance::TurnInstruction instruction;
WaypointType waypoint_type;
unsigned exit;
std::vector<IntermediateIntersection> intersections;
};
inline StepManeuver getInvalidStepManeuver()
{
return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}},
0,
0,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::None,
0};
}
} // namespace guidance
} // namespace engine
} // namespace osrmn
+18 -5
View File
@@ -1,9 +1,11 @@
#ifndef OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_
#define OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_
#ifndef OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#define OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "util/bearing.hpp"
#include <algorithm>
namespace osrm
{
namespace engine
@@ -23,9 +25,12 @@ inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruct
{
return (instruction.type == extractor::guidance::TurnType::EnterRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterRotary ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary);
}
@@ -33,8 +38,10 @@ inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruct
{
return (instruction.type == extractor::guidance::TurnType::ExitRoundabout ||
instruction.type == extractor::guidance::TurnType::ExitRotary ||
instruction.type == extractor::guidance::TurnType::ExitRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary);
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
@@ -42,7 +49,7 @@ inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruc
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline extractor::guidance::DirectionModifier angleToDirectionModifier(const double bearing)
inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(const double bearing)
{
if (bearing < 135)
{
@@ -56,8 +63,14 @@ inline extractor::guidance::DirectionModifier angleToDirectionModifier(const dou
return extractor::guidance::DirectionModifier::Left;
}
inline double angularDeviation(const double angle, const double from)
{
const double deviation = std::abs(angle - from);
return std::min(360 - deviation, deviation);
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_ */
#endif /* OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_ */
+1 -10
View File
@@ -63,18 +63,9 @@ struct Hint
friend std::ostream &operator<<(std::ostream &, const Hint &);
};
#ifndef _MSC_VER
static_assert(sizeof(Hint) == 60 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 88;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
#else
// PhantomNode is bigger under windows because MSVC does not support bit packing
static_assert(sizeof(Hint) == 72 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 104;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
#endif
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint), "ENCODED_HINT_SIZE does not match size of Hint");
}
}
+3 -1
View File
@@ -2,8 +2,8 @@
#define RAW_ROUTE_DATA_H
#include "engine/phantom_node.hpp"
#include "extractor/travel_mode.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include "osrm/coordinate.hpp"
@@ -29,6 +29,8 @@ struct PathData
extractor::guidance::TurnInstruction turn_instruction;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// entry class of the turn, indicating possibility of turns
EntryClassID entry_classid;
};
struct InternalRouteResult
@@ -23,7 +23,7 @@ struct NormalDistribution
}
// FIXME implement log-probability version since it's faster
double density_function(const double val) const
double Density(const double val) const
{
using namespace boost::math::constants;
@@ -44,7 +44,7 @@ struct LaplaceDistribution
}
// FIXME implement log-probability version since it's faster
double density_function(const double val) const
double Density(const double val) const
{
const double x = std::abs(val - location);
return 1.0 / (2. * scale) * std::exp(-x / scale);
@@ -79,9 +79,9 @@ class BayesClassifier
ClassificationT classify(const ValueT &v) const
{
const double positive_postpriori =
positive_apriori_probability * positive_distribution.density_function(v);
positive_apriori_probability * positive_distribution.Density(v);
const double negative_postpriori =
negative_apriori_probability * negative_distribution.density_function(v);
negative_apriori_probability * negative_distribution.Density(v);
const double norm = positive_postpriori + negative_postpriori;
if (positive_postpriori > negative_postpriori)
@@ -82,10 +82,10 @@ template <class CandidateLists> struct HiddenMarkovModel
}
}
clear(0);
Clear(0);
}
void clear(std::size_t initial_timestamp)
void Clear(std::size_t initial_timestamp)
{
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_distances.size() &&
path_distances.size() == pruned.size() && pruned.size() == breakage.size());
+3 -9
View File
@@ -149,13 +149,11 @@ struct PhantomNode
unsigned reverse_packed_geometry_id;
struct ComponentType
{
uint32_t id : 31;
bool is_tiny : 1;
std::uint32_t id : 31;
std::uint32_t is_tiny : 1;
} component;
// bit-fields are broken on Windows
#ifndef _MSC_VER
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to be 4 bytes big");
#endif
util::Coordinate location;
util::Coordinate input_location;
unsigned short fwd_segment_position;
@@ -165,11 +163,7 @@ struct PhantomNode
extractor::TravelMode backward_travel_mode;
};
#ifndef _MSC_VER
static_assert(sizeof(PhantomNode) == 60, "PhantomNode has more padding then expected");
#else
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
#endif
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
-1
View File
@@ -35,7 +35,6 @@ class TripPlugin final : public BasePlugin
int max_locations_trip;
InternalRouteResult ComputeRoute(const std::vector<PhantomNode> &phantom_node_list,
const api::TripParameters &parameters,
const std::vector<NodeID> &trip);
public:
@@ -162,8 +162,6 @@ class AlternativeRouting final
if (path_is_a_loop)
{
// Self Loop
BOOST_ASSERT(forward_heap1.GetData(middle_node).parent == middle_node &&
reverse_heap1.GetData(middle_node).parent == middle_node);
packed_forward_path.push_back(middle_node);
packed_forward_path.push_back(middle_node);
}
@@ -206,7 +206,7 @@ class MapMatching final : public BasicRoutingInterface<DataFacadeT, MapMatching<
split_points.push_back(split_index);
// note: this preserves everything before split_index
model.clear(split_index);
model.Clear(split_index);
std::size_t new_start = model.initialize(split_index);
// no new start was found -> stop viterbi calculation
if (new_start == map_matching::INVALID_STATE)
@@ -1,10 +1,10 @@
#ifndef ROUTING_BASE_HPP
#define ROUTING_BASE_HPP
#include "util/coordinate_calculation.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/search_engine_data.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
@@ -14,10 +14,10 @@
#include <algorithm>
#include <iterator>
#include <numeric>
#include <stack>
#include <utility>
#include <vector>
#include <stack>
#include <numeric>
namespace osrm
{
@@ -226,6 +226,11 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
recursion_stack.emplace(*std::prev(current), *current);
}
BOOST_ASSERT(*packed_path_begin == phantom_node_pair.source_phantom.forward_segment_id.id ||
*packed_path_begin == phantom_node_pair.source_phantom.reverse_segment_id.id);
BOOST_ASSERT(*std::prev(packed_path_end) == phantom_node_pair.target_phantom.forward_segment_id.id ||
*std::prev(packed_path_end) == phantom_node_pair.target_phantom.reverse_segment_id.id);
std::pair<NodeID, NodeID> edge;
while (!recursion_stack.empty())
{
@@ -301,8 +306,6 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
BOOST_ASSERT(weight_vector.size() == id_vector.size());
// ed.distance should be total_weight + penalties (turn, stop, etc)
BOOST_ASSERT(ed.distance >= total_weight);
const bool is_first_segment = unpacked_path.empty();
const std::size_t start_index =
@@ -319,13 +322,12 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
for (std::size_t i = start_index; i < end_index; ++i)
{
unpacked_path.push_back(
PathData{id_vector[i],
name_index,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
travel_mode});
PathData{id_vector[i], name_index, weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(), travel_mode,
INVALID_ENTRY_CLASSID});
}
BOOST_ASSERT(unpacked_path.size() > 0);
unpacked_path.back().entry_classid = facade->GetEntryClassID(ed.id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
}
@@ -350,7 +352,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
start_index =
id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1;
}
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
end_index =
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
}
else
{
@@ -373,19 +376,16 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later.
BOOST_ASSERT(start_index <= end_index);
for (std::size_t i = start_index; i != end_index; ++i)
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
{
BOOST_ASSERT(i < id_vector.size());
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
unpacked_path.push_back(
PathData{id_vector[i],
phantom_node_pair.target_phantom.name_id,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
target_traversed_in_reverse
? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode});
unpacked_path.push_back(PathData{
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID});
}
if (unpacked_path.size() > 0)
@@ -397,8 +397,17 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// However the first segment duration needs to be adjusted to the fact that the source
// phantom is in the middle of the segment. We do this by subtracting v--s from the
// duration.
BOOST_ASSERT(unpacked_path.front().duration_until_turn >= source_weight);
unpacked_path.front().duration_until_turn -= source_weight;
// Since it's possible duration_until_turn can be less than source_weight here if
// a negative enough turn penalty is used to modify this edge weight during
// osrm-contract, we clamp to 0 here so as not to return a negative duration
// for this segment.
// TODO this creates a scenario where it's possible the duration from a phantom
// node to the first turn would be the same as from end to end of a segment,
// which is obviously incorrect and not ideal...
unpacked_path.front().duration_until_turn =
std::max(unpacked_path.front().duration_until_turn - source_weight, 0);
}
// there is no equivalent to a node-based node in an edge-expanded graph.
@@ -559,9 +568,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// make sure to correctly unpack loops
if (distance != forward_heap.GetKey(middle) + reverse_heap.GetKey(middle))
{
// self loop
BOOST_ASSERT(forward_heap.GetData(middle).parent == middle &&
reverse_heap.GetData(middle).parent == middle);
// self loop makes up the full path
packed_leg.push_back(middle);
packed_leg.push_back(middle);
}
@@ -636,9 +643,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
}
// TODO check if unordered_set might be faster
// sort by id and increasing by distance
auto entry_point_comparator =
[](const std::pair<NodeID, EdgeWeight> &lhs, const std::pair<NodeID, EdgeWeight> &rhs)
{
auto entry_point_comparator = [](const std::pair<NodeID, EdgeWeight> &lhs,
const std::pair<NodeID, EdgeWeight> &rhs) {
return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second);
};
std::sort(forward_entry_points.begin(), forward_entry_points.end(), entry_point_comparator);
@@ -774,18 +780,50 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
nodes.target_phantom = target_phantom;
UnpackPath(packed_path.begin(), packed_path.end(), nodes, unpacked_path);
util::Coordinate previous_coordinate = source_phantom.location;
util::Coordinate current_coordinate;
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
using util::coordinate_calculation::detail::EARTH_RADIUS;
double distance = 0;
double prev_lat =
static_cast<double>(toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
double prev_lon =
static_cast<double>(toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
double prev_cos = std::cos(prev_lat);
for (const auto &p : unpacked_path)
{
current_coordinate = facade->GetCoordinateOfNode(p.turn_via_node);
distance += util::coordinate_calculation::haversineDistance(previous_coordinate,
current_coordinate);
previous_coordinate = current_coordinate;
const auto current_coordinate = facade->GetCoordinateOfNode(p.turn_via_node);
const double current_lat =
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
prev_lat = current_lat;
prev_lon = current_lon;
prev_cos = current_cos;
}
distance += util::coordinate_calculation::haversineDistance(previous_coordinate,
target_phantom.location);
const double current_lat =
static_cast<double>(toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
return distance;
}
@@ -57,15 +57,13 @@ class ShortestPathRouting final
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
total_distance_to_forward -
source_phantom.GetForwardWeightPlusOffset(),
-source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
total_distance_to_reverse -
source_phantom.GetReverseWeightPlusOffset(),
-source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
if (search_to_forward_node)
@@ -107,6 +105,7 @@ class ShortestPathRouting final
super::Search(forward_heap, reverse_heap, new_total_distance, leg_packed_path,
needs_loop_forwad, needs_loop_backwards);
}
new_total_distance += std::min(total_distance_to_forward,total_distance_to_reverse);
}
// searches shortest path between:

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