Compare commits

...

204 Commits

Author SHA1 Message Date
Daniel Patterson a0b1a5df8c Update version and CHANGELOG for 5.5.3. 2017-01-11 17:14:18 -08:00
Daniel Patterson 411313f666 Backport NumLanesToTheRight/NumLanesToTheLeft to support 6ea9f9fdf1 2017-01-11 16:44:25 -08:00
Moritz Kobitzsch ada0a1e8f8 fix coordinate assertion for walking profile with steps 2017-01-11 21:57:11 +00:00
Moritz Kobitzsch 74611f94fa Remove assertions that could be triggered by bad data. (#3469)
When two consecutive nodes have identical coordinates, there is no valid
bearing.  For now, make equal nodes have bearing 0.

Full fix still needs to be done via https://github.com/Project-OSRM/osrm-backend/issues/3470.
2017-01-11 21:55:29 +00:00
Michael Krasnyk eaff3b4210 Make a hard reset of named barrier mutexes on signal 2017-01-11 21:43:01 +00:00
Jihyun Yu 1fb9f3e1eb Fix copying vector on std::sort comparator (#3504) 2017-01-11 21:41:17 +00:00
Daniel J. Hofmann 6ea9f9fdf1 Consider number of lanes to cross, resolves #3025.
Lane Anticipation currently triggers on quick steps with lanes. This
changeset makes the "quick" part more dynamic by taking lanes left and
right of the turn into account. The reasoning for this is as follows.

The user can drive on the leftmost or rightmost lane and has to cross
all lanes left or right of the turn, respecitvely.

We scale our threshold appropriately, which now means the threshold
describes the duration the user needs for crossing _a single lane_.

Note: this is a heuristic and assumes the worst case. Which in my
opinion is fine to do since triggering Lane Anticipation in complex
scenarios is desirable.
2017-01-11 21:37:17 +00:00
Daniel Patterson 434a3a638a Make Travis buildit. 2016-12-21 15:31:03 -08:00
Daniel Patterson 6305f4a529 Update changelog and version. 2016-12-21 15:18:30 -08:00
Patrick Niklaus 646b1631ab Revert "Smarter search radius formula for map matching"
This reverts commit b73c59088c.
2016-12-21 15:14:33 -08:00
Patrick Niklaus a852ab1c43 Revert "Fix capture"
This reverts commit 4f81e31d63.
2016-12-21 15:14:33 -08:00
Patrick Niklaus ff25fc70f0 Revert "Hardcode search radius parameters"
This reverts commit 2c9e18d5a9.
2016-12-21 15:14:33 -08:00
Patrick Niklaus b34ed587d0 Revert "Fix call to std::min"
This reverts commit 8bb183bc8c.
2016-12-21 15:14:33 -08:00
Daniel Patterson b58329104a Bump version field and update CHANGELOG. 2016-12-16 13:58:21 -08:00
Patrick Niklaus d188e8e2a8 Fix changing shared memory in multi-process setup (#3462)
This change fixes two bugs:

1. A dead-lock that occurs between osrm-datastore and libosrm when an
   old dataset is free during a data update. This happened because the
   mutexes where acquired in a different order.

2. A region is deleted eventhough it is still in use. This happens when
   libosrm gets overtaken by osrm-datastore, so the new dataset is in
   the same region the old one was.
2016-12-16 13:54:57 -08:00
Daniel Patterson f88f51fd98 Log some memory usage statistics after preprocessing tasks. 2016-12-13 21:59:12 +01:00
Daniel J. Hofmann 98659fb0a0 Adds failing tests for directional access overrides, discovered in #3345 2016-12-13 17:37:42 +01:00
Daniel J. Hofmann 8a1afe456f Works around Unreachable Warning for Debug Build 2016-12-13 12:41:25 +01:00
Patrick Niklaus f1384f5e44 Merge pull request #3434 from Project-OSRM/fix/invalid-assertions
fix invalid assertion in coordinate_extractor
2016-12-12 19:19:47 +01:00
Moritz Kobitzsch 1cd5394a16 fix invalid assertion in coordinate_extractor 2016-12-12 10:12:32 +01:00
Daniel Patterson 8c7f744b1a Update node weights if traffic data is applied. 2016-12-11 16:02:58 +01:00
Patrick Niklaus 896445a337 Fix path to node binaries 2016-12-09 16:43:32 +00:00
Patrick Niklaus 8c21e1267e nvm -> install_node 2016-12-09 16:30:14 +00:00
Patrick Niklaus ad3fd46da5 Try to use mapbox node mirror 2016-12-09 15:28:28 +00:00
Huyen Chau Nguyen 62f0e11bfa assert that there is an open logger file when trying to log geojson output (#3417) 2016-12-09 14:58:20 +01:00
Patrick Niklaus 03d653c0bb Fix removing shared memory segments in a multi-process setup 2016-12-09 12:18:05 +01:00
Daniel J. Hofmann cbfb055f81 Changes Single Coordinate Geoms from Point to LineString, closes #3425. 2016-12-09 11:53:06 +01:00
Moritz Kobitzsch 2288704bb5 don't assign unused name to exception 2016-12-08 13:35:28 +01:00
Daniel J. Hofmann 97dcf4eef9 Fixes Compiler Crashes on Windows 2016-12-08 13:23:21 +01:00
Daniel Patterson 17e15033e1 Log helpful error message if mmap fails. 2016-12-07 22:03:49 +01:00
Daniel J. Hofmann 875f482203 Refactors and improves the Sliproad Handler, resolves #3109 2016-12-07 19:22:03 +01:00
Moritz Kobitzsch df3c39cef5 clean-up guidance code/code in general
removes duplicated includes
removes unused includes
eliminates dedicated toolkits that resulted in circular dependencies
moves functionality close to data, where possible
2016-12-07 12:10:56 +01:00
Moritz Kobitzsch a28a20a1ba fix errors in coordinate extractor due to duplicated coordinates
fix offset calculation in curve detection
2016-12-07 11:33:58 +01:00
Daniel Patterson 17a18b5c7c Revert "Add simple code review checklist to PR template."
This reverts commit 3f07a830e6.
2016-12-06 17:21:38 -08:00
Daniel Patterson 423c083038 Refactor logging, improve error handling workflow, clang-format. (#3385) 2016-12-06 12:31:13 -08:00
Daniel Patterson 468d8c0031 Refactor logging, improve error handling workflow, clang-format. (#3385) 2016-12-06 12:30:46 -08:00
Pepijn Schoen 6f4c6e84ae Handle file output through a FileWriter, align interfaces for FileWriter and FileReader 2016-12-06 15:59:12 +01:00
Michael Krasnyk 4b1aae40af Decoding should not fail for incomplete polyline strings (#3404)
Possible fails in
1) correct lattitude, longitude is missing
2) no end-of-number (0 5th bit) marker in the last character
2016-12-06 14:09:18 +01:00
Daniel J. Hofmann 0e6863aec1 Removes access and service restriction list from bike and foot profile 2016-12-05 14:15:47 +01:00
Daniel J. Hofmann 949d505783 Removes access_restricted flag internally 2016-12-05 14:15:47 +01:00
Emil Tin d11927046f car profile: remove use of is_access_restricted flag 2016-12-05 14:15:47 +01:00
Emil Tin 9461c83511 car profile: handle forward/backward access 2016-12-05 14:15:47 +01:00
Emil Tin 532cbfce13 profiles: Directional helper, some car refactoring 2016-12-05 14:15:47 +01:00
Michael Krasnyk 0fbd18b0dd Make absolute fixtures path 2016-12-04 16:34:42 +01:00
Daniel Patterson 3f07a830e6 Add simple code review checklist to PR template.
Add some checkboxes for common, mechanical parts that we should aim to hit for all PRs.
2016-12-02 23:18:57 -08:00
Moritz Kobitzsch 24b01fae00 fix extraction of coordinate along a way (#3397)
Also fix interpolation when coordinates are duplicated at the end of the vector
2016-12-02 13:11:04 -08:00
Daniel Patterson 0817cd6dfd Enforce iteration order so that tiles are encoded consistently on all platforms (#3393) 2016-12-02 08:59:39 -08:00
Daniel J. Hofmann 9d8b92f418 Abstracts away over differences in IntersectionView and Intersection.
Usage:

    struct MyIntersection : EnableIntersectionOps<MyIntersection> {

    };

Done.

We require MyIntersection having at least the member attributes from
IntersectionViewData but don't enforce a inheritance hierarchy.
2016-12-02 12:32:07 +01:00
Daniel Patterson 928a6f0c7d Variant got re-packaged, need to update search paths. (#3392) 2016-12-01 16:59:29 -08:00
Daniel Patterson 29b3caf529 Upgrade to mapbox/variant 1.1.4 2016-12-01 15:44:27 -08:00
Patrick Niklaus 20c8ac0272 Bump osrm version to 5.5 2016-12-01 22:12:28 +00:00
Patrick Niklaus c99c8bccbc Make the binutil detection work the same for clang and gcc
This uses the cmake internal find_program that will utilize the PATH at
configuration time. This way we don't need to pass CXXFLAGS to clang.
2016-12-01 21:55:17 +01:00
Patrick Niklaus 735191255d No need to set ccache explicitly if its in the path 2016-12-01 21:55:17 +01:00
Dane Springmeyer da6ca640a7 only install/enable binutils gold and llvm-ar when building in Release 2016-12-01 21:55:17 +01:00
Dane Springmeyer f6f7a9290f no need for llvm package 2016-12-01 21:55:17 +01:00
Dane Springmeyer 9687a9325c remove llvm-nm 2016-12-01 21:55:17 +01:00
Dane Springmeyer 43566bfd14 support -flto with clang++ 2016-12-01 21:55:17 +01:00
Michael Krasnyk 110e6c3689 Fix failing on windows io read test (#3390) 2016-12-01 11:44:28 -08:00
Moritz Kobitzsch 561b7cc58e Rember Intersection Shapes
Changes the processing order in the edge based graph factory.
Instead of iterating over all outgoing edges in order, we compute the edge
expanded graph in the order of intersections.
This allows to remember intersection shapes and re-use them for all possible ingoing edges.

Also: use low accuracry mode for intersections degree 2 intersections

We can use lower accuracy here, since the `bearing`
after the turn is not as relevant for off-route detection.
Getting lost is near impossible here.
2016-12-01 15:24:20 +01:00
Moritz Kobitzsch 5775679f64 fix coordinate extraction / errors in offset detector 2016-12-01 12:16:25 +01:00
Daniel Patterson 560d8ffec0 Restructure API docs so that they can be formatted with Docbox. (#3355)
Generate Docbox browseable HTML with `npm run build-api-docs`
2016-11-30 19:38:53 -08:00
Daniel Patterson 2544c3f20e Update changelog for FileReader change. 2016-11-30 19:10:44 -08:00
Daniel Patterson 5a311012af Consolidate file reading through the new FileReader class/interface. (#3321) 2016-11-30 19:08:01 -08:00
Karen Shea ef087f963d Merge pull request #3324 from Project-OSRM/constrain-staggering
Constrain staggered intersection detection by mode change and intermediary intersections
2016-11-30 07:35:17 -05:00
Moritz Kobitzsch a1127c3e09 reduce numbers of intersections in findNextIntersection, don't normalise for turn lanes 2016-11-30 10:21:53 +01:00
Patrick Niklaus 01a57ff1d8 Merge pull request #3367 from Project-OSRM/fix/rpath4all
Rework RPATH and building as subproject
2016-11-29 23:02:57 +01:00
karenzshea 37824e2954 don't staggered intersections on intermediary mode changes 2016-11-29 14:39:16 -05:00
Patrick Niklaus 4489c8dfc2 Expose LibOSRM find_package style variable to work as subproject 2016-11-29 15:38:51 +00:00
Patrick Niklaus ee63e39ff5 Add $ORIGIN and @executable_path to RPATH 2016-11-29 15:37:11 +00:00
karenzshea ce5bcc797b opening typo 2016-11-29 09:39:05 -05:00
Daniel J. Hofmann fe5cc55b0e support junction = circular in all profiles, add additional tests
References:
- https://wiki.openstreetmap.org/wiki/Tag:junction%3Dcircular
- https://lists.openstreetmap.org/pipermail/tagging/2016-November/030520.html
- https://github.com/Project-OSRM/osrm-backend/issues/3361
2016-11-29 13:44:32 +01:00
Moritz Kobitzsch 12d58ace10 add support for junction=circular, allowing named circular junctions to be treated as rotaries 2016-11-29 13:44:32 +01:00
Moritz Kobitzsch 4636aaabfe make can be ignored false by default 2016-11-29 11:47:35 +01:00
Moritz Kobitzsch 186cc8340a handle service roads next to roundabouts - ambiguous exit... :( 2016-11-29 11:47:35 +01:00
Michael Krasnyk e343f71541 Refactor Hilbert values computation 2016-11-28 14:17:12 +01:00
Michael Krasnyk 0df0d31d83 Fix nodes file reading in rtree benchmark 2016-11-28 14:17:12 +01:00
Moritz Kobitzsch aaf42a1caf add a follow-up section on testing to help decide what to do on guidance tests 2016-11-24 10:12:14 +01:00
Moritz Kobitzsch d02dd67e95 fix update to length cache 2016-11-23 11:27:59 +01:00
Moritz Kobitzsch a49bd70985 add low precision intersection_generator mode for faster graph traversal 2016-11-22 18:25:19 +01:00
Dane Springmeyer b2c27fbd25 test xcode8.2 2016-11-22 18:03:51 +01:00
karenzshea 9fe0e91d92 add tests for bridleways 2016-11-22 10:18:55 +01:00
Daniel J. Hofmann 08b7270f5c Fixes accidentally registering types twice to Luabind, closes #2811. 2016-11-22 10:09:08 +01:00
Kajari Ghosh fc52dd85fe refactor graph_loader (#3333)
Refactors the GraphLoader class to use the safer FileReader wrapper for better error handling.
2016-11-21 17:32:00 -08:00
Karen Shea 6d961d4a15 Merge pull request #3217 from Project-OSRM/refactor/obviousness
Refactor find obvious turn handling
2016-11-21 14:50:44 -05:00
karenzshea 0bd08224bf add comments, refactor find obvious turn 2016-11-21 13:16:30 -05:00
Daniel J. Hofmann 2a383efbf6 Makes Throughput Numbers Integral Types 2016-11-21 12:41:25 +01:00
Patrick Niklaus b84d70d305 Add regression test for nil values 2016-11-21 12:17:44 +01:00
Patrick Niklaus 3bade8625f Don't crash on assigning nil to a string in lua 2016-11-21 12:17:44 +01:00
Patrick Niklaus 844300b95a Print number of used jobs 2016-11-19 17:02:31 +01:00
Patrick Niklaus dd811539a3 Remove overriding c++ compiler from cmake on mason build 2016-11-19 17:02:31 +01:00
Patrick Niklaus 79c2ae46d8 Determine number of jobs over ncpu + 1 2016-11-19 17:02:31 +01:00
Patrick Niklaus d023e7c581 Don't use mason clang on OSX 2016-11-19 17:02:31 +01:00
Patrick Niklaus 4ccb08983f Fixed installing clang for mason builds 2016-11-19 17:02:31 +01:00
Patrick Niklaus 8c941d1344 Don't install clang when CLANG_VERSION is not set 2016-11-19 17:02:31 +01:00
Patrick Niklaus 841c032a0d Don't warn in example on 32bit only print message 2016-11-19 17:02:31 +01:00
Patrick Niklaus a764fd1f29 Don't expose all OSRM flags only the ones needed by external code 2016-11-19 17:02:31 +01:00
Patrick Niklaus 3687864cc1 Only run OSX in release 2016-11-18 17:49:05 +01:00
Dane Springmeyer 4b5466629f test with assertions+release on travis 2016-11-18 17:49:05 +01:00
Patrick Niklaus f19bf70b55 Account for imprecision in distance computation 2016-11-18 17:46:32 +01:00
Patrick Niklaus 24fa94af59 Remove obsolete test code 2016-11-18 17:46:32 +01:00
Patrick Niklaus 95a584a30d Make rounding when computing PhantomNode weight symmetric
Resolves a problem where the duration in forward and backward direction
was slightly different.
2016-11-18 17:46:32 +01:00
karenzshea 6ba36a2bc7 test and control for pushing both ways 2016-11-18 10:13:38 -05:00
karenzshea 039989a339 fix overlapping roads 2016-11-18 09:58:03 -05:00
karenzshea a7559077a0 add modes columns to bike tests 2016-11-18 09:21:48 -05:00
Daniel J. Hofmann bbe80192aa Staggered Intersections for Bike 2016-11-18 08:52:48 -05:00
karenzshea 9b16b757a4 halfway staggered intersection test 2016-11-18 08:52:48 -05:00
karenzshea 3680fc9d90 add check/test for intermediary intersections 2016-11-18 08:52:47 -05:00
karenzshea 836e8bdff0 don't collapse with mode changes 2016-11-18 08:52:47 -05:00
Patrick Niklaus 3d4b39be7d Include changed car.lua dependencies in changelog 2016-11-18 00:21:34 +01:00
Emil Tin 193dfd9d8b lua: add changelog item 2016-11-18 00:21:34 +01:00
Emil Tin 305e813489 lua: improve naming 2016-11-18 00:21:34 +01:00
Emil Tin a5756fc764 fix c++ formatting 2016-11-18 00:21:34 +01:00
Emil Tin f5bf788814 lua: simplify destination helper 2016-11-18 00:21:34 +01:00
Emil Tin 00f7d7776d lua: refactor destination helper 2016-11-18 00:21:34 +01:00
Emil Tin dce685c780 ensure we don't pass empty tags to LUA 2016-11-18 00:21:34 +01:00
Emil Tin 173a39fd8b lua: fix typo 2016-11-18 00:21:34 +01:00
Emil Tin 5d564ee510 lua: Set and Sequence 2016-11-18 00:21:34 +01:00
Emil Tin 24c2708d1e lua: eliminte tag cache, simplify tag checks 2016-11-18 00:21:34 +01:00
Emil Tin d87a972c66 don't return empty tags strings to lua 2016-11-18 00:21:34 +01:00
Emil Tin f90736b6b3 lua: handle_hov() 2016-11-18 00:21:34 +01:00
Emil Tin 9aeb3086cb lua: cleanup handle_blocking(), move common cases up early 2016-11-18 00:21:34 +01:00
Emil Tin 9e361a8178 lua: exit earlier when possible 2016-11-18 00:21:34 +01:00
Emil Tin c3aeef4e09 lua: eliminate TagCache.set_tag() 2016-11-18 00:21:34 +01:00
Emil Tin 50090e6447 lua: some cleanup 2016-11-18 00:21:34 +01:00
Emil Tin b9e5d26e3a remove dead code 2016-11-18 00:21:34 +01:00
Emil Tin 184cfab33b increase performance by passing vars instead of a table 2016-11-18 00:21:34 +01:00
Emil Tin fd95b2da76 streamline way_function 2016-11-18 00:21:34 +01:00
Emil Tin ce04a608b8 lua: refactor car.lua into smaller functions 2016-11-18 00:21:34 +01:00
Emil Tin cff69178e8 lua: simple tag cache enabling factoring way_function into smaller functions 2016-11-18 00:21:34 +01:00
Emil Tin 6c682b2258 lua: helpers for debugging 2016-11-18 00:21:34 +01:00
Alex Barth c1087eaecc Update http.md 2016-11-17 23:59:18 +01:00
Kerrick Staley 8bb183bc8c Fix call to std::min 2016-11-17 17:56:23 +01:00
Kerrick Staley 15359befdc Update docs 2016-11-17 17:56:23 +01:00
Kerrick Staley 2c9e18d5a9 Hardcode search radius parameters 2016-11-17 17:56:23 +01:00
Kerrick Staley 4f81e31d63 Fix capture 2016-11-17 17:56:23 +01:00
kerrick-lyft b73c59088c Smarter search radius formula for map matching 2016-11-17 17:56:23 +01:00
Michael Krasnyk 44e4728bde Added gcc 4.9 release build 2016-11-17 16:02:56 +01:00
Michael Krasnyk ba2629456f Added a copy of std::align due to missing implementation in gcc < 5
References:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350
2016-11-17 16:02:56 +01:00
Daniel J. Hofmann 1b4779a58c Avoids Shuffling Data Around for Nothing, closes 3306 2016-11-17 12:51:18 +01:00
Michael Krasnyk 1eaf9f3269 Fix ubsan runtime error: left shift of negative value -9 2016-11-16 12:12:20 -08:00
Daniel J. H 73e365d398 Conditionally checks std::is_trivially_copyable only if available. (#3327) 2016-11-16 12:07:45 -08:00
Michael Krasnyk d5bf508046 Fix alignments in shared facade via alignof/std::align 2016-11-16 18:20:19 +01:00
Moritz Kobitzsch 47b097038a fixes warning due to type only used in debug 2016-11-16 12:20:05 +01:00
Moritz Kobitzsch a4264c7849 fix node-based-graph-walker 2016-11-16 12:03:59 +01:00
Daniel J. H 463228d0bf Merge pull request #3323 from Project-OSRM/libosmium-2.10.2
Osmium 2.10.2, resolves #3303
2016-11-16 12:01:56 +01:00
Daniel J. Hofmann 1dde5d288d Merge commit '6f885b5bdb2d220eb49e7d0fabcd520f56f2b419' into libosmium-2.10.2 2016-11-16 11:33:59 +01:00
Daniel J. Hofmann 6f885b5bdb Squashed 'third_party/libosmium/' changes from 40c4a48..d5ecf4d
d5ecf4d Release v2.10.2
7c04564 Update embedded protozero to version 1.4.4.
e209d81 Write code for 64bit systems, so it compiles on 32bit w/o warning.
640217c Fix buffer overflow.
8b4620f Release v2.10.1
38bf3ab Update protozero to 1.4.3.
f81b3c6 Fix IdSet on 32 bit.
5ff4753 Workaround so the test works on 32bit systems.
7542694 Include our endian.hpp before using the endianness test macros.

git-subtree-dir: third_party/libosmium
git-subtree-split: d5ecf4df90e2995c816886d2a002c3d3de7062ee
2016-11-16 11:33:59 +01:00
Daniel J. Hofmann 820feb3a04 Update Libosmium Dependency Script to 2.10.2 2016-11-16 10:58:52 +01:00
Daniel Patterson 46b00e1378 Update docs for tile plugin. 2016-11-15 18:56:03 -08:00
Daniel Patterson eb12c16fd6 Output newlines for each progress indicator when not on a tty. 2016-11-15 18:14:05 -08:00
Daniel Patterson 17c32f5ce7 Fully revert 04f8b653c94614 2016-11-15 16:55:02 -08:00
Daniel Patterson 53ef2e2955 Use an enum type for the 'should read fingerprint' flag, rather than a mysterious boolean
Fix tests.
2016-11-15 16:55:02 -08:00
Daniel Patterson 7b1131b982 Consolidate vector deserialization. 2016-11-15 16:55:02 -08:00
Daniel Patterson 1fc969e6c8 Fix naming convention, and pass-by-reference for data layout. 2016-11-15 16:55:02 -08:00
Daniel Patterson 49f960064c Partial revert of 04f8b653c94614 - the PackedVector is special. 2016-11-15 16:55:02 -08:00
Daniel Patterson 83a9d0590d Pass-by-reference instead of pointer. 2016-11-15 16:55:02 -08:00
Daniel Patterson d8b016b92a Simplify read error detection. 2016-11-15 16:55:02 -08:00
Daniel Patterson 608044305d Rename the datafacades to more clearly describe what they do. 2016-11-15 16:55:02 -08:00
Daniel Patterson 4760b85930 Add checking assertions for all copy operations. 2016-11-15 16:55:02 -08:00
Daniel Patterson 9e2782d923 Fix undefined behaviour - we were referring to two different temporaries. 2016-11-15 16:55:02 -08:00
Daniel Patterson 2dfeb0cabc Remove unused code. 2016-11-15 16:55:02 -08:00
Daniel Patterson 2f9b5788d0 Destructor should fail hard if an exception is raised. 2016-11-15 16:55:02 -08:00
Daniel Patterson be496eb4e3 Return the type we claim it will return. 2016-11-15 16:55:02 -08:00
Daniel Patterson 97244557b1 Don't need to use new, make_unique<> can do what we need here. 2016-11-15 16:55:02 -08:00
Daniel Patterson e2e5eb0169 Remove use of ShM<>::vector in favour of the boost::iterator_range 2016-11-15 16:55:02 -08:00
Daniel Patterson 6949d7ee5b Remove ownership of block pointers from base class. 2016-11-15 16:55:02 -08:00
Daniel Patterson 02303904b8 Update changelog. 2016-11-15 16:55:02 -08:00
Daniel Patterson 4ad6d88888 Refactor file loading to use a common class that has proper error handling. 2016-11-15 16:55:02 -08:00
Daniel Patterson e226b52f21 const-ify things, use RAII for file closure, and start to use io:: to read some stuff. 2016-11-15 16:55:02 -08:00
Daniel Patterson b1125b7f1f Rename base class to something more in line with it's actual function. 2016-11-15 16:55:02 -08:00
Daniel Patterson 33ff92d27e Remove debugging code. 2016-11-15 16:55:02 -08:00
Daniel Patterson de4fd76d57 Clean up some todo notes. 2016-11-15 16:55:02 -08:00
Daniel Patterson bf6df74d44 Consolidate datafacade file loading logic.
Both datafacades now use a single large memory block and common
file loading logic.
2016-11-15 16:55:02 -08:00
Daniel J. Hofmann 8f6dd805e5 Fixes ODR Violation in Graph Loader, closes #3308 2016-11-15 12:04:13 +01:00
Patrick Niklaus 3235f30a98 [skip ci] clarify release branches 2016-11-14 23:21:48 +00:00
Daniel J. Hofmann 7e4020c010 Allocates memory for the node info list upfront.
Turns out we were not doing this. Huh.

Callstack:
- https://github.com/Project-OSRM/osrm-backend/blob/78583d2c8c639466bdde01c848398b2a48b72f44/include/util/graph_loader.hpp#L65-L68
- https://github.com/Project-OSRM/osrm-backend/blob/538bbd47d1ee169764b66df3ef67ecfe131cdfec/src/extractor/extractor.cpp#L423-L424
- https://github.com/Project-OSRM/osrm-backend/blob/78583d2c8c639466bdde01c848398b2a48b72f44/src/extractor/extractor.cpp#L465-L466
- https://github.com/Project-OSRM/osrm-backend/blob/78583d2c8c639466bdde01c848398b2a48b72f44/src/extractor/extractor.cpp#L254-L261
2016-11-15 00:06:52 +01:00
Moritz Kobitzsch 538bbd47d1 fix length limited graph walker 2016-11-14 18:38:15 +01:00
Moritz Kobitzsch 78583d2c8c fix getTurnDirection, widen straight range, adjust tests accordingly 2016-11-14 11:09:14 +01:00
Dane Springmeyer fa1a0a1325 Ensure pkg-config reports OSRM_LIB_LINKER_FLAGS 2016-11-12 14:35:32 +01:00
Dane Springmeyer 6df1437cfc drop md5sum dependency, depend on node.js script 2016-11-12 02:48:13 +01:00
Dane Springmeyer 15ed53d4a7 install ccache/cmake via consistent method 2016-11-12 02:48:13 +01:00
Dane Springmeyer 63be191775 speed up osx builds by avoiding homebrew 2016-11-12 02:48:13 +01:00
Moritz Kobitzsch 6ec505281e fix edge discovery in tile plugin 2016-11-12 02:15:04 +01:00
Patrick Niklaus 5a293e891b Merge pull request #3296 from Project-OSRM/libosmium-2.10.0
Osmium 2.10
2016-11-12 02:12:49 +01:00
Michael Krasnyk b57169e221 Flush stxxl vectors before using in PrepareData 2016-11-12 02:09:51 +01:00
Lev Dragunov 045d25041f Review fixes. 2016-11-12 02:05:48 +01:00
Lev Dragunov 170923874b Add request duration to routed logs. 2016-11-12 02:05:48 +01:00
Dane Springmeyer 8137e95fbb Merge pull request #3274 from Project-OSRM/customize-tool-root
Improve support for customized build directory
2016-11-11 13:54:11 -08:00
Daniel J. Hofmann 0375af197d Skips OSM object metadata reading, closes #3278 2016-11-11 16:35:57 +01:00
Daniel J. Hofmann babbda98a6 Squashed 'third_party/libosmium/' changes from 80df1d6..40c4a48
40c4a48 Release v2.10.0
6addb2e Search for protozero also in the place where libosmium was found.
9c0d4bb Consistently use lhs and rhs as parameter names in operators etc.
6179759 Update change log.
894eb7d Explicitly use size_t to get no narrowing conversions.
e549e73 Fix CMake config for index_lookup.
ccf0bc2 Fix bug where some compilers deduce the wrong type.
fc3507d Cleaned and documented index example and renamed to osmium_index_lookup.
d3c3036 Rename serdump example to dump_internal and document it.
0e9822e Also forward set_uid_from_signed() function.
29ef95c Rename build_taglist function because it was to similar to build_tag_list.
c088dd0 Move static constant out of class so clang will compile it.
606cdc4 Fix CMake build script: Path for finding libosmium.
65f91fe Removed unused typedef.
07174f5 Use condition_variable to tell producer when thread queue is not full.
b35e957 Some code cleanup in XML parser.
c703dff Fix problem with MemberMeta.
1ccbbef Refactoring CompressionFactory.
6561bd6 Use our own exception type for map factory errors.
56e31fa Throw not_found error directly instead of using helper function.
28230c3 Test empty value for node location store, reorganize tests.
2ba316c Reorganize and fix projection tests.
f949485 Don't run quite as many tests with projections because they are slow.
1bad16d Add information about build environment to benchmark output.
99617bb Change proj_geojson benchmark into mercator benchmark.
553b946 Allow optional parameters on Reader in any order.
dcc3d8f Factor out some common code.
004d8cd Fix forwarding constructor.
9702978 Fix metadata check.
6cfb6c4 Faster implementation of decode_dense_nodes without reading metdata.
4ba4638 Add additional read_metadata parameter to other Reader constructors.
d005937 Optionally ignore metadata when reading file.
63961da Mark all CRC32 update functions as noexcept.
cc4ca75 Refactor set_user() function to speed it up.
38d19dc Update comments with file sizes. OSM has grown...
f7d0824 Add new benchmark that shows performance when main thread is busy.
25070dc Use const ref params.
88e8d96 Mark add_user() as deprecated.
f58d9db Refactor some low-level collection code to clean up code.
4680def Add example showing how to create OSM data out of thin air.
d42fd50 Add an example showing how tags in OSM files can be changed.
49bf5bc Add additional constructors to Builders taking a reference to parent.
7b91d63 Change Builder::add_item() to take a reference instead of pointer.
2957e48 Some cleanup of examples.
d0b458d Calculate size of object at compile time.
3fbb6e7 Use explicit cast.
1851f3d Remove a test that depends on math details.
f6a0802 Various cleanups of example programs.
ba4921f Rename add_user() to set_user().
d7637c9 Various cleanups related to builders.
07827bc Fix add_user().
9a5b395 Also refactor OSMObjectBuilder like ChangesetBuilder before.
b1f423c Use call chaining on the builder.
e49473d Get rid of ObjectBuilder class.
67d70b9 Refactor ChangesetBuilder::add_user().
8199c33 Make ChangesetBuilder derive directly from Builder.
61d1b67 Simplify some code.
d38467a Change derivation hierarchy of some builder classes.
b52f8af Refactor Builder code.
d012bfa Refactored some code setting attributes on objects using builder instead.
6a05f60 Also forward set_removed function from builders.
8d63b7d Return *this from Builder setter functions and test it.
72a1266 Update catch.hpp to newest version.
3424a74 Check GEOS version is <= 3.5.
aee9f9d Cleanup test code.
aef198c Improved asserts in Buffer.
a98b9bf Code cleanup in tests.
a150466 Use GDAL/OGR instead of GEOS to test our WKB implementation.
b04a525 Refactor test.
39aa932 Refactored test_factory_with_projection so it works without GEOS.
648f43a Remove unused dependency on geos from tile test.
f1748ae Add setters to Builder classes forwarding to underlying objects.
8166879 In debug mode check that Builders are correctly called and destructed.
1c4257e Call commit() on buffer only after all builders are destructed.
2618636 Add functions to check availability of relation members.
b45a4d9 Mark RelationMember::set_ref() as deprecated.
7886771 Move "basic" and "buffer" tests to "osm" and "memory", respectively.
b664685 Use functions instead of macros in location test for faster compile.
b4929ac Add more tests for number parser.
02662a7 Merge pull request #171 from lonvia/fix-long-exponentials
5344a6c fix parsing of numbers in e-notiation with many post-comma digits
3aeaff3 Add some typedefs to NodeRefList and memory::Collection.
e750665 Add iterators to IdSetSmall and add docs and tests to IdSet classes.
50ecb2a Add more features to IdSetDense, including unset and iterator.
e3dec78 Make IdSet virtual base class with two implementations.
8ea0153 Use C array instead of std::array in IdSet and clear explicitly.
3ba9905 Deprecate osmium::index::BoolVector in favour of new IdSet.
453d1ca Add osmium::index::IdSet.
c78254e Add function to (temporarily) disable the progress bar.
4d88a9f Better document osmium::io::Header class.
320e3af Look for protozero includes in CMake config.
838d25e Allow optional checking for libosmium version number in CMake config.
6ce60c1 Fix entity_bits static_assert() tests.
f054731 Update change log.
77ac4c2 Make sleep duration for full queues much smaller.
7e39c01 Make some entity_bits functions constexpr.
69ea72f Fix ~ operator on entity_bits and more tests for entity bits.
dafe4cf Update embedded Catch unit test header to version 1.5.7.
a41c832 Fixed parsing of location coordinates starting with decimal dot.
6523bae README cosmetics.
229acac Add tests for some examples.
f1e753d Merge pull request #163 from sebastic/executable-not-elf-or-script
ccea2d5 Remove executable bit from .cpp files.
af77fb4 Changelog formatting fixes.

git-subtree-dir: third_party/libosmium
git-subtree-split: 40c4a48f88d25edace6f0b9e079c306308c7760b
2016-11-11 15:50:02 +01:00
Daniel J. Hofmann 72bfbed1f1 Merge commit 'babbda98a6ea1d53a8bc5015ef5dfb313c47186a' into libosmium-2.10.0 2016-11-11 15:50:02 +01:00
Daniel J. Hofmann feeae05f1c Update Libosmium Dependency Script 2016-11-11 15:16:07 +01:00
Moritz Kobitzsch f88ac989ea reserve when possible 2016-11-11 14:48:50 +01:00
Dane Springmeyer 41f083cded test customized build directory, make test/data/Makefile customizable 2016-11-10 11:56:51 -08:00
Patrick Niklaus 12ded539aa Merge pull request #3235 from Project-OSRM/mason-improvements
Mason improvements
2016-11-10 16:58:18 +01:00
Moritz Kobitzsch 827a1fbd7a separate intersection generation and intersection normalization 2016-11-10 12:56:46 +01:00
Moritz Kobitzsch e84a0ea37c reduce coordinate_extraction overhead. slowdown reduced by 30 percent 2016-11-10 10:44:54 +01:00
Moritz Kobitzsch 88208bfa5d add testscases for mode changes / additional assertions 2016-11-09 12:55:28 +01:00
Moritz Kobitzsch 7073403f1b rip out dedicated file for single function (minor refactor) 2016-11-09 12:52:39 +01:00
Michael Krasnyk 2501882adb Remove duplicated linking of boost and tbb libraries 2016-11-09 12:44:49 +01:00
Michael Krasnyk 4f2bb19b0f Use single precision values in vector<float> initializer list (#3270) 2016-11-08 21:06:55 -08:00
Dane Springmeyer de77befb23 Merge commit 'a5db3d72f1bc9a8253e327a18d535d244a635b6a' into mason-improvements 2016-11-08 15:30:44 -08:00
Dane Springmeyer a5db3d72f1 Squashed 'third_party/mason/' changes from 1b3085e..8df1478
58ae447 bump to v0.1.1
c5ef33f rename llvm 4.x to 4.0.0 [skip ci]
5d5d26b add llvm 4.x based sub-packages
9708680 only set LIBCXX_ENABLE_STATIC_ABI_LIBRARY for linux [skip ci]
6918fb0 install LLVMgold.so on linux [skip ci]
ab20ff7 binutils: using 'all-gold' breaks make install on linux [skip ci]
cb8b15f fix binutils install [skip ci]
df77b02 properly set LLVM_BINUTILS_INCDIR value [skip ci]
295d4db binutils gold fixes [skip ci]
ac85676 enable LLVMgold.so for linux [skip ci]
acc4249 add binutils 2.27
16d4452 add lldb and llvm-cov 3.8.1 packages
757b908 remove patching no longer needed [skip ci]
69415b5 better fix for statically linking/linked libc++ with llvm 3.8.1 [skip ci]
43933ed Added mesa-13.0.0-glx (non-CXX11ABI)
2bb81cc Added mesa-13.0.0-glx
d70e3ef LLVM_EXTERNALIZE_DEBUGINFO is osx specific
ba737bf llvm 3.8.1 linux build fixes
4279f58 Updates for mesa 13.0.0
d544278 Revert typo in mason.sh
03ecb2c Add mesa 13.0.0 (Gallium-OSMesa)
0997905 Add expat 2.2.0
f41eb6d mason.cmake: multiple static libs also need to be split
c9fcd1a add lldb to llvm 3.8.1 [skip ci]
6d8e16c minor llvm/clang++ improvements
b2bdb33 Add note that we need to create a github release [skip ci]

git-subtree-dir: third_party/mason
git-subtree-split: 8df14782dda0c2c7314b5c6dba98e9e36a67eedc
2016-11-08 15:30:44 -08:00
Dane Springmeyer b8898ef410 mason improvements 2016-11-08 15:29:49 -08:00
422 changed files with 18231 additions and 10470 deletions
+7
View File
@@ -0,0 +1,7 @@
{
"presets": [
"stage-0",
"es2015",
"react"
]
}
+58 -45
View File
@@ -13,6 +13,7 @@ notifications:
branches:
only:
- master
- 5.5
cache:
ccache: true
@@ -25,7 +26,8 @@ env:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- CASHER_TIME_OUT=599 # one second less than 10m to avoid 10m timeout error: https://github.com/Project-OSRM/osrm-backend/issues/2742
- JOBS=4
- CCACHE_VERSION=3.3.1
- CMAKE_VERSION=3.6.2
matrix:
fast_finish: true
@@ -39,7 +41,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON BUILD_COMPONENTS=ON
- os: linux
@@ -47,34 +49,45 @@ matrix:
addons: &clang38
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CLANG_VERSION='3.8.1' CLANG_PACKAGE="clang++" BUILD_TYPE='Debug' RUN_CLANG_FORMAT=ON BUILD_COMPONENTS=ON CUCUMBER_TIMEOUT=60000
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CLANG_VERSION='3.8.1' BUILD_TYPE='Debug' RUN_CLANG_FORMAT=ON BUILD_COMPONENTS=ON CUCUMBER_TIMEOUT=60000
- os: osx
osx_image: xcode7.3
compiler: clang
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Debug' JOBS=1 CUCUMBER_TIMEOUT=60000
osx_image: xcode8.2
compiler: "mason-osx-release"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON
# Release Builds
- os: linux
compiler: "mason-release"
compiler: "mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'ccache']
env: BUILD_TYPE='Release' ENABLE_MASON=ON
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='3.8.1' BUILD_TYPE='Release' ENABLE_MASON=ON
- os: linux
compiler: "gcc-6-release"
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_COMPONENTS=ON
- os: linux
compiler: "gcc-6-release-i686"
env: TARGET_ARCH='i686' CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
env: >
TARGET_ARCH='i686' CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
CFLAGS='-m32 -msse2 -mfpmath=sse' CXXFLAGS='-m32 -msse2 -mfpmath=sse'
- os: linux
compiler: "gcc-4.9-release"
addons: &gcc49
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
# Disabled because of CI slowness
#- os: linux
@@ -85,19 +98,13 @@ matrix:
#- 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: osx
#- osx_image: xcode7.3
#- compiler: clang
#- env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Release'
# Shared Library
- os: linux
compiler: "gcc-6-release-shared"
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON BUILD_COMPONENTS=ON
# Disabled because CI slowness
@@ -111,24 +118,36 @@ matrix:
before_install:
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
- if [[ $(uname -s) == 'Darwin' ]]; then sudo mdutil -i off /; fi;
- source ./scripts/install_node.sh 4
- npm install
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- export PATH=${DEPS_DIR}/bin:${PATH} && mkdir -p ${DEPS_DIR}
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/3.5.2.tar.gz"
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
- |
if [[ ${CLANG_VERSION:-false} != false ]]; then
export CCOMPILER='clang'
export CXXCOMPILER='clang++'
CLANG_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/${CLANG_PACKAGE}/${CLANG_VERSION}.tar.gz"
travis_retry wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
export JOBS=$((`nproc` + 1))
fi
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
# implicit deps, but seem to be installed by default with recent images: libxml2 GDAL boost
brew install libzip libstxxl lua51 luabind tbb md5sha1sum ccache
export JOBS=$((`sysctl -n hw.ncpu` + 1))
sudo mdutil -i off /
fi
- echo "Using ${JOBS} jobs"
- source ./scripts/install_node.sh 4
- npm install -g "npm@>=3" # Upgrade to npm >v2 to reduce size of downloaded dependencies
- npm install
- ./third_party/mason/mason install ccache ${CCACHE_VERSION}
- export PATH=$(./third_party/mason/mason prefix ccache ${CCACHE_VERSION})/bin:${PATH}
- ./third_party/mason/mason install cmake ${CMAKE_VERSION}
- export PATH=$(./third_party/mason/mason prefix cmake ${CMAKE_VERSION})/bin:${PATH}
- |
if [[ ! -z ${CLANG_VERSION} ]]; then
export CCOMPILER='clang'
export CXXCOMPILER='clang++'
./third_party/mason/mason install clang++ ${CLANG_VERSION}
export PATH=$(./third_party/mason/mason prefix clang++ ${CLANG_VERSION})/bin:${PATH}
# we only enable lto for release builds
# and therefore don't need to us ld.gold or llvm tools for linking
# for debug builds
if [[ ${BUILD_TYPE} == 'Release' ]]; then
./third_party/mason/mason install binutils 2.27
export PATH=$(./third_party/mason/mason prefix binutils 2.27)/bin:${PATH}
fi
fi
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
@@ -137,11 +156,11 @@ install:
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
./scripts/check_taginfo.py taginfo.json profiles/car.lua
fi
- mkdir build && pushd build
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_MASON=${ENABLE_MASON:-OFF} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DENABLE_COVERAGE=${ENABLE_COVERAGE:-OFF} -DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} -DBUILD_TOOLS=ON -DBUILD_COMPONENTS=${BUILD_COMPONENTS:-OFF} -DENABLE_CCACHE=ON
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_MASON=${ENABLE_MASON:-OFF} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS:-OFF} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DENABLE_COVERAGE=${ENABLE_COVERAGE:-OFF} -DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} -DBUILD_TOOLS=ON -DBUILD_COMPONENTS=${BUILD_COMPONENTS:-OFF} -DENABLE_CCACHE=ON
- echo "travis_fold:start:MAKE"
- make osrm-extract --jobs=3
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
- make benchmarks --jobs=${JOBS}
@@ -153,17 +172,11 @@ install:
sudo ldconfig
fi
- popd
- |
if [[ ${ENABLE_MASON:-OFF} == 'ON' ]]; then
# for mason builds we need to point the example
# at the clang++ installed by the CMakeLists.txt automatically
export CXX=$(./third_party/mason/mason prefix clang++ 3.8.1)/bin/clang++
export CC=$(./third_party/mason/mason prefix clang++ 3.8.1)/bin/clang
fi
- mkdir example/build && pushd example/build
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
- make
- make --jobs=${JOBS}
- popd
- npm run build-api-docs
script:
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
@@ -172,7 +185,7 @@ script:
- 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
- pushd ${OSRM_BUILD_DIR}
- ./unit_tests/library-tests ../test/data/monaco.osrm
- ./unit_tests/extractor-tests
- ./unit_tests/engine-tests
+33
View File
@@ -1,3 +1,22 @@
# 5.5.3
- Changes from 5.5.2
- Bugfixes:
- PR #3504 - debug tiles were very slow to generate due to unnecessarily copying data in a hot loop.
- PR #3556 - fix an assertion in the walking profile triggered by tight spiral stairwells
- PR #3469 - don't assert when identical coordinates are supplied to some calculations - OSM data contains these, we shouldn't crash.
- Enhancements:
- backported 6ea9f9fdf19 - when anticipating upcoming lanes, consider how many lanes need to be crossed to get there.
- when using osrm-datastore, it will attempt to clean up locks if it crashes.
# 5.5.2
- Changes from 5.5.1
- Revert smarter map-matching search radius. The increased radius causes performance degredation when map-matching against non-car road networks with more edges.
# 5.5.1
- Changes from 5.5.0
- Bugfixes
- Fixes #3455 where a deadlock could occur if re-loading new data under heavy load with multiple consumers osrm-datastore
# 5.5.0
- Changes from 5.4.0
- API:
@@ -5,6 +24,10 @@
- Shared memory now allows for multiple clients (multiple instances of libosrm on the same segment)
- Polyline geometries can now be requested with precision 5 as well as with precision 6
- Profiles
- the car profile has been refactored into smaller functions
- get_value_by_key() is now guaranteed never to return empty strings, nil is returned instead.
- debug.lua was added to make it easier to test/develop profile code.
- `car.lua` now depends on lib/set.lua and lib/sequence.lua
- `restrictions` is now used for namespaced restrictions and restriction exceptions (e.g. `restriction:motorcar=` as well as `except=motorcar`)
- replaced lhs/rhs profiles by using test defined profiles
- Handle `oneway=alternating` (routed over with penalty) separately from `oneway=reversible` (not routed over due to time dependence)
@@ -15,6 +38,7 @@
- Improved turn angle calculation, detecting offsets due to lanes / minor variations due to inaccuracies
- Corrected the bearings returned for intermediate steps - requires reprocessing
- Improved turn locations for collapsed turns
- Sliproad classification refinements: the situations we detect as Sliproads now resemble more closely the reality
- Trip Plugin
- changed internal behaviour to prefer the smallest lexicographic result over the largest one
- Bugfixes
@@ -22,8 +46,17 @@
- fixed compile errors in tile unit-test framework
- fixed a bug that could result in inconsistent behaviour when collapsing instructions
- fixed a bug that could result in crashes when leaving a ferry directly onto a motorway ramp
- fixed a bug in the tile plugin that resulted in discovering invalid edges for connections
- improved error messages when missing files during traffic updates (#3114)
- For single coordinate geometries the GeoJSON `Point` encoding was broken. We now always emit `LineString`s even in the one-coordinate-case (backwards compatible) (#3425)
- Debug Tiles
- Added support for turn penalties
- Internals
- Internal/Shared memory datafacades now share common memory layout and data loading code
- File reading now has much better error handling
- Misc
- Progress indicators now print newlines when stdout is not a TTY
- Prettier API documentation now generated via `npm run build-api-docs` output `build/docs`
# 5.4.3
- Changes from 5.4.2
+135 -65
View File
@@ -7,6 +7,13 @@ Please create a directory and run cmake from there, passing the path to this sou
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
endif()
# detect if this is included as subproject and if so expose
# some variables to its parent scope
get_directory_property(BUILD_AS_SUBPROJECT PARENT_DIRECTORY)
if(BUILD_AS_SUBPROJECT)
message(STATUS "Building libosrm as subproject.")
endif()
option(ENABLE_MASON "Use mason for dependencies" OFF)
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
option(BUILD_TOOLS "Build OSRM tools" OFF)
@@ -19,43 +26,47 @@ option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
if(ENABLE_MASON)
# versions in use
set(MASON_CLANG_VERSION "3.8.1")
set(MASON_BOOST_VERSION "1.61.0")
set(MASON_STXXL_VERSION "1.4.1")
set(MASON_EXPAT_VERSION "2.1.1")
set(MASON_EXPAT_VERSION "2.2.0")
set(MASON_LUA_VERSION "5.2.4")
set(MASON_LUABIND_VERSION "e414c57bcb687bb3091b7c55bbff6947f052e46b")
set(MASON_BZIP2_VERSION "1.0.6")
set(MASON_TBB_VERSION "43_20150316")
set(MASON_CCACHE_VERSION "3.3.1")
message(STATUS "Enabling mason")
find_program(CURL_FOUND curl)
if(NOT CURL_FOUND)
message(FATAL_ERROR "curl command required with -DENABLE_MASON")
endif()
set(MASON_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/third_party/mason/mason)
include(${CMAKE_CURRENT_SOURCE_DIR}/third_party/mason/mason.cmake)
if(NOT CMAKE_CXX_COMPILER)
mason_use(clang++ VERSION ${MASON_CLANG_VERSION})
message(STATUS "Setting compiler to clang++ ${MASON_CLANG_VERSION} (via mason) ${MASON_PACKAGE_clang++_PREFIX}/bin/clang++")
set(CMAKE_CXX_COMPILER "${MASON_PACKAGE_clang++_PREFIX}/bin/clang++")
set(CMAKE_C_COMPILER "${MASON_PACKAGE_clang++_PREFIX}/bin/clang")
endif()
endif()
# be compatible with version handling before cmake 3.x
if (POLICY CMP0048)
cmake_policy(SET CMP0048 OLD)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 4)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION_MINOR 5)
set(OSRM_VERSION_PATCH 3)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
# these two functions build up custom variables:
# OSRM_INCLUDE_PATHS and OSRM_DEFINES
# DEPENDENCIES_INCLUDE_DIRS and OSRM_DEFINES
# These variables we want to pass to
# include_directories and add_definitions for both
# this build and for sharing externally via pkg-config
function(add_dependency_includes includes)
list(APPEND OSRM_INCLUDE_PATHS "${includes}")
set(OSRM_INCLUDE_PATHS "${OSRM_INCLUDE_PATHS}" PARENT_SCOPE)
list(APPEND DEPENDENCIES_INCLUDE_DIRS "${includes}")
set(DEPENDENCIES_INCLUDE_DIRS "${DEPENDENCIES_INCLUDE_DIRS}" PARENT_SCOPE)
endfunction(add_dependency_includes)
function(add_dependency_defines defines)
@@ -83,7 +94,7 @@ endif()
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/variant/include)
add_custom_target(FingerPrintConfigure ALL ${CMAKE_COMMAND}
"-DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}"
@@ -129,6 +140,7 @@ if(ENABLE_GOLD_LINKER)
if("${LD_VERSION}" MATCHES "GNU gold")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
message(STATUS "Using GNU gold as linker.")
# Issue 2785: check gold binutils version and don't use gc-sections for versions prior 2.25
@@ -183,7 +195,8 @@ endif()
if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "Configuring release mode optimizations")
# Check if LTO is available
check_cxx_compiler_flag("-flto" LTO_AVAILABLE)
check_cxx_compiler_flag("-Wl,-flto" LTO_AVAILABLE)
if(ENABLE_LTO AND LTO_AVAILABLE)
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# GCC in addition allows parallelizing LTO
@@ -198,27 +211,57 @@ if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CM
check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS)
if(LTO_WORKS)
message(STATUS "LTO working")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -flto")
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} -flto")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -flto")
else()
message(STATUS "LTO broken")
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
set(ENABLE_LTO Off)
endif()
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW)
message(STATUS "Using gcc specific binutils for LTO.")
set(CMAKE_AR "/usr/bin/gcc-ar")
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
find_program(GCC_AR gcc-ar)
find_program(GCC_RANLIB gcc-ranlib)
if ("${GCC_AR}" STREQUAL "GCC_AR-NOTFOUND" OR "${GCC_RANLIB}" STREQUAL "GCC_RANLIB-NOTFOUND")
message(WARNING "GCC specific binutils not found.")
else()
message(STATUS "Using GCC specific binutils for LTO:")
message(STATUS " ${GCC_AR}")
message(STATUS " ${GCC_RANLIB}")
set(CMAKE_AR ${GCC_AR})
set(CMAKE_RANLIB ${GCC_RANLIB})
endif()
endif()
# Same for clang LTO requires their own toolchain
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
find_program(LLVM_AR llvm-ar)
find_program(LLVM_RANLIB llvm-ranlib)
if ("${LLVM_AR}" STREQUAL "LLVM_AR-NOTFOUND" OR "${LLVM_RANLIB}" STREQUAL "LLVM_RANLIB-NOTFOUND")
message(WARNING "LLVM specific binutils not found.")
else()
message(STATUS "Using LLVM specific binutils for LTO:")
message(STATUS " ${LLVM_AR}")
message(STATUS " ${LLVM_RANLIB}")
set(CMAKE_AR ${LLVM_AR})
set(CMAKE_RANLIB ${LLVM_RANLIB})
endif()
endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
message(STATUS "Disabling LTO on GCC < 4.9.0 since it is broken, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57038")
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
set(ENABLE_LTO Off)
endif()
endif()
endif()
if (ENABLE_MASON AND (LTO_WORKS OR ENABLE_GOLD_LINKER))
if(UNIX AND NOT APPLE AND ENABLE_MASON AND (LTO_WORKS OR ENABLE_GOLD_LINKER))
message(WARNING "ENABLE_MASON and ENABLE_LTO/ENABLE_GOLD_LINKER may not work on all linux systems currently")
message(WARNING "For more details see: https://github.com/Project-OSRM/osrm-backend/issues/3202")
endif()
@@ -234,6 +277,7 @@ if (ENABLE_COVERAGE)
endif()
if (ENABLE_SANITIZER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -fsanitize=address")
endif()
# Configuring compilers
@@ -280,9 +324,11 @@ if("${LINKER_VERSION}" MATCHES "GNU gold" OR "${LINKER_VERSION}" MATCHES "GNU ld
endif()
# Default linker optimization flags
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-O1 -Wl,--hash-style=gnu -Wl,--sort-common")
else()
message(STATUS "Using unknown linker, not setting linker optimizations")
endif ()
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} ${LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
@@ -290,6 +336,7 @@ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
# Activate C++1y
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y")
endif()
# Configuring other platform dependencies
@@ -371,18 +418,21 @@ if(ENABLE_MASON)
if(NOT MASON_PACKAGE_tbb_LIBRARY_DIRS)
message(FATAL_ERROR "MASON_PACKAGE_tbb_LIBRARY_DIRS is empty, rpath will not work")
endif()
set(TBB_LINKER_RPATHS "")
foreach(libpath ${MASON_PACKAGE_tbb_LIBRARY_DIRS})
if(UNIX AND NOT APPLE)
set(LINKER_FLAGS "-Wl,-rpath,${libpath}")
elseif(APPLE)
set(LINKER_FLAGS "-Wl,-rpath, -Wl,${libpath}")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(TBB_LINKER_RPATHS "${TBB_LINKER_RPATHS} -Wl,-rpath -Wl,${libpath}")
file(GLOB TBBGlob ${libpath}/*.*)
install(FILES ${TBBGlob} DESTINATION lib)
endforeach()
if(APPLE)
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} -Wl,-rpath -Wl,@executable_path")
elseif(UNIX)
set(LINKER_FLAGS "${TBB_LINKER_RPATHS} '-Wl,-rpath,$ORIGIN' -Wl,-z,origin")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
if(BUILD_COMPONENTS)
message(FATAL_ERROR "BUILD_COMPONENTS is not supported with ENABLE_MASON")
@@ -391,14 +441,9 @@ if(ENABLE_MASON)
# current mason packages target -D_GLIBCXX_USE_CXX11_ABI=0
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=0")
if(ENABLE_CCACHE)
mason_use(ccache VERSION ${MASON_CCACHE_VERSION})
message(STATUS "Setting ccache to ccache ${MASON_CCACHE_VERSION} (via mason) ${MASON_PACKAGE_ccache_PREFIX}/bin/ccache")
message(STATUS "Using ccache to speed up incremental builds")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${MASON_PACKAGE_ccache_PREFIX}/bin/ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${MASON_PACKAGE_ccache_PREFIX}/bin/ccache)
set(ENV{CCACHE_CPP2} "true")
endif()
# note: we avoid calling find_package(Osmium ...) here to ensure that the
# expat and bzip2 are used from mason rather than the system
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include)
else()
@@ -439,29 +484,30 @@ else()
)
endif()
# prefix compilation with ccache by default if available and on clang or gcc
if(ENABLE_CCACHE AND (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"))
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
message(STATUS "Using ccache to speed up incremental builds")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
set(ENV{CCACHE_CPP2} "true")
endif()
endif()
# note libosmium depends on expat and bzip2
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/cmake")
set(OSMIUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include")
find_package(Osmium REQUIRED COMPONENTS io)
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
endif()
# prefix compilation with ccache by default if available and on clang or gcc
if(ENABLE_CCACHE AND (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"))
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
message(STATUS "Using ccache to speed up incremental builds")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
set(ENV{CCACHE_CPP2} "true")
endif()
endif()
# even with mason builds we want to link to system zlib
# to ensure that osrm binaries play well with other binaries like nodejs
find_package(ZLIB REQUIRED)
add_dependency_includes(${ZLIB_INCLUDE_DIRS})
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/cmake")
set(OSMIUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include")
find_package(Osmium REQUIRED COMPONENTS io)
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
if(NOT WIN32 AND NOT Boost_USE_STATIC_LIBS)
add_dependency_defines(-DBOOST_TEST_DYN_LINK)
endif()
@@ -483,7 +529,7 @@ if(OPENMP_FOUND)
endif()
add_definitions(${OSRM_DEFINES})
include_directories(SYSTEM ${OSRM_INCLUDE_PATHS})
include_directories(SYSTEM ${DEPENDENCIES_INCLUDE_DIRS})
set(BOOST_BASE_LIBRARIES
${Boost_DATE_TIME_LIBRARY}
@@ -499,10 +545,10 @@ set(BOOST_ENGINE_LIBRARIES
${BOOST_BASE_LIBRARIES})
# Binaries
target_link_libraries(osrm-datastore osrm_store ${Boost_PROGRAM_OPTIONS_LIBRARY} ${BOOST_BASE_LIBRARIES})
target_link_libraries(osrm-extract osrm_extract ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_REGEX_LIBRARY} ${BOOST_BASE_LIBRARIES})
target_link_libraries(osrm-contract ${Boost_PROGRAM_OPTIONS_LIBRARY} ${BOOST_BASE_LIBRARIES} ${TBB_LIBRARIES} osrm_contract)
target_link_libraries(osrm-routed osrm ${Boost_PROGRAM_OPTIONS_LIBRARY} ${BOOST_ENGINE_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
target_link_libraries(osrm-datastore osrm_store ${Boost_PROGRAM_OPTIONS_LIBRARY})
target_link_libraries(osrm-extract osrm_extract ${Boost_PROGRAM_OPTIONS_LIBRARY})
target_link_libraries(osrm-contract osrm_contract ${Boost_PROGRAM_OPTIONS_LIBRARY})
target_link_libraries(osrm-routed osrm ${Boost_PROGRAM_OPTIONS_LIBRARY} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
set(EXTRACTOR_LIBRARIES
${BZIP2_LIBRARIES}
@@ -593,7 +639,7 @@ set_property(TARGET osrm-contract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
file(GLOB VariantGlob third_party/variant/*.hpp)
file(GLOB VariantGlob third_party/variant/include/mapbox/*.hpp)
file(GLOB LibraryGlob include/osrm/*.hpp)
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/phantom_node.hpp)
@@ -608,7 +654,7 @@ install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
install(FILES ${LibraryGlob} DESTINATION include/osrm)
install(FILES ${ParametersGlob} DESTINATION include/osrm/engine/api)
install(FILES ${VariantGlob} DESTINATION include/variant)
install(FILES ${VariantGlob} DESTINATION include/mapbox)
install(TARGETS osrm-extract DESTINATION bin)
install(TARGETS osrm-contract DESTINATION bin)
install(TARGETS osrm-datastore DESTINATION bin)
@@ -618,9 +664,8 @@ install(TARGETS osrm_extract DESTINATION lib)
install(TARGETS osrm_contract DESTINATION lib)
install(TARGETS osrm_store DESTINATION lib)
foreach(lib ${ENGINE_LIBRARIES})
set(ENGINE_LIBRARY_LISTING "${ENGINE_LIBRARY_LISTING} ${lib}")
endforeach()
# Setup exporting variables for pkgconfig and subproject
#
if(BUILD_DEBIAN_PACKAGE)
include(CPackDebianConfig)
@@ -632,9 +677,33 @@ function(JOIN VALUES GLUE OUTPUT)
set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
endfunction()
# Set up variables, then write to pkgconfig file
JOIN("${OSRM_DEFINES}" " " OSRM_DEFINES_STRING)
JOIN("-I${OSRM_INCLUDE_PATHS}" " -I" OSRM_INCLUDE_PATHS_STRING)
JOIN("${OSRM_DEFINES}" " " TMP_OSRM_DEFINES)
set(LibOSRM_CXXFLAGS "${OSRM_CXXFLAGS} ${TMP_OSRM_DEFINES}")
set(LibOSRM_LDFLAGS "${OSRM_LDFLAGS}")
if(BUILD_AS_SUBPROJECT)
set(LibOSRM_CXXFLAGS "${LibOSRM_CXXFLAGS}" PARENT_SCOPE)
set(LibOSRM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE)
set(LibOSRM_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
set(LibOSRM_LIBRARIES "osrm" PARENT_SCOPE)
set(LibOSRM_DEPENDENT_LIBRARIES "${ENGINE_LIBRARIES}" PARENT_SCOPE)
set(LibOSRM_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/include/osrm"
"${CMAKE_CURRENT_SOURCE_DIR}/third_party"
"${DEPENDENCIES_INCLUDE_DIRS}" PARENT_SCOPE)
set(LibOSRM_LIBRARY_DIRS "${LibOSRM_LIBRARY_DIR}" PARENT_SCOPE)
endif()
# pkgconfig defines
set(PKGCONFIG_OSRM_CXXFLAGS "${LibOSRM_CXXFLAGS}")
set(PKGCONFIG_OSRM_LDFLAGS "${LibOSRM_LDFLAGS}")
set(PKGCONFIG_LIBRARY_DIR "${CMAKE_INSTALL_PREFIX}/lib")
set(PKGCONFIG_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include")
list(APPEND DEPENDENCIES_INCLUDE_DIRS "${PKGCONFIG_INCLUDE_DIR}")
list(APPEND DEPENDENCIES_INCLUDE_DIRS "${PKGCONFIG_INCLUDE_DIR}/osrm")
JOIN("-I${DEPENDENCIES_INCLUDE_DIRS}" " -I" PKGCONFIG_OSRM_INCLUDE_FLAGS)
JOIN("${ENGINE_LIBRARIES}" " " PKGCONFIG_OSRM_DEPENDENT_LIBRARIES)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
@@ -660,6 +729,7 @@ if (ENABLE_FUZZING)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-coverage=edge,indirect-calls,8bit-counters -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} -fsanitize=address")
message(STATUS "Using -fsanitize=${FUZZ_SANITIZER} for Fuzz testing")
+1 -1
View File
@@ -4,7 +4,7 @@ set(INFILE ${SOURCE_DIR}/include/util/fingerprint_impl.hpp.in)
file(MD5 ${SOURCE_DIR}/src/tools/contract.cpp MD5PREPARE)
file(MD5 ${SOURCE_DIR}/include/util/static_rtree.hpp MD5RTREE)
file(MD5 ${SOURCE_DIR}/include/util/graph_loader.hpp MD5GRAPH)
file(MD5 ${SOURCE_DIR}/include/engine/datafacade/internal_datafacade.hpp MD5OBJECTS)
file(MD5 ${SOURCE_DIR}/src/storage/storage.cpp MD5OBJECTS)
CONFIGURE_FILE(${INFILE} ${NEWFILE})
+6 -6
View File
@@ -1,11 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
includedir=${prefix}/include
libdir=${prefix}/lib
includedir=@PKGCONFIG_INCLUDE_DIR@
libdir=@PKGCONFIG_LIBRARY_DIR@
Name: libOSRM
Description: Project OSRM library
Version: v@OSRM_VERSION_MAJOR@.@OSRM_VERSION_MINOR@.@OSRM_VERSION_PATCH@
Version: v@OSRM_VERSION@
Requires:
Libs: -L${libdir} -losrm
Libs.private: @ENGINE_LIBRARY_LISTING@
Cflags: -I${includedir} -I${includedir}/osrm @OSRM_INCLUDE_PATHS_STRING@ @OSRM_DEFINES_STRING@ @CMAKE_CXX_FLAGS@
Libs: -L${libdir} -losrm @PKGCONFIG_OSRM_LDFLAGS@
Libs.private: @PKGCONFIG_OSRM_DEPENDENT_LIBRARIES@
Cflags: @PKGCONFIG_OSRM_INCLUDE_FLAGS@ @PKGCONFIG_OSRM_CXXFLAGS@
+336 -281
View File
@@ -1,50 +1,43 @@
## Environent Variables
## General options
### SIGNAL_PARENT_WHEN_READY
All OSRM HTTP requests use a common structure.
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.
The following syntax applies to all services, except as noted.
### DISABLE_ACCESS_LOGGING
### Requests
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
```endpoint
GET /{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) | fastest 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 fastest 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 statically by the Lua profile that is used to prepare the data using `osrm-extract`.
- `coordinates`: String of format `{longitude},{latitude};{longitude},{latitude}[;{longitude},{latitude} ...]` or `polyline({polyline})`.
- `format`: Only `json` is supported at the moment. This parameter is optional and defaults to `json`.
| Parameter | Description |
| --- | --- |
| `service` | One of the following values: [`route`](#route-service), [`nearest`](#nearest-service), [`table`](#table-service), [`match`](#match-service), [`trip`](#trip-service), [`tile`](#tile-service) |
| `version` | Version of the protocol implemented by the service. `v1` for all OSRM 5.x installations |
| `profile` | Mode of transportation, is determined statically by the Lua profile that is used to prepare the data using `osrm-extract`. Typically `car`, `bike` or `foot` if using one of the supplied profiles. |
| `coordinates`| String of format `{longitude},{latitude};{longitude},{latitude}[;{longitude},{latitude} ...]` or `polyline({polyline})`. |
| `format`| Only `json` is supported 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 by default and can be generated using [this package](https://www.npmjs.com/package/polyline).
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:
**Request 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 from previous request 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` |
```
{option}={element};{element}[;{element} ... ]
```
@@ -57,48 +50,19 @@ Example: 2nd location use the default value for `option`:
{option}={element};;{element}
```
## General options
#### Example Requests
| 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
```curl
# Query on Berlin with three coordinates:
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false'
# Using polyline:
curl 'http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false'
```
Using polyline:
### Responses
```
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:
Every response object has a `code` field containing one of the strings below or a service dependent code:
| Type | Description |
|-------------------|----------------------------------------------------------------------------------|
@@ -112,18 +76,27 @@ Where `code` is on one of the strings below or service dependent:
| `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.
- `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`.
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
#### Example response
```json
{
"code": "Ok",
"message": "Everything worked"
}
```
http://{server}/nearest/v1/{profile}/{coordinates}.json?number={number}
## Services
### Nearest service
Snaps a coordinate to the street network and returns the nearest `n` matches.
```endpoint
GET http://{server}/nearest/v1/{profile}/{coordinates}.json?number={number}
```
Where `coordinates` only supports a single `{longitude},{latitude}` entry.
@@ -134,26 +107,62 @@ In addition to the [general options](#general-options) the following options are
|------------|------------------------------|----------------------------------------------------|
|number |`integer >= 1` (default `1`) |Number of nearest segments that should be returned. |
### Response
**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
#### Example Requests
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
```curl
# Querying nearest three snapped locations of `13.388860,52.517037` with a bearing between `20° - 340°`.
curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?number=3&bearings=0,20'
```
## Service `route`
### Request
#### Example Response
```json
{
"waypoints" : [
{
"hint" : "KSoKADRYroqUBAEAEAAAABkAAAAGAAAAAAAAABhnCQCLtwAA_0vMAKlYIQM8TMwArVghAwEAAQH1a66g",
"distance" : 4.152629,
"name" : "Friedrichstraße",
"location" : [
13.388799,
52.517033
]
},
{
"hint" : "KSoKADRYroqUBAEABgAAAAAAAAAAAAAAKQAAABhnCQCLtwAA7kvMAAxZIQM8TMwArVghAwAAAQH1a66g",
"distance" : 11.811961,
"name" : "Friedrichstraße",
"location" : [
13.388782,
52.517132
]
},
{
"hint" : "KioKgDbbDgCUBAEAAAAAABoAAAAAAAAAPAAAABlnCQCLtwAA50vMADJZIQM8TMwArVghAwAAAQH1a66g",
"distance" : 15.872438,
"name" : "Friedrichstraße",
"location" : [
13.388775,
52.51717
],
}
],
"code" : "Ok"
}
```
http://{server}/route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
### Route service
Finds the fastest route between coordinates in the supplied order.
```endpoint
GET /route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
```
In addition to the [general options](#general-options) the following options are supported for this service:
@@ -165,11 +174,11 @@ In addition to the [general options](#general-options) the following options are
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|continue_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. |
|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. |
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
### Response
**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:
@@ -183,23 +192,22 @@ In case of error the following `code`s are supported in addition to the general
All other fields might be undefined.
### Example
#### Example Request
Query on Berlin with three coordinates and no overview geometry returned:
```
http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false
```curl
# Query on Berlin with three coordinates and no overview geometry returned:
curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false'
```
## Service `table`
### Request
```
http://{server}/table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]`
### Table service
Computes the duration of the fastest route between all pairs of supplied coordinates.
```endpoint
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]
```
This computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
### Coordinates
**Coordinates**
In addition to the [general options](#general-options) the following options are supported for this service:
@@ -211,7 +219,7 @@ In addition to the [general options](#general-options) the following options are
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
to number of input locations;
Example:
**Example:**
```
sources=0;5;7&destinations=5;1;4;2;3;6
@@ -221,7 +229,20 @@ sources=0;5;7&destinations=5;1;4;2;3;6
|------------|-----------------------------|
|index |`0 <= integer < #locations` |
### Response
#### Example Request
```curl
# Returns a 3x3 matrix:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219'
# Returns a 1x3 matrix
curl '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`:
curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHulFzeMe`EuvKpnCglA)?sources=0;1;3&destinations=2;4'
```
**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
@@ -237,53 +258,39 @@ In case of error the following `code`s are supported in addition to the general
All other fields might be undefined.
#### Examples
### Match service
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/polyline(egs_Iq_aqAppHzbHulFzeMe`EuvKpnCglA)?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.
Map matching matches/snaps 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|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}
```endpoint
GET /match/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|polyline6|geojson}&overview={simplified|full|false}&annotations={true|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), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|annotations |`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. Timestamps need to be monotonically increasing. |
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. |
|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) |
|Parameter |Values |
|------------|-----------------------------------|
|timestamp |`integer` seconds since UNIX epoch |
|radius |`double >= 0` (default 5m) |
The radius for each point should be the standard error of the location measured in meters from the true location.
Use `Location.getAccuracy()` on Android or `CLLocation.horizontalAccuracy` on iOS.
This value is used to determine which points should be considered as candidates (larger radius means more candidates) and how likely each candidate is (larger radius means far-away candidates are penalized less).
The area to search is chosen such that the correct candidate should be considered 99.9% of the time (for more details see [this ticket](https://github.com/Project-OSRM/osrm-backend/pull/3184)).
**Response**
### Response
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `tracepoints`: Array of `Waypoint` objects representing all points of the trace in order.
If the trace point was ommited by map matching because it is an outlier, the entry will be `null`.
@@ -301,17 +308,15 @@ In case of error the following `code`s are supported in addition to the general
All other fields might be undefined.
## Service `trip`
### Trip service
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm).
The returned path does not have to be the fastest path, as TSP is NP-hard it is only an approximation.
Note that 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|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}
```endpoint
GET /trip/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}'
```
In addition to the [general options](#general-options) the following options are supported for this service:
@@ -323,7 +328,7 @@ In addition to the [general options](#general-options) the following options are
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
### Response
**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:
@@ -339,23 +344,68 @@ In case of error the following `code`s are supported in addition to the general
All other fields might be undefined.
### Tile service
This service 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.
```endpoint
GET /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/).
#### Example request
```curl
# This fetches a Z=13 tile for downtown San Francisco:
curl 'http://router.project-osrm.org/tile/v1/car/tile(1310,3166,13).mvt'
```
#### Example response
> ![example rendered tile](images/example-tile-response.png)
> http://map.project-osrm.org/debug/#14.33/52.5212/13.3919
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 two layers:
`speeds` layer:
| Field | Type | Description |
| ------------ | --------- | ---------------------------------------- |
| `speed` | `integer` | the speed on that road segment, in km/h |
| `is_small` | `boolean` | whether this segment belongs to a small (< 1000 node) [strongly connected component](https://en.wikipedia.org/wiki/Strongly_connected_component) |
| `datasource` | `string` | the source for the speed value (normally `lua profile` unless you're using the [traffic update feature](https://github.com/Project-OSRM/osrm-backend/wiki/Traffic), in which case it contains the stem of the filename that supplied the speed value for this segment |
| `duration` | `float` | how long this segment takes to traverse, in seconds |
| `name` | `string` | the name of the road this segment belongs to |
`turns` layer:
| Field | Type | Description |
| ------------ | --------- | ---------------------------------------- |
| `bearing_in` | `integer` | the absolute bearing that approaches the intersection. -180 to +180, 0 = North, 90 = East |
| `turn_angle` | `integer` | the angle of the turn, relative to the `bearing_in`. -180 to +180, 0 = straight ahead, 90 = 90-degrees to the right |
| `cost` | `float` | the time we think it takes to make that turn, in seconds. May be negative, depending on how the data model is constructed (some turns get a "bonus"). |
## Result objects
### Route
### Route object
Represents a route through (potentially multiple) waypoints.
#### Properties
**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. |
| 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.
@@ -383,34 +433,34 @@ Three input coordinates, `geometry=geojson`, `steps=false`:
}
```
### RouteLeg
### RouteLeg object
Represents a route between two waypoints.
#### Properties
**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 | |
|--------------|-----------------------------------------------------------------------|
| 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 |
| 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:
| annotations | |
|--------------|-----------------------------------------------------------------------|
| true | An `Annotation` object containing node ids, durations and distances |
| false | `undefined` |
| annotations | |
|--------------|-----------------------------------------------------------------------|
| true | An `Annotation` object containing node ids, durations and distances |
| false | `undefined` |
#### Example
@@ -430,11 +480,11 @@ With `steps=false` and `annotations=true`:
}
```
### Annotation
### Annotation object
Annotation of the whole route leg with fine-grained information about each segment or node id.
#### Properties
**Properties**
- `distance`: The distance, in metres, between each pair of coordinates
- `duration`: The duration between each pair of coordinates, in seconds
@@ -453,24 +503,24 @@ Annotation of the whole route leg with fine-grained information about each segme
```
### RouteStep
### RouteStep object
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
**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 |
| polyline6 | [polyline](https://www.npmjs.com/package/polyline) with precision 6 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)|
| `geometry` | |
|------------|--------------------------------------------------------------------|
| polyline | [polyline](https://www.npmjs.com/package/polyline) with precision 5 in [latitude,longitude] encoding |
| polyline6 | [polyline](https://www.npmjs.com/package/polyline) with precision 6 in [latitude,longitude] encoding |
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) |
- `name`: The name of the way along which travel proceeds.
- `ref`: A reference number or code for the way. Optionally included, if ref data is available for the given way.
- `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit.
@@ -481,42 +531,49 @@ step.
#### Example
```
```json
{
"distance":152.3,
"duration":15.6,
"name":"Lortzingstraße",
"maneuver":{
"type":"turn",
"modifier":"right",
},
"geometry":"{lu_IypwpAVrAvAdI",
"mode":"driving",
"intersections":[
{"location":[13.39677,52.54366],
"in":3,
"out":2,
"bearings":[10,92,184,270],
"entry":["true","true","true","false"],
"lanes":[
{"indications":["left","straight"], "valid":"false"},
{"indications":["right"], "valid":"true"}
]},
{"location":[13.394718,52.543096],
"in":0,
"out":1,
"bearings":[60,240,330],
"entry":["false","true","true"]
"lanes":[
{"indications":["straight"], "valid":"true"},
{"indications":["right"], "valid":"false"}
]}
]}
"geometry" : "{lu_IypwpAVrAvAdI",
"mode" : "driving",
"duration" : 15.6,
"intersections" : [
{ "bearings" : [ 10, 92, 184, 270 ],
"lanes" : [
{ "indications" : [ "left", "straight" ],
"valid" : "false" },
{ "valid" : "true",
"indications" : [ "right" ] }
],
"out" : 2,
"in" : 3,
"entry" : [ "true", "true", "true", "false" ],
"location" : [ 13.39677, 52.54366 ]
},
{ "out" : 1,
"lanes" : [
{ "indications" : [ "straight" ],
"valid" : "true" },
{ "indications" : [ "right" ],
"valid" : "false" }
],
"bearings" : [ 60, 240, 330 ],
"in" : 0,
"entry" : [ "false", "true", "true" ],
"location" : [ 13.394718, 52.543096 ]
}
],
"name" : "Lortzingstraße",
"distance" : 152.3,
"maneuver" : {
"modifier" : "right",
"type" : "turn"
}
}
```
### StepManeuver
### StepManeuver object
#### Properties
**Properties**
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
- `bearing_before`: The clockwise angle from true north to the
@@ -526,79 +583,79 @@ step.
- `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/possible, 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`|
| `use lane` | going straight on a specific lane |
| `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/rotary_pronunciation` 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 |
| `type` | Description |
|------------------|--------------------------------------------------------------|
| `turn` | a basic turn into direction of the `modifier` |
| `new name` | no turn is taken/possible, 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`|
| `use lane` | going straight on a specific lane |
| `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 traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name/rotary_pronunciation` 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 |
| `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 |
| `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`/`rotary` | 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` |
| `type` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `roundabout`/`rotary` | 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.
### Lane
### Lane object
A `Lane` represents a turn lane at the corresponding turn location.
#### Properties
**Properties**
- `indications`: a indication (e.g. marking on the road) specifying the turn lane. A road can have multiple indications (e.g. an arrow pointing straight and left). The indications are given in an array, each containing one of the following types. Further indications might be added on without an API version change.
| `value` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `none` | No dedicated indication is shown. |
| `uturn` | An indication signaling the possibility to reverse (i.e. fully bend arrow). |
| `sharp right` | An indication indicating a sharp right turn (i.e. strongly bend arrow). |
| `right` | An indication indicating a right turn (i.e. bend arrow). |
| `slight right` | An indication indicating a slight right turn (i.e. slightly bend arrow). |
| `straight` | No dedicated indication is shown (i.e. straight arrow). |
| `slight left` | An indication indicating a slight left turn (i.e. slightly bend arrow). |
| `left` | An indication indicating a left turn (i.e. bend arrow). |
| `sharp left` | An indication indicating a sharp left turn (i.e. strongly bend arrow). |
| `value` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `none` | No dedicated indication is shown. |
| `uturn` | An indication signaling the possibility to reverse (i.e. fully bend arrow). |
| `sharp right` | An indication indicating a sharp right turn (i.e. strongly bend arrow). |
| `right` | An indication indicating a right turn (i.e. bend arrow). |
| `slight right` | An indication indicating a slight right turn (i.e. slightly bend arrow). |
| `straight` | No dedicated indication is shown (i.e. straight arrow). |
| `slight left` | An indication indicating a slight left turn (i.e. slightly bend arrow). |
| `left` | An indication indicating a left turn (i.e. bend arrow). |
| `sharp left` | An indication indicating a sharp left turn (i.e. strongly bend arrow). |
- `valid`: a boolean flag indicating whether the lane is a valid choice in the current maneuver
@@ -611,12 +668,12 @@ A `Lane` represents a turn lane at the corresponding turn location.
}
```
### Intersection
### Intersection object
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
**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.
@@ -630,7 +687,8 @@ location of the StepManeuver. Further intersections are listed for every cross-w
- `lanes`: Array of `Lane` objects that denote the available turn lanes at the intersection. If no lane information is available for an intersection, the `lanes` property will not be present.
#### Example
```
```json
{
"location":[13.394718,52.543096],
"in":0,
@@ -641,35 +699,32 @@ location of the StepManeuver. Further intersections are listed for every cross-w
"indications": ["left", "straight"],
"valid": "false"
}
]}
}
```
### Waypoint
### Waypoint object
Object used to describe waypoint on a route.
#### Properties
**Properties**
- `name` Name of the street the coordinate snapped to
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
- `distance` The distance of the snapped point from the original
- `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`
#### Example
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
```json
{
"hint" : "KSoKADRYroqUBAEAEAAAABkAAAAGAAAAAAAAABhnCQCLtwAA_0vMAKlYIQM8TMwArVghAwEAAQH1a66g",
"distance" : 4.152629,
"name" : "Friedrichstraße",
"location" : [
13.388799,
52.517033
]
}
```
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.
Binary file not shown.

After

Width:  |  Height:  |  Size: 694 KiB

+13 -6
View File
@@ -1,7 +1,11 @@
## Introduction
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:
## Important interface objects
- [`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.
@@ -16,11 +20,14 @@ Take a look at the example code that lives in the [example directory](https://gi
- [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]].
- [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). 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 [HTTP API](#http-api).
------------------------------------------------------------------------------------------------------------------
## Example
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
See [the example folder](https://github.com/Project-OSRM/osrm-backend/tree/master/example) in the OSRM repository.
## Workflow
- 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
+2
View File
@@ -32,6 +32,7 @@ We may introduce forward-compatible changes: query parameters and response prope
- The `master` branch is for the bleeding edge development
- We create and maintain release branches `x.y` to control the release flow
- We create the release branch once we tagged the final version `x.y.0` version, RCs go on master
- No minor or major version will be released without a code-equal release candidates
- For quality assurance, release candidates will be run on the demo server for 24 hours before releaseing the version proper
- Patch versions may be released without a release candidate
@@ -44,6 +45,7 @@ We may introduce forward-compatible changes: query parameters and response prope
3. Make sure `CHANGELOG.md` is up to date.
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. Use `npm run build-api-docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
6. Push tags and commits: `git push; git push --tags`
8. Proceede with the `node-osrm` release as [outlined in the repository](https://github.com/Project-OSRM/node-osrm/blob/master/docs/releasing.md).
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
+14
View File
@@ -0,0 +1,14 @@
## Environment 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.
+16
View File
@@ -0,0 +1,16 @@
var fs = require('fs');
/**
* This file exports the content of your website, as a bunch of concatenated
* Markdown files. By doing this explicitly, you can control the order
* of content without any level of abstraction.
*
* Using the brfs module, fs.readFileSync calls in this file are translated
* into strings of those files' content before the file is delivered to a
* browser: the content is read ahead-of-time and included in bundle.js.
*/
module.exports =
'# HTTP API\n' +
fs.readFileSync('./content/http.md', 'utf8') + '\n'+
'# libosrm C++ API\n' +
fs.readFileSync('./content/libosrm.md', 'utf8') + '\n';
+16
View File
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta http-equiv='X-UA-Compatible' content='IE=11' />
<title>OSRM API Documentation</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link href='css/base.css' rel='stylesheet' />
<link href='css/style.css' rel='stylesheet' />
<link href='css/railscasts.css' rel='stylesheet' />
</head>
<body>
<!--START--><div id='app'></div><!--STOP-->
<script src='bundle.js'></script>
</body>
</html>
+63
View File
@@ -0,0 +1,63 @@
'use strict';
/**
* Brand names, in order to decreasing length, for different
* media queries.
*/
module.exports.brandNames = {
desktop: 'OSRM API Documentation',
tablet: 'OSRM API Docs',
mobile: 'OSRM API'
};
/**
* Classes that define the top-left brand box.
*/
module.exports.brandClasses = 'fill-red';
/**
* Text for the link back to the linking website.
*/
module.exports.backLink = 'Back to project-osrm.org';
/**
* Runs after highlighting code samples. You can use this
* hook to, for instance, highlight a token and link it
* to some canonical part of documentation.
*/
module.exports.postHighlight = function(html) {
return html;
};
/**
* Highlight tokens in endpoint URLs, optionally linking to documentation
* or adding detail. This is the equivalent of postHighlight but it
* operates on endpoint URLs only.
*/
function highlightTokens(str) {
return str.replace(/{[\w_]+}/g,
(str) => '<span class="strong">' + str + '</span>');
}
/**
* Transform endpoints given as strings in a highlighted block like
*
* ```endpoint
* GET /foo/bar
* ```
*
* Into HTML nodes that format those endpoints in nice ways.
*/
module.exports.transformURL = function(value) {
let parts = value.split(/\s+/);
return {
type: 'html',
value: `<div class='endpoint dark fill-dark round '>
<div class='round-left pad0y pad1x fill-lighten0 code small endpoint-method'>${parts[0]}</div>
<div class='pad0 code small endpoint-url'>${highlightTokens(parts[1])}</div>
</div>`
};
};
module.exports.remarkPlugins = [];
+78
View File
@@ -309,3 +309,81 @@ And the relations
```
Unless this format is used, OSRM will omit the (then ambiguous) turn restrictions and ignore them.
## My Guidance Tests are Failing - Understanding what you can change
If you change some stuff in guidance, you will easily see tests change their result. E.g. if you change the angles for which we report `right`, then obviously some tests might not report a `direction modifier` named `right` anymore.
This small section will try to guide you in making the correct decisions for changing the behaviour of tests.
The difficulty in guidance tests is that not all items can be translated 1:1 from the ascii art into turn-angles.
The turn-angle calculation tries to find turn angles that would represent perceived turn angles, not the exact angle at the connection.
This is necessary, since connections in OSM are always bound by the paradigm that the way is supposed to be in the middle of the actual road.
For broad streets, you will see stronger angles than the actual turns.
### Don't change the test, change the expected behaviour
If we have a test that looks like this:
```
Given a grid size of 5 m
Given the node map
"""
a - b - - - - - - c
\
d - - - - - e
"""
When I route I should get
| waypoints | route | turns |
| a,e | abc,bde,bde | depart,turn slight right,arrive|
```
And the test reports `turn right` for the route `a->e`, where before it said `slight right`.
If you changed the turn angles, obviously you can expect changes in the distinction between `slight right` and `right`.
In such a case it is, of course, reasonable to change the expected route to report `right` instead of `slight right`. You should consider inspecting the actual turn angles at `b` to see if you feel that change is justified.
However, you should never adjust the test itself.
If you look at a failure, the other way around
```
Given a grid size of 5 m
Given the node map
"""
a - b - - - - - - c
\
d - - - - - e
"""
When I route I should get
| waypoints | route | turns |
| a,e | abc,bde,bde | depart,turn right,arrive|
```
where we see a `slight right`, over the expected `right`.
We could be tempted to adjust the grid size (e.g. from `10 m` to `20` meters).
Such a change would fundamentally alter the tests, though.
Since the part `b-d` is a short offset, when we are looking at a grid of size `5 m`, the angle calculation will try and compensate for this offset.
In this case we would see a very slight turn angle. If your change now reports different turn angles, you can of course change the expected result. But you should not adjust the grid size. The test would be testing turn angles of `180` and `100` degrees, instead of `180` and `160`.
### Consider Post-Processing Impacts
Some changes you might see could look completely unrelated. To understand the impact of your changes, you can make use of the debugging utilities you can finde in `util/debug.hpp` (and potentially other related headers).
If your test is inspecting a series of turns (remember, a turn not necessarily equals an instruction), you could see interaction with post-processing.
To see the unprocessed turns, you should print the steps at the end of step assembly (`assembleSteps` in `engine/guidance/assemble_steps.hpp`).
If you see unexpected changes, you can consider adding the `locations` field to your test to study what location a turn is reported at.
To study a test without post-processing impacts, you can create a copy of the case on a very large grid (like 2000 meters). In such a grid, `turn collapsing` would be essentially disable.
Sadly, there is no general guideline.
### Use Caution
If in doubt, ask another person. Inspect as much of the data as possible (e.g. print un-collapsed steps, turn angles and so on) and use your best judgement, if the new result seems justified.
+2 -2
View File
@@ -19,7 +19,7 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(bitness 64)
message(STATUS "Building on a 64 bit system")
else()
message(WARNING "Building on a 32 bit system is unsupported")
message(STATUS "Building on a 32 bit system")
endif()
if(WIN32 AND MSVC_VERSION LESS 1900)
@@ -33,4 +33,4 @@ find_package(LibOSRM REQUIRED)
target_link_libraries(osrm-example ${LibOSRM_LIBRARIES} ${LibOSRM_DEPENDENT_LIBRARIES})
include_directories(SYSTEM ${LibOSRM_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS ${LibOSRM_CXXFLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LibOSRM_CXXFLAGS}")
+8
View File
@@ -174,3 +174,11 @@ Feature: Bike - Access tags on ways
| cycleway | | no | | x |
| runway | | | yes | |
| cycleway | | | no | x |
Scenario: Bike - Bridleways when access is explicit
Then routability should be
| highway | horse | foot | bicycle | bothw |
| bridleway | | | yes | x |
| bridleway | | yes | | x |
| bridleway | designated | | | |
| bridleway | | | | |
+2 -2
View File
@@ -8,7 +8,7 @@ Feature: Bike - Surfaces
Then routability should be
| highway | surface | bothw |
| cycleway | | 48 s |
| cycleway | asphalt | 48 s |
| cycleway | asphalt | 47.9 s|
| cycleway | cobblestone:flattened | 72 s |
| cycleway | paving_stones | 72 s |
| cycleway | compacted | 72 s |
@@ -26,7 +26,7 @@ Feature: Bike - Surfaces
Then routability should be
| highway | surface | bothw |
| cycleway | | 48 s |
| path | | 60 s |
| path | | 59.9 s|
| track | | 60 s |
| track | asphalt | 60 s |
| path | asphalt | 60 s |
+45 -2
View File
@@ -30,6 +30,35 @@ Feature: Car - Restricted access
| | | no | yes | x |
| | | yes | no | |
Scenario: Car - Access tag hierarchy and forward/backward
Then routability should be
| access | access:forward | access:backward | motorcar | motorcar:forward | motorcar:backward | forw | backw |
| | | | | | | x | x |
| yes | | | | | | x | x |
| yes | no | | | | | | x |
| yes | yes | | no | | | | |
| yes | yes | | yes | no | | | x |
| yes | | | | | | x | x |
| yes | | no | | | | x | |
| yes | | yes | no | | | | |
| yes | | yes | yes | | no | x | |
| no | | | | | | | |
| no | yes | | | | | x | |
| no | no | | yes | | | x | x |
| no | no | | no | yes | | x | |
| no | | | | | | | |
| no | | yes | | | | | x |
| no | | no | yes | | | x | x |
| no | | no | no | | yes | | x |
| | no | | | no | | | x |
| | | no | | | no | x | |
| | no | | | | no | | |
| | | no | no | | | | |
| | no | | | yes | | x | x |
| | | no | | | yes | x | x |
| | yes | | | no | | | x |
| | | yes | | | no | x | |
Scenario: Car - Access tag hierarchy on nodes
Then routability should be
| node/access | node/vehicle | node/motor_vehicle | node/motorcar | bothw |
@@ -149,6 +178,7 @@ Feature: Car - Restricted access
| runway | | | | yes | |
| primary | | | | no | x |
@hov
Scenario: Car - only designated HOV ways are ignored by default
Then routability should be
| highway | hov | bothw |
@@ -156,6 +186,7 @@ Feature: Car - Restricted access
| primary | yes | x |
| primary | no | x |
@hov
Scenario: Car - a way with all lanes HOV-designated is inaccessible by default (similar to hov=designated)
Then routability should be
| highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw |
@@ -166,8 +197,8 @@ Feature: Car - Restricted access
| primary | designated\|no | designated\|no | | | x | x |
| primary | yes\|no | yes\|no | | | x | x |
| primary | | | | | x | x |
| primary | designated | | | -1 | | |
| primary | | designated | | -1 | | x |
| primary | designated | | | -1 | | x |
| primary | | designated | | -1 | | |
| primary | | | designated | yes | | |
| primary | | | designated | -1 | | |
| primary | | | designated\| | yes | x | |
@@ -189,3 +220,15 @@ Feature: Car - Restricted access
Then routability should be
| highway | toll | bothw |
| primary | yes | |
Scenario: Car - directional access tags
Then routability should be
| highway | access | access:forward | access:backward | forw | backw |
| primary | yes | yes | yes | x | x |
| primary | yes | | no | x | |
| primary | yes | no | | | x |
| primary | yes | no | no | | |
| primary | no | no | no | | |
| primary | no | | yes | | x |
| primary | no | yes | | x | |
| primary | no | yes | yes | x | x |
+13 -2
View File
@@ -90,7 +90,7 @@ OSRM will use 4/5 of the projected free-flow speed.
| primary | | 3 | 60 | | 29 km/h | 32 km/h |
| primary | | | | 60 | 52 km/h | 47 km/h |
| primary | | 3 | | 60 | 32 km/h | 29 km/h |
| primary | 15 | | 60 | | 47 km/h | 12 km/h |
| primary | 15 | | 60 | | 47 km/h | 11 km/h |
| primary | 15 | 3 | 60 | | 29 km/h | 7 km/h |
| primary | 15 | | | 60 | 12 km/h | 47 km/h |
| primary | 15 | 3 | | 60 | 7 km/h | 29 km/h |
@@ -109,7 +109,7 @@ OSRM will use 4/5 of the projected free-flow speed.
| primary | | 1 | 60 | | 29 km/h | 32 km/h |
| primary | | | | 60 | 52 km/h | 47 km/h |
| primary | | 1 | | 60 | 32 km/h | 29 km/h |
| primary | 15 | | 60 | | 47 km/h | 12 km/h |
| primary | 15 | | 60 | | 47 km/h | 11 km/h |
| primary | 15 | 1 | 60 | | 29 km/h | 7 km/h |
| primary | 15 | | | 60 | 12 km/h | 47 km/h |
| primary | 15 | 1 | | 60 | 7 km/h | 29 km/h |
@@ -123,3 +123,14 @@ OSRM will use 4/5 of the projected free-flow speed.
| primary | 30 | 1 | -1 | | 23 km/h |
| primary | 30 | 1 | | 15 km/h | 15 km/h |
| primary | 30 | 2 | | 23 km/h | 23 km/h |
Scenario: Car - Forwward/backward maxspeed on reverse oneways
Then routability should be
| highway | maxspeed | maxspeed:forward | maxspeed:backward | oneway | forw | backw |
| primary | | | | -1 | | 52 km/h |
| primary | 30 | | | -1 | | 23 km/h |
| primary | | 30 | | -1 | | 52 km/h |
| primary | | | 30 | -1 | | 23 km/h |
| primary | 20 | 30 | | -1 | | 16 km/h |
| primary | 20 | | 30 | -1 | | 23 km/h |
+13 -13
View File
@@ -78,24 +78,24 @@ Feature: Car - Street names in instructions
Scenario: Inner city expressway with on road
Given the node map
"""
a b c g
f
a b . . . c g
`f .
`
.
.
d
.
.
.
e
"""
And the ways
| nodes | highway | name | name:pronunciation |
| abc | primary | road | roooaad |
| cg | primary | road | roooaad |
| bfd | trunk_link | | |
| cde | trunk | trunk | truank |
| nodes | highway | name | name:pronunciation | oneway |
| abc | primary | road | roooaad | |
| cg | primary | road | roooaad | |
| bfd | trunk_link | sliproad | | yes |
| cde | trunk | trunk | truank | yes |
And the relations
| type | way:from | way:to | node:via | restriction |
+4 -1
View File
@@ -27,7 +27,10 @@ Feature: Basic Routing
When I route I should get
| waypoints | route | summary |
| a,e | road,,1 st,1 st | road, 1 st |
| a,d,f | road,,,street,street | road;street |
# The via node `d` belongs to `cd`, `de`, `df`, `dg` and depending on the edge
# summary can be "road;street", "road, 1 st;1 st, street", "road, blvd;blvd, street"
# The test must be fixed by #2287
#| a,d,f | road,,,street,street | road;street |
| a,e,f | road,,1 st,1 st,1 st,street,street | road, 1 st;1 st, street |
Scenario: Name Empty
+3 -1
View File
@@ -111,7 +111,9 @@ Feature: Traffic - turn penalties
"""
When I route I should get
| from | to | route | time |
| a | d | ad,ad | 10s +-1 |
# The target point `d` can be in `ad`, `cd`, `deh` and `dhk`
# The test must be fixed by #2287
#| a | d | ad,ad | 10s +-1 |
| a | e | ad,def,def | 10s +-1 |
| b | f | bf,bf | 10s +-1 |
| b | g | bf,fg,fg | 20s +-1 |
+8
View File
@@ -95,3 +95,11 @@ Feature: Foot - Access tags on ways
| footway | | no | | x |
| motorway | | | yes | |
| footway | | | no | x |
Scenario: Foot - Bridleways when access is explicit
Then routability should be
| highway | horse | bicycle | foot | bothw |
| bridleway | | | yes | x |
| bridleway | | yes | | |
| bridleway | designated | | | |
| bridleway | | | | |
+24 -15
View File
@@ -5,13 +5,17 @@ Feature: Turn Lane Guidance
Given the profile "car"
Given a grid size of 3 meters
@sliproads
Scenario: Separate Turn Lanes
Given the node map
"""
e
a b c g
d
.
a ... b ..... c . g
` .
`... d
.
f
"""
@@ -41,8 +45,10 @@ Feature: Turn Lane Guidance
Given the node map
"""
e
a b c g
d
a . . b . . . c g
` .
` .
` d
f
"""
@@ -67,21 +73,22 @@ Feature: Turn Lane Guidance
| a,g | in,straight,straight | depart,new name straight,arrive | ,left:false straight:true right:false, |
| a,f | in,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, |
@sliproads
Scenario: Separate Turn Lanes Next to other turns
Given the node map
"""
e
a b c g
d
f
i h j
. e
a . . b . . . c g
. ` .
. ` .
. d
. f
.
.
.
.
i . . h . . . j
"""
And the ways
@@ -109,6 +116,7 @@ Feature: Turn Lane Guidance
| a,j | in,turn,other,other | depart,turn right,turn left,arrive | ,,left:true right:false, |
| a,i | in,turn,other,other | depart,turn right,turn right,arrive | ,,left:false right:true, |
@todo @2654 @none
#https://github.com/Project-OSRM/osrm-backend/issues/2645
#http://www.openstreetmap.org/export#map=19/52.56054/13.32152
@@ -231,6 +239,7 @@ Feature: Turn Lane Guidance
| a,j | ghough,market,market | depart,turn left,arrive | ,none:true straight:false straight:false straight:false, |
| a,f | ghough,ghough,ghough | depart,continue slight left,arrive | ,none:true straight:true straight:false straight:false, |
Scenario: Check sliproad handler loop's exit condition, Issue #2896
# http://www.openstreetmap.org/way/198481519
Given the node locations
@@ -783,3 +783,38 @@ Feature: Turn Lane Guidance
| waypoints | route | turns | lanes |
| a,f | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,turn right,arrive | ,left:false left:true none:false none:false,left:false left:true none:false none:false,left:false left:true none:false none:false,left:false left:false right:true, |
| a,g | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,turn left,arrive | ,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true right:false, |
@anticipate
Scenario: Complex lane scenarios scale threshold for triggering Lane Anticipation
Given the node map
"""
a b x
|
|
|
|
|
|
|
|
|
|
c
|
e d y
"""
# With a grid size of 20m the duration is ~20s but our default threshold for Lane Anticipation is 15s.
# The additional lanes left and right of the turn scale the threshold up so that Lane Anticipation still triggers.
And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|through\|right\|right | MySt |
| bx | | XSt |
| bc | | MySt |
| cd | left\|right | MySt |
| de | | MySt |
| dy | | YSt |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, |
@@ -0,0 +1,139 @@
@routing @guidance @staggered-intersections
Feature: Staggered Intersections
Background:
Given the profile "bicycle"
Given a grid size of 1 meters
# Note the one meter grid size: staggered intersections make zig-zags of a couple of meters only
Scenario: Staggered Intersection - pushing in the middle
Given the node map
"""
j
a b c
d
e f g
h
i
"""
And the ways
| nodes | highway | name | oneway |
| abc | residential | Oak St | |
| efg | residential | Oak St | |
| ihedcj | residential | Cedar Dr | yes |
When I route I should get
| waypoints | route | turns | modes |
| a,g | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive | cycling,pushing bike,cycling,cycling |
| g,a | Oak St,Oak St | depart,arrive | cycling,cycling |
Scenario: Staggered Intersection - pushing at start
Given the node map
"""
j
a b c
d
e f g
h
i
"""
And the ways
| nodes | highway | name | oneway |
| cba | residential | Oak St | yes |
| efg | residential | Oak St | |
| ihedcj | residential | Cedar Dr | |
When I route I should get
| waypoints | route | turns | modes |
| a,g | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive | pushing bike,cycling,cycling,cycling |
| g,a | Oak St,Oak St | depart,arrive | cycling,cycling |
Scenario: Staggered Intersection - pushing at end
Given the node map
"""
j
a b c
d
e f g
h
i
"""
And the ways
| nodes | highway | name | oneway |
| abc | residential | Oak St | |
| gfe | residential | Oak St | yes |
| ihedcj | residential | Cedar Dr | |
When I route I should get
| waypoints | route | turns | modes |
| a,g | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive | cycling,cycling,pushing bike,pushing bike |
| g,a | Oak St,Oak St | depart,arrive | cycling,cycling |
Scenario: Staggered Intersection - pushing at start and end
Given the node map
"""
j
a b c
d
e f g
h
i
"""
And the ways
| nodes | highway | name | oneway |
| cba | residential | Oak St | yes |
| gfe | residential | Oak St | yes |
| ihedcj | residential | Cedar Dr | |
When I route I should get
| waypoints | route | turns | modes |
| a,g | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive | pushing bike,cycling,pushing bike,pushing bike |
| g,a | Oak St,Oak St | depart,arrive | cycling,cycling |
Scenario: Staggered Intersection - pushing at start and end
Given the node map
"""
j
a b c
d
e f g
h
i
"""
And the ways
| nodes | highway | name |
| cba | pedestrian | Oak St |
| gfe | pedestrian | Oak St |
| ihedcj | residential | Cedar Dr |
When I route I should get
| waypoints | route | turns | modes |
| a,g | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive | pushing bike,cycling,pushing bike,pushing bike |
| g,a | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive | pushing bike,cycling,pushing bike,pushing bike |
Scenario: Staggered Intersection - control, all cycling on staggered intersection
Given the node map
"""
j
a b c
d
e f g
h
i
"""
And the ways
| nodes | highway | name |
| cba | residential | Oak St |
| gfe | residential | Oak St |
| ihedcj | residential | Cedar Dr |
When I route I should get
| waypoints | route | turns | modes |
| a,g | Oak St,Oak St | depart,arrive | cycling,cycling |
| g,a | Oak St,Oak St | depart,arrive | cycling,cycling |
+282
View File
@@ -0,0 +1,282 @@
@routing @guidance
Feature: Rotary
Background:
Given the profile "car"
Given a grid size of 30 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 | circular |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,bgecb-exit-3,arrive |
| a,f | ab,ef,ef | depart,bgecb-exit-2,arrive |
| a,h | ab,gh,gh | depart,bgecb-exit-1,arrive |
| d,f | cd,ef,ef | depart,bgecb-exit-3,arrive |
| d,h | cd,gh,gh | depart,bgecb-exit-2,arrive |
| d,a | cd,ab,ab | depart,bgecb-exit-1,arrive |
| f,h | ef,gh,gh | depart,bgecb-exit-3,arrive |
| f,a | ef,ab,ab | depart,bgecb-exit-2,arrive |
| f,d | ef,cd,cd | depart,bgecb-exit-1,arrive |
| h,a | gh,ab,ab | depart,bgecb-exit-3,arrive |
| h,d | gh,cd,cd | depart,bgecb-exit-2,arrive |
| h,f | gh,ef,ef | depart,bgecb-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 | circular |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| a,e | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| a,g | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| d,e | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| d,g | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| d,b | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| f,g | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| f,b | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| f,c | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| h,b | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| h,c | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive |
| h,e | gh,bcegb,bcegb | depart,bcegb-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 | circular |
When I route I should get
| waypoints | route | turns |
| b,d | bcegb,cd,cd | depart,bcegb-exit-1,arrive |
| b,f | bcegb,ef,ef | depart,bcegb-exit-2,arrive |
| b,h | bcegb,gh,gh | depart,bcegb-exit-3,arrive |
| c,f | bcegb,ef,ef | depart,bcegb-exit-1,arrive |
| c,h | bcegb,gh,gh | depart,bcegb-exit-2,arrive |
| c,a | bcegb,ab,ab | depart,bcegb-exit-3,arrive |
| e,h | bcegb,gh,gh | depart,bcegb-exit-1,arrive |
| e,a | bcegb,ab,ab | depart,bcegb-exit-2,arrive |
| e,d | bcegb,cd,cd | depart,bcegb-exit-3,arrive |
| g,a | bcegb,ab,ab | depart,bcegb-exit-1,arrive |
| g,d | bcegb,cd,cd | depart,bcegb-exit-2,arrive |
| g,f | bcegb,ef,ef | depart,bcegb-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 | circular |
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 |
#needs to be adjusted when name-discovery works for entrys
Scenario: Mixed Entry and Exit
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 | circular | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,rotary-exit-1,arrive |
| a,l | abc,jkl,jkl | depart,bkheb-exit-2,arrive |
| a,i | abc,ghi,ghi | depart,bkheb-exit-3,arrive |
| a,f | abc,def,def | depart,bkheb-exit-4,arrive |
| d,f | def,def,def | depart,rotary-exit-1,arrive |
| d,c | def,abc,abc | depart,bkheb-exit-2,arrive |
| d,l | def,jkl,jkl | depart,bkheb-exit-3,arrive |
| d,i | def,ghi,ghi | depart,bkheb-exit-4,arrive |
| g,i | ghi,ghi,ghi | depart,rotary-exit-1,arrive |
| g,f | ghi,def,def | depart,bkheb-exit-2,arrive |
| g,c | ghi,abc,abc | depart,bkheb-exit-3,arrive |
| g,l | ghi,jkl,jkl | depart,bkheb-exit-4,arrive |
| j,l | jkl,jkl,jkl | depart,rotary-exit-1,arrive |
| j,i | jkl,ghi,ghi | depart,bkheb-exit-2,arrive |
| j,f | jkl,def,def | depart,bkheb-exit-3,arrive |
| j,c | jkl,abc,abc | depart,bkheb-exit-4,arrive |
Scenario: Collinear in X,Y
Given the node map
"""
a
b
c d f
e
"""
And the ways
| nodes | junction |
| ab | |
| bcdb | circular |
| ce | |
| df | |
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 |
Scenario: Collinear in X,Y
Given the node map
"""
a
d
b c f
e
"""
And the ways
| nodes | junction |
| ad | |
| bcdb | circular |
| be | |
| cf | |
When I route I should get
| waypoints | route | turns |
| 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
"""
a
c
d b f
e
"""
And the ways
| nodes | junction |
| ac | |
| bcdb | circular |
| de | |
| bf | |
When I route I should get
| waypoints | route | turns |
| 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
"""
f
d c e
b
a
"""
And the ways
| nodes | junction |
| ab | |
| bcdb | circular |
| ce | |
| df | |
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 |
Scenario: Collinear in X,Y
Given the node map
"""
f
d c e
b
a
"""
And the ways
| nodes | junction |
| ab | |
| bcdb | circular |
| ce | |
| df | |
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 |
+35
View File
@@ -55,3 +55,38 @@ Feature: Collapse
| waypoints | route | turns |
| a,g | road,road,road | depart,continue uturn,arrive |
| d,c | road,road,road | depart,continue uturn,arrive |
Scenario: Forking before a turn (forky)
Given the node map
"""
g
.
c
a . . b .'
`d.
f e
"""
# note: check clooapse.feature for a similar test case where we do not
# classify the situation as Sliproad and therefore keep the fork inst.
And the ways
| nodes | name | oneway | highway |
| ab | road | yes | primary |
| bd | road | yes | primary |
| bc | road | yes | primary |
| de | road | yes | primary |
| fd | cross | no | secondary |
| dc | cross | no | secondary |
| cg | cross | no | secondary |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bd | dc | d | no_left_turn |
| restriction | bc | dc | c | no_right_turn |
When I route I should get
| waypoints | route | turns |
| a,g | road,cross,cross | depart,turn left,arrive |
| a,e | road,road,road | depart,continue right,arrive |
# We should discuss whether the next item should be collapsed to depart,turn right,arrive.
| a,f | road,road,cross,cross | depart,continue slight right,turn right,arrive |
+62 -41
View File
@@ -338,10 +338,10 @@ Feature: Collapse
Given the node map
"""
a f g
b e
| | . '
b-e '
/ /
/ /
c d
"""
@@ -353,13 +353,13 @@ Feature: Collapse
| 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 |
| 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,turn left,arrive |
Scenario: Do not collapse turning roads
Given the node map
@@ -484,6 +484,23 @@ Feature: Collapse
| waypoints | route | turns |
| a,d | road,road | depart,arrive |
Scenario: No Name During Turns - Ferry
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | name | route |
| ab | tertiary | road | |
| bc | tertiary | | ferry |
| cd | tertiary | road | |
When I route I should get
| waypoints | route | turns |
| a,d | road,,road,road | depart,notification right,notification left,arrive |
Scenario: No Name During Turns, Random Oneway
Given the node map
"""
@@ -684,12 +701,15 @@ Feature: Collapse
Given the node map
"""
g
.
c
a b
d
a . . b .'
` d.
f e
"""
# as it is right now we don't classify this as a sliproad,
# check collapse-detail.feature for a similar test case
# which removes the fork here due to it being a Sliproad.
And the ways
| nodes | name | oneway | highway |
@@ -707,11 +727,10 @@ Feature: Collapse
| restriction | bc | dc | c | no_right_turn |
When I route I should get
| waypoints | route | turns |
| a,g | road,cross,cross | depart,turn left,arrive |
| a,e | road,road,road | depart,continue slight right,arrive |
# We should discuss whether the next item should be collapsed to depart,turn right,arrive.
| a,f | road,road,cross,cross | depart,continue slight right,turn right,arrive |
| waypoints | route | turns |
| a,g | road,cross,cross | depart,fork left,arrive |
| a,e | road,road,road | depart,fork slight right,arrive |
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive |
Scenario: On-Off on Highway
Given the node map
@@ -738,12 +757,13 @@ Feature: Collapse
Scenario: Don't collapse going straight if actual turn
Given the node map
"""
c e
d f
e
c |
\ d - - - f
\|
b
|
|
a
"""
@@ -754,10 +774,10 @@ Feature: Collapse
| df | right | residential |
When I route I should get
| waypoints | route | turns |
| a,c | main,main | depart,arrive |
| a,e | main,straight,straight | depart,turn straight,arrive |
| a,f | main,straight,right,right | depart,turn straight,turn right,arrive |
| waypoints | route | turns | locations |
| a,c | main,main | depart,arrive | a,c |
| a,e | main,straight,straight | depart,turn straight,arrive | a,b,e |
| a,f | main,straight,right,right | depart,turn straight,turn right,arrive | a,b,d,f |
Scenario: Entering a segregated road
Given the node map
@@ -929,16 +949,17 @@ Feature: Collapse
#http://www.openstreetmap.org/#map=19/52.48778/13.30024
Scenario: Hohenzollerdammbrücke
Given a grid size of 10 meters
Given the node map
"""
q s
p o
.. . .
. . . .
.. ..
. . . .
j - i - - - h - - - g - f
> k < > l <
a - b - - - c - - - d - e
. . . .
. . . .
.. ..
m n
t r
@@ -995,13 +1016,13 @@ Feature: Collapse
| restriction | ph | hi | h | no_right_turn |
When I route I should get
| waypoints | route | turns |
| a,e | hohe,hohe | depart,arrive |
| a,s | hohe,a100,a100 | depart,on ramp left,arrive |
| a,t | hohe,a100,a100 | depart,on ramp right,arrive |
| a,j | | |
| f,j | hohe,hohe | depart,arrive |
| a,t | hohe,a100,a100 | depart,on ramp right,arrive |
| f,e | | |
| q,j | a100,hohe,hohe | depart,turn right,arrive |
| q,e | a100,a100,hohe | depart,continue left,arrive |
| waypoints | route | turns | locations |
| a,e | hohe,hohe | depart,arrive | a,e |
| a,s | hohe,a100,a100 | depart,on ramp left,arrive | a,b,s |
| a,t | hohe,a100,a100 | depart,on ramp right,arrive | a,b,t |
| a,j | | | |
| f,j | hohe,hohe | depart,arrive | f,j |
| a,t | hohe,a100,a100 | depart,on ramp right,arrive | a,b,t |
| f,e | | | |
| q,j | a100,hohe,hohe | depart,turn right,arrive | q,p,j |
| q,e | a100,hohebruecke,hohe | depart,turn left,arrive | q,p,e |
+399 -48
View File
@@ -9,32 +9,32 @@ Feature: Slipways and Dedicated Turn Lanes
Given the node map
"""
e
a b c d
h
1
a b . . c d
`h .
`
1 `
.
f
.
g
"""
And the ways
| nodes | highway | name |
| abc | trunk | first |
| cd | trunk | first |
| bhf | trunk_link | |
| cfg | primary | second |
| ec | primary | second |
| nodes | highway | name | oneway |
| abc | trunk | first | |
| cd | trunk | first | |
| bhf | trunk_link | | yes |
| cfg | primary | second | yes |
| ec | primary | second | |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | abc | cfg | c | no_right_turn |
When I route I should get
| waypoints | route | turns |
| a,g | first,second,second | depart,turn right,arrive |
| a,1 | first,, | depart,turn slight right,arrive |
| waypoints | route | turns |
| a,g | first,second,second | depart,turn right,arrive |
| a,1 | first,, | depart,turn right,arrive |
Scenario: Turn Instead of Ramp - Max-Speed
Given the node map
@@ -51,21 +51,21 @@ Feature: Slipways and Dedicated Turn Lanes
"""
And the ways
| nodes | highway | name | maxspeed |
| abc | trunk | first | 70 |
| cd | trunk | first | 2 |
| bhf | trunk_link | | 2 |
| cfg | primary | second | 50 |
| ec | primary | second | 50 |
| nodes | highway | name | maxspeed | oneway |
| abc | trunk | first | 70 | |
| cd | trunk | first | 2 | |
| bhf | trunk_link | | 2 | yes |
| cfg | primary | second | 50 | yes |
| ec | primary | second | 50 | |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | abc | cfg | c | no_right_turn |
When I route I should get
| waypoints | route | turns |
| a,g | first,second,second | depart,turn right,arrive |
| a,1 | first,, | depart,turn slight right,arrive |
| waypoints | route | turns |
| a,g | first,second,second | depart,turn right,arrive |
| a,1 | first,, | depart,turn right,arrive |
Scenario: Turn Instead of Ramp
@@ -94,8 +94,8 @@ Feature: Slipways and Dedicated Turn Lanes
| efg | primary | second |
When I route I should get
| waypoints | route | turns |
| a,g | first,,second,second | depart,off ramp slight right,turn straight,arrive |
| waypoints | route | turns |
| a,g | first,,second,second | depart,off ramp right,turn straight,arrive |
Scenario: Turn Instead of Ramp
Given the node map
@@ -119,30 +119,30 @@ Feature: Slipways and Dedicated Turn Lanes
| efg | primary | second |
When I route I should get
| waypoints | route | turns |
| a,g | first,,second,second | depart,off ramp slight right,turn straight,arrive |
| waypoints | route | turns |
| a,g | first,,second,second | depart,off ramp right,turn straight,arrive |
Scenario: Inner city expressway with on road
Given the node map
"""
a b c g
f
a b . . . c g
`f .
`
.
.
d
.
.
.
e
"""
And the ways
| nodes | highway | name |
| abc | primary | road |
| cg | primary | road |
| bfd | trunk_link | |
| cde | trunk | trunk |
| nodes | highway | name | oneway |
| abc | primary | road | |
| cg | primary | road | |
| bfd | trunk_link | | yes |
| cde | trunk | trunk | yes |
And the relations
| type | way:from | way:to | node:via | restriction |
@@ -240,8 +240,8 @@ Feature: Slipways and Dedicated Turn Lanes
| qe | secondary_link | Ettlinger Allee | | yes |
When I route I should get
| waypoints | route | turns | ref |
| a,o | Schwarzwaldstrasse,Ettlinger Allee,Ettlinger Allee | depart,turn right,arrive | L561,L561, |
| waypoints | route | turns | ref |
| a,o | Schwarzwaldstrasse,Ettlinger Allee,Ettlinger Allee | depart,turn right,arrive | L561,L561, |
Scenario: Traffic Lights everywhere
#http://map.project-osrm.org/?z=18&center=48.995336%2C8.383813&loc=48.995467%2C8.384548&loc=48.995115%2C8.382761&hl=en&alt=0
@@ -271,11 +271,11 @@ Feature: Slipways and Dedicated Turn Lanes
| jcghf | primary | Brauerstrasse | yes |
When I route I should get
| waypoints | route | turns |
| a,i | Ebertstrasse,Ebertstrasse | depart,arrive |
| a,l | Ebertstrasse,Ebertstrasse | depart,arrive |
| a,f | Ebertstrasse,Brauerstrasse,Brauerstrasse | depart,turn right,arrive |
| a,1 | Ebertstrasse,, | depart,turn right,arrive |
| waypoints | route | turns |
| a,i | Ebertstrasse,Ebertstrasse | depart,arrive |
| a,l | Ebertstrasse,Ebertstrasse | depart,arrive |
| a,f | Ebertstrasse,Brauerstrasse,Brauerstrasse | depart,turn right,arrive |
| a,1 | Ebertstrasse,, | depart,turn slight right,arrive |
#2839
Scenario: Self-Loop
@@ -431,3 +431,354 @@ Feature: Slipways and Dedicated Turn Lanes
When I route I should get
| waypoints | route | turns |
| a,i | road,road,road | depart,fork slight left,arrive |
# The following tests are current false positives / false negatives #3199
@sliproads
# http://www.openstreetmap.org/#map=19/52.59847/13.14815
Scenario: Sliproad Detection
Given the node map
"""
a . . .
. .
b . . . . . . c . . . d
` . .
e . .
` . .
f . .
` . .
g i
` h .
"""
And the ways
| nodes | highway | name |
| abefgh | residential | Nachtigallensteig |
| bcd | residential | Kiebitzsteig |
| cg | residential | Haenflingsteig |
| hid | residential | Waldkauzsteig |
When I route I should get
| waypoints | route | turns |
| a,d | Nachtigallensteig,Kiebitzsteig,Kiebitzsteig | depart,turn left,arrive |
| a,h | Nachtigallensteig,Nachtigallensteig | depart,arrive |
@sliproads
Scenario: Not a obvious Sliproad
Given the node map
"""
d
.
s . a . . b . . c
` .
` e
.`
. `
f g
"""
And the ways
| nodes | highway | name | oneway |
| sabc | primary | sabc | |
| dbef | primary | dbef | yes |
| aeg | primary | aeg | yes |
When I route I should get
| waypoints | route | turns |
| s,f | sabc,aeg,dbef,dbef | depart,turn right,turn right,arrive |
@sliproads
Scenario: Through Street, not a Sliproad although obvious
Given the node map
"""
d
.
s . a . . b . . c
` .
` e
. `
. `
f g
"""
And the ways
| nodes | highway | name | oneway |
| sabc | primary | sabc | |
| dbef | primary | dbef | yes |
| aeg | primary | aeg | yes |
When I route I should get
| waypoints | route | turns |
| s,f | sabc,aeg,dbef,dbef | depart,turn right,turn right,arrive |
@sliproads
Scenario: Sliproad target turn is restricted
Given the node map
"""
d
.
s . a . . . . b . . c
` .
` .
` .
` .
`.
e
.`
f `
. ` g
"""
And the ways
| nodes | highway | name | oneway |
| sa | primary | sabc | |
| abc | primary | sabc | |
| dbe | primary | dbef | yes |
| ef | primary | dbef | |
| ae | primary | aeg | yes |
| eg | primary | aeg | |
# the reason we have to split ways at e is that otherwise we can't handle restrictions via e
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae | ef | e | no_right_turn |
When I route I should get
| waypoints | route | turns |
| s,f | sabc,dbef,dbef | depart,turn right,arrive |
| s,g | sabc,aeg,aeg | depart,turn right,arrive |
@sliproads
Scenario: Not a Sliproad, road not continuing straight
Given the node map
"""
d
.
s . a . . b . . c
` .
` e . . g
"""
And the ways
| nodes | highway | name | oneway |
| sabc | primary | sabc | |
| dbe | primary | dbe | yes |
| aeg | primary | aeg | yes |
When I route I should get
| waypoints | route | turns |
| s,c | sabc,sabc | depart,arrive |
| s,g | sabc,aeg,aeg | depart,turn right,arrive |
@sliproads
Scenario: Intersection too far away with Traffic Light shortly after initial split
Given the node map
"""
d
.
s . a . . . . . . . . . . . . . t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . b . . c
` . . . . . . . . . . . .
` . . . . . . . . . . . .
` . . . . . . . . . . . .
` . . . . . . . . . . . .
` . . . . . . . . . . . .
` . . . . . . . . . . . .
` . . .
` e
.
f
.
"""
And the nodes
| node | highway |
| t | traffic_signals |
And the ways
| nodes | highway | name | oneway |
| satbc | primary | sabc | |
| dbef | primary | dbef | yes |
| ae | primary | ae | yes |
When I route I should get
| waypoints | route | turns |
| s,f | sabc,ae,dbef,dbef | depart,turn slight right,turn right,arrive |
@sliproads
Scenario: Traffic Signal on Sliproad
Given the node map
"""
d
.
s . a . . . . . b . . c
` .
` .
` .
t .
` .
e
.
.
f
"""
And the nodes
| node | highway |
| t | traffic_signals |
And the ways
| nodes | highway | name | oneway |
| sabc | primary | sabc | |
| dbe | primary | dbe | yes |
| ef | primary | ef | |
| ate | primary | ate | yes |
When I route I should get
| waypoints | route | turns |
| s,f | sabc,ef,ef | depart,turn right,arrive |
@sliproads
Scenario: Sliproad tagged as link
Given the node map
"""
d
.
s . a . . . . . b . . c
` .
` .
` .
` .
` .
e
.
.
f
"""
And the ways
| nodes | highway | name | oneway |
| sabc | motorway | sabc | |
| dbef | motorway | dbef | yes |
| ae | motorway_link | ae | yes |
When I route I should get
| waypoints | route | turns |
| s,f | sabc,dbef,dbef | depart,turn right,arrive |
@sliproads
Scenario: Sliproad with same-ish names
Given the node map
"""
d
.
s . a . . b . . c
` .
. e
..
.
f
.
t
"""
And the ways
| nodes | highway | name | ref | oneway |
| sabc | primary | main | | |
| dbe | primary | crossing | r0 | yes |
| eft | primary | crossing | r0;r1 | yes |
| af | primary | sliproad | | yes |
When I route I should get
| waypoints | route | turns |
| s,t | main,crossing,crossing | depart,turn right,arrive |
@sliproads
Scenario: Not a Sliproad, name mismatch
Given the node map
"""
d
.
s . a . . b . . c
` .
. e
. .
..
.
f
.
t
"""
And the ways
| nodes | highway | name | oneway |
| sabc | primary | main | |
| dbe | primary | top | yes |
| ef | primary | bottom | yes |
| ft | primary | away | yes |
| af | primary | sliproad | yes |
When I route I should get
| waypoints | route | turns |
| s,t | main,away,away | depart,turn right,arrive |
@sliproads
Scenario: Not a Sliproad, low road priority
Given the node map
"""
d
.
s . a . . b . . c
` .
. e
. .
..
.
f
.
t
"""
And the ways
# maxspeed otherwise service road will never be routed over and we won't see instructions
| nodes | highway | name | maxspeed | oneway |
| sabc | primary | main | 30 km/h | |
| dbe | primary | crossing | 30 km/h | yes |
| eft | primary | crossing | 30 km/h | yes |
| ft | primary | away | 30 km/h | yes |
| af | service | sliproad | 30 km/h | yes |
When I route I should get
| waypoints | route | turns |
| s,t | main,away,away | depart,turn right,arrive |
@sliproads
Scenario: Not a Sliproad, more than three roads at target intersection
Given the node map
"""
d
.
s . a . . b . . c
` .
. e
. .
..
. h
f .
. g
t
"""
And the ways
| nodes | highway | name | oneway |
| sabc | primary | main | |
| dbe | primary | top | yes |
| eft | primary | bottom | yes |
| fh | primary | another | |
| fg | primary | another | |
| af | primary | sliproad | yes |
When I route I should get
| waypoints | route | turns |
| s,g | main,sliproad,another,another | depart,turn right,turn left,arrive |
+119
View File
@@ -0,0 +1,119 @@
@routing @guidance
Feature: Exceptions for routing onto low-priority roads
Background:
Given the profile "car"
Given a grid size of 10 meters
Scenario: Straight onto low-priority: same name
Given the node map
"""
c
a b d
e
"""
And the ways
| nodes | highway | name |
| abd | residential | road |
| eb | service | service |
| bc | service | service |
When I route I should get
| waypoints | route | turns |
| c,e | service,service | depart,arrive |
| e,c | service,service | depart,arrive |
Scenario: Straight onto low-priority: onto and from unnamed
Given the node map
"""
c
a b d
e
"""
And the ways
| nodes | highway | name |
| abd | residential | road |
| eb | service | |
| bc | service | |
When I route I should get
| waypoints | route | turns |
| e,c | , | depart,arrive |
| c,e | , | depart,arrive |
Scenario: Straight onto low-priority: unnamed
Given the node map
"""
c
a b d
e
"""
And the ways
| nodes | highway | name |
| abd | residential | road |
| eb | service | service |
| bc | service | |
When I route I should get
| waypoints | route | turns |
| e,c | service, | depart,arrive |
| c,e | ,service,service | depart,turn straight,arrive |
Scenario: Straight onto low-priority
Given the node map
"""
a b c
"""
And the ways
| nodes | highway | name |
| ab | residential | road |
| bc | service | service |
When I route I should get
| waypoints | route | turns |
| a,c | road,service,service | depart,new name straight,arrive |
Scenario: Straight onto low-priority, with driveway
Given the node map
"""
f
a b c
"""
And the ways
| nodes | highway | name |
| ab | residential | road |
| bc | service | road |
| bf | driveway | |
When I route I should get
| waypoints | route | turns |
| a,c | road,road | depart,arrive |
Scenario: Straight onto low-priority, with driveway
Given the node map
"""
f
a b c
"""
And the ways
| nodes | highway | name |
| ab | residential | road |
| bc | service | |
| bf | driveway | |
When I route I should get
| waypoints | route | turns |
| a,c | road, | depart,arrive |
| c,a | ,road,road | depart,new name straight,arrive |
+12 -12
View File
@@ -10,12 +10,12 @@ Feature: Simple Turns
"""
a
b
^
/ \
c d
e
|\
| e
|
f
"""
@@ -96,16 +96,16 @@ Feature: Simple Turns
Given the node map
"""
a
b
|
.b.
c h
| |
| |
1 2
| |
d g
e
'e'
|
f
"""
@@ -0,0 +1,59 @@
@routing @guidance @left-handed
Feature: Basic Roundabout
Background:
Given a grid size of 10 meters
Given the profile file
"""
require 'car'
properties.left_hand_driving = true
"""
Scenario: Roundabout exit counting for left sided driving
And a grid size of 10 meters
And the node map
"""
a
b
h g c d
e
f
"""
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
Scenario: Mixed Entry and Exit
And a grid size of 10 meters
And the node map
"""
c a
j b f
k e
l h d
g i
"""
And the ways
| nodes | junction | oneway |
| cba | | yes |
| fed | | yes |
| ihg | | yes |
| lkj | | yes |
| behkb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| c,a | cba,cba,cba | depart,roundabout-exit-1,arrive |
| l,a | lkj,cba,cba | depart,roundabout-exit-2,arrive |
| i,a | ihg,cba,cba | depart,roundabout-exit-3,arrive |
+67
View File
@@ -38,6 +38,30 @@ Feature: Basic Roundabout
| h,c | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
| h,e | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive |
Scenario: Roundabout With Service
Given the node map
"""
a h
bg
d c
e
f
"""
And the ways
| nodes | junction | highway |
| ab | | primary |
| cd | | primary |
| ef | | service |
| gh | | primary |
| bcegb | roundabout | primary |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout-exit-1,arrive |
| a,h | ab,gh,gh | depart,roundabout-exit-2,arrive |
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive |
#2927
Scenario: Only Roundabout
Given the node map
@@ -468,3 +492,46 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns |
| e,h | left,right,right | depart,roundabout-exit-2,arrive |
@3361
Scenario: Bersarinplatz (Not a Roundabout)
Given the node map
"""
a n
b m
c l
d e j k
f h
g i
"""
And the ways
| nodes | junction | name | ref | highway | oneway |
| ab | | Petersburger Strasse | B 96a | primary | yes |
| bc | circular | Bersarinplatz | B 96a | primary | |
| ce | circular | Bersarinplatz | B 96a | primary | |
| ed | | Weidenweg | | residential | |
| ef | circular | Bersarinplatz | B 96a | primary | |
| fg | | Petersburger Strasse | B 96a | primary | yes |
| fh | circular | Bersarinplatz | | secondary | |
| ih | | Petersburger Strasse | B 96a | primary | yes |
| hj | circular | Bersarinplatz | | secondary | |
| jk | | Rigaer Strasse | | residential | |
| jl | circular | Bersarinplatz | | secondary | |
| lm | circular | Bersarinplatz | | secondary | |
| mb | circular | Bersarinplatz | | secondary | |
| mn | | Petersburger Strasse | B 96a | primary | yes |
When I route I should get
| waypoints | route | turns |
| a,g | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-2,arrive |
| d,g | Weidenweg,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-1,arrive |
| i,k | Petersburger Strasse,Rigaer Strasse,Rigaer Strasse | depart,Bersarinplatz-exit-1,arrive |
| i,n | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-2,arrive |
| i,d | Petersburger Strasse,Weidenweg,Weidenweg | depart,Bersarinplatz-exit-3,arrive |
| i,g | Petersburger Strasse,Petersburger Strasse,Petersburger Strasse | depart,Bersarinplatz-exit-4,arrive |
@@ -25,7 +25,7 @@ Feature: Staggered Intersections
| jcdehi | residential | Cedar Dr |
When I route I should get
| waypoints | route | turns |
| waypoints | route | turns |
| a,g | Oak St,Oak St | depart,arrive |
| g,a | Oak St,Oak St | depart,arrive |
@@ -98,3 +98,48 @@ Feature: Staggered Intersections
| waypoints | route | turns |
| a,g | Oak St,Cedar Dr,Elm St,Elm St | depart,turn right,turn left,arrive |
| g,a | Elm St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive |
Scenario: Staggered Intersection: do not collapse if a mode change is involved
Given the node map
"""
j
a b c
d
e f g
h
"""
And the ways
| nodes | highway | name | route |
| abc | primary | to_sea | |
| ef | | to_sea | ferry |
| fg | primary | road | |
| jcdeh | primary | road | |
When I route I should get
| waypoints | route | turns | modes |
| a,g | to_sea,road,to_sea,road,road | depart,turn right,turn left,notification straight,arrive | driving,driving,ferry,driving,driving |
| g,a | road,to_sea,road,to_sea,to_sea | depart,notification straight,turn right,turn left,arrive | driving,ferry,driving,driving,driving |
Scenario: Staggered Intersection: do not collapse intermediary intersections
Given the node map
"""
j
a b c
e f g
d
k l m
i
"""
And the ways
| nodes | highway | name |
| abc | primary | Oak St |
| efg | residential | Elm St |
| klm | residential | Oak St |
| jcedki | residential | Cedar Dr |
When I route I should get
| waypoints | route | turns |
| a,m | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive |
| m,a | Oak St,Cedar Dr,Oak St,Oak St | depart,turn right,turn left,arrive |
+189 -40
View File
@@ -201,14 +201,14 @@ Feature: Simple Turns
| ef | residential | road | 2 | yes |
When I route I should get
| waypoints | route | turns |
| a,c | road,road | depart,arrive |
| c,a | road,road | depart,arrive |
| g,a | turn,road,road | depart,turn left,arrive |
| g,c | turn,road,road | depart,turn right,arrive |
| g,f | turn,road | depart,arrive |
| c,f | road,road,road | depart,continue right,arrive |
| a,f | road,road,road | depart,continue uturn,arrive |
| waypoints | route | turns | locations |
| a,c | road,road | depart,arrive | a,c |
| c,a | road,road | depart,arrive | c,a |
| g,a | turn,road,road | depart,turn left,arrive | g,b,a |
| g,c | turn,road,road | depart,turn right,arrive | g,b,c |
| g,f | turn,road,road | depart,turn left,arrive | g,e,f |
| c,f | road,road,road | depart,continue right,arrive | c,b,f |
| a,f | road,road,road | depart,continue uturn,arrive | a,b,f |
# http://www.openstreetmap.org/#map=19/52.48753/13.52838
Scenario: Traffic Circle
@@ -249,7 +249,7 @@ Feature: Simple Turns
When I route I should get
| waypoints | route | turns | intersections |
| a,p | road,road,road | depart,roundabout turn straight exit-1,arrive | true:90;true:135 false:270 false:345,true:90 false:180 true:345;true:270 |
| a,p | road,road,road | depart,roundabout turn straight exit-1,arrive | true:90;true:165 false:270 false:345,true:90 false:180 true:345;true:270 |
Scenario: Splitting Road with many lanes
Given the node map
@@ -317,30 +317,30 @@ Feature: Simple Turns
Scenario: Curved Turn At Cross
Given the node map
"""
h
|
|
|
|
| . b - - - - - - - - - - - - - - - - - - a
| .
| .
| c
|
|
|
d
|
|
|
e |
. |
. |
g - - - - - - - - - - - - - f |
|
|
|
i
h
|
|
|
|
| . b - - - - - - - - - - - - - - - - - - - - - - - a
| .
| .
| c
|
|
|
d
|
|
|
e |
. |
. |
g - - - - - - - - - - - - - - - - - - f |
|
|
|
i
"""
And the ways
@@ -443,9 +443,9 @@ Feature: Simple Turns
| ef | residential | road | 2 | yes |
When I route I should get
| waypoints | route | turns |
| g,f | turn,road,road | depart,turn left,arrive |
| c,f | road,road,road | depart,continue right,arrive |
| waypoints | route | turns | locations | # |
| g,f | turn,road | depart,arrive | g,f | #could offer an additional turn at `e` if you don't detect the turn in between as curve |
| c,f | road,road,road | depart,continue right,arrive | c,b,f | |
#http://www.openstreetmap.org/search?query=52.479264%2013.295617#map=19/52.47926/13.29562
Scenario: Splitting Roads with curved split
@@ -627,12 +627,14 @@ Feature: Simple Turns
| 1,h | ,allee,allee | depart,turn left,arrive |
| 2,h | ,allee,allee | depart,turn left,arrive |
#http://www.openstreetmap.org/#map=18/52.56251/13.32650
@todo
Scenario: Curved Turn on Separated Directions
Given the node map
"""
e d
f - - - - - - - - - - - - - - - c - - - - - - - - - - - j
f c - - - - - - - - - - - j
| l ' |
| ' |
| ' |
@@ -680,6 +682,58 @@ Feature: Simple Turns
| j,o | Kapweg,Kapweg,Kapweg | depart,continue uturn,arrive |
| a,i | Kurt,Kurt,Kurt | depart,continue uturn,arrive |
#http://www.openstreetmap.org/#map=18/52.56251/13.32650
Scenario: Curved Turn on Separated Directions
Given the node map
"""
e d
f c - - - - - - - - - - - j
| l ' |
| ' |
| ' |
| ' |
| ' |
| n |
| |
| ' |
| |
| ' |
| |
| |
| |
|' |
| |
| |
| |
| |
g |
h - - - - - - - - - - - - - - - b - - - - - - - - - - - o
| |
| |
| |
| |
| |
| |
i a
"""
And the ways
| nodes | name | oneway | lanes | highway |
| jc | Kapweg | yes | 3 | primary |
| clngh | Kapweg | yes | | primary_link |
| hbo | Kapweg | yes | 2 | primary |
| efh | Kurt | yes | 4 | secondary |
| hi | Kurt | yes | 3 | primary |
| ab | Kurt | yes | 4 | primary |
| cd | Kurt | yes | 3 | secondary |
| bc | Kurt | yes | 2 | primary |
When I route I should get
| waypoints | route | turns |
| j,i | Kapweg,Kurt,Kurt | depart,turn left,arrive |
| j,o | Kapweg,Kapweg,Kapweg | depart,continue uturn,arrive |
| a,i | Kurt,Kurt,Kurt | depart,continue uturn,arrive |
#http://www.openstreetmap.org/#map=19/52.53731/13.36033
Scenario: Splitting Road to Left
Given the node map
@@ -775,7 +829,7 @@ Feature: Simple Turns
| waypoints | route | turns |
| a,j | Siemens,Siemens,Siemens | depart,continue slight right,arrive |
| a,g | Siemens,Erna,Erna | depart,new name slight left,arrive |
| g,j | Erna,Siemens,Siemens | depart,turn sharp left,arrive |
| g,j | Erna,Siemens,Siemens | depart,turn left,arrive |
| g,a | Erna,Siemens,Siemens | depart,new name slight right,arrive |
#http://www.openstreetmap.org/#map=19/52.51303/13.32170
@@ -1112,8 +1166,9 @@ Feature: Simple Turns
"""
And the ways
| nodes | name | highway | lanes |
| abcdefghijklmnopc | circled | residential | 1 |
| nodes | name | highway | lanes | oneway |
| abc | circled | residential | 1 | no |
| cdefghijklmnopc | circled | residential | 1 | yes |
When I route I should get
| waypoints | bearings | route | turns |
@@ -1168,3 +1223,97 @@ Feature: Simple Turns
When I route I should get
| waypoints | route |
| a,e | ab,bcde,bcde |
@3401
Scenario: Curve With Duplicated Coordinates
Given the node locations
| node | lat | lon | # |
| a | 0.9999280745650984 | 1.0 | |
| b | 0.9999280745650984 | 1.0000179813587253 | |
| c | 0.9999280745650984 | 1.0000359627174509 | |
| d | 0.9999460559238238 | 1.0000674300952204 | |
| e | 0.9999640372825492 | 1.0000809161142643 | |
| f | 0.9999820186412746 | 1.0000854114539457 | |
| g | 1.0 | 1.0000854114539457 | |
| h | 1.0 | 1.0000854114539457 | #same as g |
| z | 0.9999100932063729 | 1.0000179813587253 | |
# g
# |
# f
# '
# e
# '
# d
# '
#a - b - c
# |
# z
And the ways
| nodes | oneway | lanes | # |
| ab | yes | 1 | |
| zb | yes | 1 | |
| bcdefgh | yes | 1 | #intentional duplication |
# we don't care for turn instructions, this is a coordinate extraction bug check
When I route I should get
| waypoints | route | intersections |
| a,g | ab,bcdefgh,bcdefgh | true:90;true:45 false:180 false:270;true:180 |
#https://github.com/Project-OSRM/osrm-backend/pull/3469#issuecomment-270806580
Scenario: Oszillating Lower Priority Road
#Given the node map
# """
# a -db c
# f
# """
Given the node locations
| node | lat | lon | # |
| a | 1.0 | 1.0 | |
| b | 1.0000179813587253 | 1.0 | |
| c | 1.0000204580571323 | 1.0 | |
| d | 1.0000179813587253 | 1.0 | same as b |
| f | 1.0000179813587253 | 1.0000179813587253 | |
And the ways
| nodes | oneway | lanes | highway |
| ab | yes | 1 | primary |
| bf | yes | 1 | primary |
| bcd | yes | 1 | service |
# we don't care for turn instructions, this is a coordinate extraction bug check
When I route I should get
| waypoints | route |
| a,d | ab,ab |
Scenario: Sharp Turn Onto A Bridge
Given the node map
"""
e
|
|
|
|
|
|
|
|
|
|
|
|
|
g a - - -b
f /
d -c
"""
And the ways
| nodes | oneway | lanes |
| gaf | yes | 1 |
| abcde | yes | 1 |
When I route I should get
| waypoints | route |
| g,e | abcde,abcde |
+35 -13
View File
@@ -44,6 +44,27 @@ Feature: Turn Lane Guidance
| a,c | in,straight,straight | depart,new name straight,arrive | ,straight:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,straight:false right:true, |
# Turn Lane onto a ferry could end up breaking in intersection generation
Scenario: Basic Turn Lane 3-way Turn with designated lane
Given the node map
"""
a - b ~ ~ c - e
| |
d f
"""
And the ways
| nodes | turn:lanes:forward | name | route |
| ab | through\|through\|right | ferry-route | |
| bc | through\|through\|right | ferry-route | ferry |
| ce | | ferry-route | |
| bd | | right | |
| cf | | right | |
When I route I should get
| waypoints | route | turns |
| a,e | ferry-route,ferry-route,ferry-route,ferry-route | depart,notification straight,notification straight,arrive |
@simple
Scenario: Basic Turn Lane 4-Way Turn
Given the node map
@@ -95,24 +116,25 @@ Feature: Turn Lane Guidance
Scenario: Basic Turn Lane 4-Way With U-Turn Lane
Given the node map
"""
e
a 1 b c
d
e
f a-1-b---c
d
"""
And the ways
| nodes | turn:lanes | turn:lanes:forward | name |
| ab | | reverse;left\|through;right | in |
| bc | | | straight |
| bd | | | right |
| be | | | left |
| nodes | turn:lanes | turn:lanes:forward | name | # |
| ab | | reverse;left\|through;right | in | |
| bc | | | straight | |
| bd | | | right | |
| be | | | left | |
| fa | | | uturn-avoider | #due to https://github.com/Project-OSRM/osrm-backend/issues/3359 |
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,left;uturn:false straight;right:true, |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,left;uturn:false straight;right:true, |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,left;uturn:true straight;right:false, |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,left;uturn:true straight;right:false, |
| from | to | bearings | route | turns | lanes | locations |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,left;uturn:false straight;right:true, | a,b,c |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,left;uturn:false straight;right:true, | a,b,d |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,left;uturn:true straight;right:false, | a,b,e |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,left;uturn:true straight;right:false, | _,b,a |
#this next test requires decision on how to announce lanes for going straight if there is no turn
+10 -10
View File
@@ -1179,8 +1179,8 @@ Feature: Simple Turns
Scenario: Obvious Index wigh very narrow turn to the right
Given the node map
"""
a b c
d
a - b -.-.- - - c
' ' 'd
"""
And the ways
@@ -1198,8 +1198,8 @@ Feature: Simple Turns
Scenario: Obvious Index wigh very narrow turn to the right
Given the node map
"""
a b c
e d f
a - b - . -.- - c
e - -'-'d-f
"""
And the ways
@@ -1218,8 +1218,8 @@ Feature: Simple Turns
Scenario: Obvious Index wigh very narrow turn to the left
Given the node map
"""
d
a b c
. . .d
a - b -'-'- - - c
"""
And the ways
@@ -1237,8 +1237,8 @@ Feature: Simple Turns
Scenario: Obvious Index wigh very narrow turn to the left
Given the node map
"""
e d f
a b c
e - -.- d-f
a - b - ' - - - c
"""
And the ways
@@ -1373,5 +1373,5 @@ Feature: Simple Turns
| kchm | Alexanderstr | primary | yes |
When I route I should get
| waypoints | turns | route |
| a,d | depart,new name straight,arrive | Stralauer Str,Holzmarktstr,Holzmarktstr |
| waypoints | turns | route |
| a,d | depart,arrive | Stralauer Str,Holzmarktstr |
+16
View File
@@ -3,6 +3,14 @@ Feature: osrm-contract command line options: invalid options
Background:
Given the profile "testbot"
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been extracted
Scenario: osrm-contract - Non-existing option
When I try to run "osrm-contract --fly-me-to-the-moon"
@@ -10,3 +18,11 @@ Feature: osrm-contract command line options: invalid options
And stderr should contain "option"
And stderr should contain "fly-me-to-the-moon"
And it should exit with an error
# This tests the error messages when you try to use --segment-speed-file,
# but osrm-extract has not been run with --generate-edge-lookup
Scenario: osrm-contract - Someone forgot --generate-edge-lookup on osrm-extract
When I try to run "osrm-contract --segment-speed-file /dev/null {processed_file}"
Then stderr should contain "Error while trying to mmap"
Then stderr should contain ".osrm.edge_penalties"
And it should exit with an error
+1 -18
View File
@@ -37,7 +37,7 @@ module.exports = function () {
outputRow[direction] = result[direction].status ?
result[direction].status.toString() : '';
break;
case /^\d+ s/.test(want):
case /^[\d\.]+ s/.test(want):
// the result here can come back as a non-number value like
// `diff`, but we only want to apply the unit when it comes
// back as a number, for tableDiff's literal comparison
@@ -127,23 +127,6 @@ module.exports = function () {
var parseRes = (key, scb) => {
if (result.forw[key] === result.backw[key]) {
result.bothw[key] = result.forw[key];
// FIXME these time and speed checks are stopgaps for precision errors in how
// OSRM returns inconsistent durations for rev/for requests along the same way
} else if (key === 'time') {
var range = [result.forw[key] - 1, result.forw[key] + 1];
if (result.backw[key] >= range[0] && result.backw[key] <= range[1])
// usually when we see minor differences here there's an integer
// duration value and one that comes back with a .9 or .1 rounding.
// This returns the integer one
result.bothw[key] = parseInt(result.forw[key]) === result.forw[key] ? result.forw[key] : result.backw[key];
else
result.bothw[key] = 'diff';
} else if (key === 'speed') {
if (Math.abs(result.backw.time - result.forw.time) < 0.2) {
result.bothw[key] = parseInt(result.forw[key]) === result.forw[key] ? result.forw[key] : result.backw[key];
} else {
result.bothw[key] = 'diff';
}
} else {
result.bothw[key] = 'diff';
}
+12 -16
View File
@@ -48,7 +48,7 @@ Feature: Bearing parameter
Scenario: Testbot - Initial bearing on split way
Given the node map
"""
g d 1 c f
g d 2 1 c f
h a 0 b e
"""
@@ -64,21 +64,17 @@ Feature: Bearing parameter
| ha | yes |
When I route I should get
| from | to | bearings | route | bearing |
| 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 | 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 | | |
| from | to | bearings | route | bearing |
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
| 0 | b | 170 170 | da,da | 0->0,0->0 |
| 0 | b | 189 189 | da,da | 0->0,0->0 |
| 0 | 1 | 90 270 | ab,bc,cd,cd | 0->90,90->0,0->270,270->0 |
| 1 | 2 | 10 10 | bc,bc | 0->0,0->0 |
| 1 | 2 | 90 90 | ab,bc,cd,da,ab,ab | 0->90,90->0,0->270,270->180,180->90,90->0 |
| 1 | 0 | 189 189 | da,da | 0->180,180->0 |
| 1 | 2 | 270 270 | cd,cd | 0->270,270->0 |
| 1 | 2 | 349 349 | | |
Scenario: Testbot - Initial bearing in all direction
Given the node map
+2 -2
View File
@@ -20,5 +20,5 @@ Feature: Geometry Compression
When I route I should get
| from | to | route | distance | speed |
| b | e | abcdef,abcdef | 588.8m | 36 km/h |
| e | b | abcdef,abcdef | 588.8m | 36 km/h |
| b | e | abcdef,abcdef | 588.6m | 36 km/h |
| e | b | abcdef,abcdef | 588.6m | 36 km/h |
+42
View File
@@ -0,0 +1,42 @@
@routing @testbot @nil
Feature: Testbot - Check assigning nil values
Scenario: Assign nil values to all way strings
Given the profile file "testbot" extended with
"""
function way_function (way, result)
result.name = "name"
result.ref = "ref"
result.destinations = "destinations"
result.pronunciation = "pronunciation"
result.turn_lanes_forward = "turn_lanes_forward"
result.turn_lanes_backward = "turn_lanes_backward"
result.name = nil
result.ref = nil
result.destinations = nil
result.pronunciation = nil
result.turn_lanes_forward = nil
result.turn_lanes_backward = nil
result.forward_speed = 10
result.backward_speed = 10
result.forward_mode = mode.driving
result.backward_mode = mode.driving
end
"""
Given the node map
"""
a b c
d
"""
And the ways
| nodes |
| ab |
| bc |
| bd |
When I route I should get
| from | to | route |
| a | d | ,, |
| d | a | ,, |
-25
View File
@@ -83,28 +83,3 @@ Feature: Testbot - side bias
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
Scenario: Mixed Entry and Exit
And a grid size of 10 meters
And the node map
"""
c a
j b f
k e
l h d
g i
"""
And the ways
| nodes | junction | oneway |
| cba | | yes |
| fed | | yes |
| ihg | | yes |
| lkj | | yes |
| behkb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| c,a | cba,cba,cba | depart,roundabout-exit-1,arrive |
| l,a | lkj,cba,cba | depart,roundabout-exit-2,arrive |
| i,a | ihg,cba,cba | depart,roundabout-exit-3,arrive |
+1
View File
@@ -81,6 +81,7 @@ class Contractor
EdgeID
LoadEdgeExpandedGraph(const std::string &edge_based_graph_path,
util::DeallocatingVector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights,
const std::string &edge_segment_lookup_path,
const std::string &edge_penalty_path,
const std::vector<std::string> &segment_speed_path,
+23 -21
View File
@@ -6,8 +6,8 @@
#include "util/deallocating_vector.hpp"
#include "util/dynamic_graph.hpp"
#include "util/integer_range.hpp"
#include "util/log.hpp"
#include "util/percent.hpp"
#include "util/simple_logger.hpp"
#include "util/timing_util.hpp"
#include "util/typedefs.hpp"
#include "util/xor_fast_hash.hpp"
@@ -156,11 +156,10 @@ class GraphContractor
#ifndef NDEBUG
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
{
util::SimpleLogger().Write(logWARNING)
<< "Edge weight large -> "
<< static_cast<unsigned int>(std::max(diter->weight, 1)) << " : "
<< static_cast<unsigned int>(diter->source) << " -> "
<< static_cast<unsigned int>(diter->target);
util::Log(logWARNING) << "Edge weight large -> "
<< static_cast<unsigned int>(std::max(diter->weight, 1))
<< " : " << static_cast<unsigned int>(diter->source) << " -> "
<< static_cast<unsigned int>(diter->target);
}
#endif
edges.emplace_back(diter->source,
@@ -245,15 +244,14 @@ class GraphContractor
}
}
}
util::SimpleLogger().Write() << "merged " << edges.size() - edge << " edges out of "
<< edges.size();
util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size();
edges.resize(edge);
contractor_graph = std::make_shared<ContractorGraph>(nodes, edges);
edges.clear();
edges.shrink_to_fit();
BOOST_ASSERT(0 == edges.capacity());
util::SimpleLogger().Write() << "contractor finished initalization";
util::Log() << "contractor finished initalization";
}
void Run(double core_factor = 1.0)
@@ -270,7 +268,6 @@ class GraphContractor
const constexpr size_t DeleteGrainSize = 1;
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
util::Percent p(number_of_nodes);
ThreadDataContainer thread_data_list(number_of_nodes);
@@ -292,9 +289,10 @@ class GraphContractor
bool use_cached_node_priorities = !node_levels.empty();
if (use_cached_node_priorities)
{
std::cout << "using cached node priorities ..." << std::flush;
util::UnbufferedLog log;
log << "using cached node priorities ...";
node_priorities.swap(node_levels);
std::cout << "ok" << std::endl;
log << "ok";
}
else
{
@@ -302,7 +300,8 @@ class GraphContractor
node_priorities.resize(number_of_nodes);
node_levels.resize(number_of_nodes);
std::cout << "initializing elimination PQ ..." << std::flush;
util::UnbufferedLog log;
log << "initializing elimination PQ ...";
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
[this, &node_priorities, &node_depth, &thread_data_list](
const tbb::blocked_range<int> &range) {
@@ -313,11 +312,14 @@ class GraphContractor
this->EvaluateNodePriority(data, node_depth[x], x);
}
});
std::cout << "ok" << std::endl;
log << "ok";
}
BOOST_ASSERT(node_priorities.size() == number_of_nodes);
std::cout << "preprocessing " << number_of_nodes << " nodes ..." << std::flush;
util::Log() << "preprocessing " << number_of_nodes << " nodes ...";
util::UnbufferedLog log;
util::Percent p(log, number_of_nodes);
unsigned current_level = 0;
bool flushed_contractor = false;
@@ -331,7 +333,7 @@ class GraphContractor
new_edge_set; // this one is not explicitely
// cleared since it goes out of
// scope anywa
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
log << " [flush " << number_of_contracted_nodes << " nodes] ";
// Delete old heap data to free memory that we need for the coming operations
thread_data_list.data.clear();
@@ -599,9 +601,8 @@ class GraphContractor
is_core_node.clear();
}
util::SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes "
<< contractor_graph->GetNumberOfEdges() << " edges."
<< std::endl;
util::Log() << "[core] " << remaining_nodes.size() << " nodes "
<< contractor_graph->GetNumberOfEdges() << " edges.";
thread_data_list.data.clear();
}
@@ -618,8 +619,9 @@ class GraphContractor
template <class Edge> inline void GetEdges(util::DeallocatingVector<Edge> &edges)
{
util::Percent p(contractor_graph->GetNumberOfNodes());
util::SimpleLogger().Write() << "Getting edges of minimized graph";
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
util::Percent p(log, contractor_graph->GetNumberOfNodes());
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
if (contractor_graph->GetNumberOfNodes())
{
+3
View File
@@ -26,6 +26,9 @@ struct QueryEdge
forward = other.forward;
backward = other.backward;
}
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
// node. Otherwise we see the edge based node to access node data.
NodeID id : 31;
bool shortcut : 1;
int weight : 30;
+14 -10
View File
@@ -42,7 +42,8 @@ std::string modeToString(const extractor::TravelMode mode);
} // namespace detail
template <unsigned POLYLINE_PRECISION, typename ForwardIter> util::json::String makePolyline(ForwardIter begin, ForwardIter end)
template <unsigned POLYLINE_PRECISION, typename ForwardIter>
util::json::String makePolyline(ForwardIter begin, ForwardIter end)
{
return {encodePolyline<POLYLINE_PRECISION>(begin, end)};
}
@@ -53,22 +54,25 @@ 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;
if (num_coordinates > 1)
{
geojson.values["type"] = "LineString";
util::json::Array coordinates;
coordinates.values.reserve(num_coordinates);
std::transform(
begin, end, std::back_inserter(coordinates.values), &detail::coordinateToLonLat);
geojson.values["coordinates"] = std::move(coordinates);
auto into = std::back_inserter(coordinates.values);
std::transform(begin, end, into, &detail::coordinateToLonLat);
}
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);
// For a single location we create a [location, location] LineString
// instead of a single Point making the GeoJSON output consistent.
coordinates.values.reserve(2);
auto location = detail::coordinateToLonLat(*begin);
coordinates.values.push_back(location);
coordinates.values.push_back(location);
}
geojson.values["coordinates"] = std::move(coordinates);
return geojson;
}
+6 -6
View File
@@ -196,16 +196,16 @@ class RouteAPI : public BaseAPI
[this, &leg_geometry](const guidance::RouteStep &step) {
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
{
return static_cast<util::json::Value>(
json::makePolyline<100000>(leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end));
return static_cast<util::json::Value>(json::makePolyline<100000>(
leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end));
}
if (parameters.geometries == RouteParameters::GeometriesType::Polyline6)
{
return static_cast<util::json::Value>(
json::makePolyline<1000000>(leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end));
return static_cast<util::json::Value>(json::makePolyline<1000000>(
leg_geometry.locations.begin() + step.geometry_begin,
leg_geometry.locations.begin() + step.geometry_end));
}
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
+6 -6
View File
@@ -1,7 +1,7 @@
#ifndef OSRM_ENGINE_DATA_WATCHDOG_HPP
#define OSRM_ENGINE_DATA_WATCHDOG_HPP
#include "engine/datafacade/shared_datafacade.hpp"
#include "engine/datafacade/shared_memory_datafacade.hpp"
#include "storage/shared_barriers.hpp"
#include "storage/shared_datatype.hpp"
@@ -102,10 +102,10 @@ class DataWatchdog
boost::upgrade_to_unique_lock<boost::upgrade_mutex> unique_facade_lock(facade_lock);
current_timestamp = *shared_timestamp;
facade = std::make_shared<datafacade::SharedDataFacade>(shared_barriers,
current_timestamp.layout,
current_timestamp.data,
current_timestamp.timestamp);
facade = std::make_shared<datafacade::SharedMemoryDataFacade>(shared_barriers,
current_timestamp.layout,
current_timestamp.data,
current_timestamp.timestamp);
return get_locked_facade();
}
@@ -119,7 +119,7 @@ class DataWatchdog
std::unique_ptr<storage::SharedMemory> shared_regions;
mutable boost::shared_mutex facade_mutex;
std::shared_ptr<datafacade::SharedDataFacade> facade;
std::shared_ptr<datafacade::SharedMemoryDataFacade> facade;
storage::SharedDataTimestamp current_timestamp;
};
}
@@ -1,11 +1,6 @@
#ifndef SHARED_DATAFACADE_HPP
#define SHARED_DATAFACADE_HPP
#ifndef CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP
#define CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP
// implements all data storage when shared memory _IS_ used
#include "storage/shared_barriers.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "extractor/compressed_edge_container.hpp"
@@ -17,11 +12,13 @@
#include "util/guidance/turn_lanes.hpp"
#include "engine/geospatial_query.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/log.hpp"
#include "util/packed_vector.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/typedefs.hpp"
@@ -47,9 +44,15 @@ namespace engine
namespace datafacade
{
class SharedDataFacade final : public BaseDataFacade
/**
* This base class implements the Datafacade interface for accessing
* data that's stored in a single large block of memory (RAM).
*
* In this case "internal memory" refers to RAM - as opposed to "external memory",
* which usually refers to disk.
*/
class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
private:
using super = BaseDataFacade;
using QueryGraph = util::StaticGraph<EdgeData, true>;
@@ -63,18 +66,8 @@ class SharedDataFacade final : public BaseDataFacade
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using RTreeNode = SharedRTree::TreeNode;
storage::SharedDataLayout *data_layout;
char *shared_memory;
std::shared_ptr<storage::SharedBarriers> shared_barriers;
storage::SharedDataType layout_region;
storage::SharedDataType data_region;
unsigned shared_timestamp;
unsigned m_check_sum;
std::unique_ptr<QueryGraph> m_query_graph;
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;
@@ -121,362 +114,303 @@ class SharedDataFacade final : public BaseDataFacade
std::shared_ptr<util::RangeTable<16, true>> m_bearing_ranges_table;
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
void LoadChecksum()
void InitializeChecksumPointer(storage::DataLayout &data_layout, char *memory_block)
{
m_check_sum = *data_layout->GetBlockPtr<unsigned>(shared_memory,
storage::SharedDataLayout::HSGR_CHECKSUM);
util::SimpleLogger().Write() << "set checksum: " << m_check_sum;
m_check_sum =
*data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::HSGR_CHECKSUM);
util::Log() << "set checksum: " << m_check_sum;
}
void LoadProfileProperties()
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout, char *memory_block)
{
m_profile_properties = data_layout->GetBlockPtr<extractor::ProfileProperties>(
shared_memory, storage::SharedDataLayout::PROPERTIES);
m_profile_properties = data_layout.GetBlockPtr<extractor::ProfileProperties>(
memory_block, storage::DataLayout::PROPERTIES);
}
void LoadTimestamp()
void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto timestamp_ptr =
data_layout->GetBlockPtr<char>(shared_memory, storage::SharedDataLayout::TIMESTAMP);
m_timestamp.resize(data_layout->GetBlockSize(storage::SharedDataLayout::TIMESTAMP));
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::TIMESTAMP);
m_timestamp.resize(data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP));
std::copy(timestamp_ptr,
timestamp_ptr + data_layout->GetBlockSize(storage::SharedDataLayout::TIMESTAMP),
timestamp_ptr + data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP),
m_timestamp.begin());
}
void LoadRTree()
void InitializeRTreePointers(storage::DataLayout &data_layout, char *memory_block)
{
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
const auto file_index_ptr = data_layout->GetBlockPtr<char>(
shared_memory, storage::SharedDataLayout::FILE_INDEX_PATH);
const auto file_index_ptr =
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::FILE_INDEX_PATH);
file_index_path = boost::filesystem::path(file_index_ptr);
if (!boost::filesystem::exists(file_index_path))
{
util::SimpleLogger().Write(logDEBUG) << "Leaf file name " << file_index_path.string();
util::Log(logDEBUG) << "Leaf file name " << file_index_path.string();
throw util::exception("Could not load " + file_index_path.string() +
"Is any data loaded into shared memory?");
"Is any data loaded into shared memory?" + SOURCE_REF);
}
auto tree_ptr = data_layout->GetBlockPtr<RTreeNode>(
shared_memory, storage::SharedDataLayout::R_SEARCH_TREE);
auto tree_ptr =
data_layout.GetBlockPtr<RTreeNode>(memory_block, storage::DataLayout::R_SEARCH_TREE);
m_static_rtree.reset(
new SharedRTree(tree_ptr,
data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE],
file_index_path,
m_coordinate_list));
m_geospatial_query.reset(
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadGraph()
void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto graph_nodes_ptr = data_layout->GetBlockPtr<GraphNode>(
shared_memory, storage::SharedDataLayout::GRAPH_NODE_LIST);
auto graph_nodes_ptr =
data_layout.GetBlockPtr<GraphNode>(memory_block, storage::DataLayout::GRAPH_NODE_LIST);
auto graph_edges_ptr = data_layout->GetBlockPtr<GraphEdge>(
shared_memory, storage::SharedDataLayout::GRAPH_EDGE_LIST);
auto graph_edges_ptr =
data_layout.GetBlockPtr<GraphEdge>(memory_block, storage::DataLayout::GRAPH_EDGE_LIST);
util::ShM<GraphNode, true>::vector node_list(
graph_nodes_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_NODE_LIST]);
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::GRAPH_NODE_LIST]);
util::ShM<GraphEdge, true>::vector edge_list(
graph_edges_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_EDGE_LIST]);
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::GRAPH_EDGE_LIST]);
m_query_graph.reset(new QueryGraph(node_list, edge_list));
}
void LoadNodeAndEdgeInformation()
void InitializeNodeAndEdgeInformationPointers(storage::DataLayout &data_layout,
char *memory_block)
{
const auto coordinate_list_ptr = data_layout->GetBlockPtr<util::Coordinate>(
shared_memory, storage::SharedDataLayout::COORDINATE_LIST);
m_coordinate_list.reset(
coordinate_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
const auto coordinate_list_ptr = data_layout.GetBlockPtr<util::Coordinate>(
memory_block, storage::DataLayout::COORDINATE_LIST);
m_coordinate_list.reset(coordinate_list_ptr,
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
for (unsigned i = 0; i < m_coordinate_list.size(); ++i)
{
BOOST_ASSERT(GetCoordinateOfNode(i).IsValid());
}
const auto osmnodeid_list_ptr = data_layout->GetBlockPtr<std::uint64_t>(
shared_memory, storage::SharedDataLayout::OSM_NODE_ID_LIST);
m_osmnodeid_list.reset(
osmnodeid_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::OSM_NODE_ID_LIST]);
const auto osmnodeid_list_ptr = data_layout.GetBlockPtr<std::uint64_t>(
memory_block, storage::DataLayout::OSM_NODE_ID_LIST);
m_osmnodeid_list.reset(osmnodeid_list_ptr,
data_layout.num_entries[storage::DataLayout::OSM_NODE_ID_LIST]);
// We (ab)use the number of coordinates here because we know we have the same amount of ids
m_osmnodeid_list.set_number_of_entries(
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
const auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
shared_memory, storage::SharedDataLayout::TRAVEL_MODE);
const auto travel_mode_list_ptr = data_layout.GetBlockPtr<extractor::TravelMode>(
memory_block, storage::DataLayout::TRAVEL_MODE);
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list);
const auto lane_data_id_ptr = data_layout->GetBlockPtr<LaneDataID>(
shared_memory, storage::SharedDataLayout::LANE_DATA_ID);
const auto lane_data_id_ptr =
data_layout.GetBlockPtr<LaneDataID>(memory_block, storage::DataLayout::LANE_DATA_ID);
util::ShM<LaneDataID, true>::vector lane_data_id(
lane_data_id_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DATA_ID]);
lane_data_id_ptr, data_layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
m_lane_data_id = std::move(lane_data_id);
const auto lane_tupel_id_pair_ptr =
data_layout->GetBlockPtr<util::guidance::LaneTupleIdPair>(
shared_memory, storage::SharedDataLayout::TURN_LANE_DATA);
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
memory_block, storage::DataLayout::TURN_LANE_DATA);
util::ShM<util::guidance::LaneTupleIdPair, true>::vector lane_tupel_id_pair(
lane_tupel_id_pair_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_LANE_DATA]);
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
const auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
data_layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
memory_block, storage::DataLayout::TURN_INSTRUCTION);
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list = std::move(turn_instruction_list);
const auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::NAME_ID_LIST);
const auto name_id_list_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::NAME_ID_LIST);
util::ShM<unsigned, true>::vector name_id_list(
name_id_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_ID_LIST]);
name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
m_name_ID_list = std::move(name_id_list);
const auto entry_class_id_list_ptr = data_layout->GetBlockPtr<EntryClassID>(
shared_memory, storage::SharedDataLayout::ENTRY_CLASSID);
const auto entry_class_id_list_ptr =
data_layout.GetBlockPtr<EntryClassID>(memory_block, storage::DataLayout::ENTRY_CLASSID);
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
entry_class_id_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASSID]);
entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
m_entry_class_id_list = std::move(entry_class_id_list);
const auto pre_turn_bearing_ptr = data_layout->GetBlockPtr<util::guidance::TurnBearing>(
shared_memory, storage::SharedDataLayout::PRE_TURN_BEARING);
const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_block, storage::DataLayout::PRE_TURN_BEARING);
typename util::ShM<util::guidance::TurnBearing, true>::vector pre_turn_bearing(
pre_turn_bearing_ptr,
data_layout->num_entries[storage::SharedDataLayout::PRE_TURN_BEARING]);
pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
m_pre_turn_bearing = std::move(pre_turn_bearing);
const auto post_turn_bearing_ptr = data_layout->GetBlockPtr<util::guidance::TurnBearing>(
shared_memory, storage::SharedDataLayout::POST_TURN_BEARING);
const auto post_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_block, storage::DataLayout::POST_TURN_BEARING);
typename util::ShM<util::guidance::TurnBearing, true>::vector post_turn_bearing(
post_turn_bearing_ptr,
data_layout->num_entries[storage::SharedDataLayout::POST_TURN_BEARING]);
post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
m_post_turn_bearing = std::move(post_turn_bearing);
}
void LoadViaNodeList()
void InitializeViaNodeListPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto via_geometry_list_ptr = data_layout->GetBlockPtr<GeometryID>(
shared_memory, storage::SharedDataLayout::VIA_NODE_LIST);
auto via_geometry_list_ptr =
data_layout.GetBlockPtr<GeometryID>(memory_block, storage::DataLayout::VIA_NODE_LIST);
util::ShM<GeometryID, true>::vector via_geometry_list(
via_geometry_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::VIA_NODE_LIST]);
via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
m_via_geometry_list = std::move(via_geometry_list);
}
void LoadNames()
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
{
auto offsets_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::NAME_OFFSETS);
auto blocks_ptr = data_layout->GetBlockPtr<IndexBlock>(
shared_memory, storage::SharedDataLayout::NAME_BLOCKS);
auto offsets_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::NAME_OFFSETS);
auto blocks_ptr =
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::NAME_BLOCKS);
util::ShM<unsigned, true>::vector name_offsets(
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_OFFSETS]);
offsets_ptr, data_layout.num_entries[storage::DataLayout::NAME_OFFSETS]);
util::ShM<IndexBlock, true>::vector name_blocks(
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_BLOCKS]);
blocks_ptr, data_layout.num_entries[storage::DataLayout::NAME_BLOCKS]);
auto names_list_ptr = data_layout->GetBlockPtr<char>(
shared_memory, storage::SharedDataLayout::NAME_CHAR_LIST);
auto names_list_ptr =
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::NAME_CHAR_LIST);
util::ShM<char, true>::vector names_char_list(
names_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_CHAR_LIST]);
names_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_CHAR_LIST]);
m_name_table = std::make_unique<util::RangeTable<16, true>>(
name_offsets, name_blocks, static_cast<unsigned>(names_char_list.size()));
m_names_char_list = std::move(names_char_list);
}
void LoadTurnLaneDescriptions()
void InitializeTurnLaneDescriptionsPointers(storage::DataLayout &data_layout,
char *memory_block)
{
auto offsets_ptr = data_layout->GetBlockPtr<std::uint32_t>(
shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS);
auto offsets_ptr = data_layout.GetBlockPtr<std::uint32_t>(
memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS);
util::ShM<std::uint32_t, true>::vector offsets(
offsets_ptr,
data_layout->num_entries[storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS]);
offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]);
m_lane_description_offsets = std::move(offsets);
auto masks_ptr = data_layout->GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_MASKS);
auto masks_ptr = data_layout.GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS);
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector masks(
masks_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DESCRIPTION_MASKS]);
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
m_lane_description_masks = std::move(masks);
}
void LoadCoreInformation()
void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto core_marker_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::CORE_MARKER);
auto core_marker_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CORE_MARKER);
util::ShM<bool, true>::vector is_core_node(
core_marker_ptr, data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER]);
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CORE_MARKER]);
m_is_core_node = std::move(is_core_node);
}
void LoadGeometries()
void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block)
{
auto geometries_index_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_INDEX);
auto geometries_index_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::GEOMETRIES_INDEX);
util::ShM<unsigned, true>::vector geometry_begin_indices(
geometries_index_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_INDEX]);
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
m_geometry_indices = std::move(geometry_begin_indices);
auto geometries_node_list_ptr = data_layout->GetBlockPtr<NodeID>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_NODE_LIST);
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::ShM<NodeID, true>::vector geometry_node_list(
geometries_node_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_NODE_LIST]);
data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]);
m_geometry_node_list = std::move(geometry_node_list);
auto geometries_fwd_weight_list_ptr = data_layout->GetBlockPtr<EdgeWeight>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
util::ShM<EdgeWeight, true>::vector geometry_fwd_weight_list(
geometries_fwd_weight_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
m_geometry_fwd_weight_list = std::move(geometry_fwd_weight_list);
auto geometries_rev_weight_list_ptr = data_layout->GetBlockPtr<EdgeWeight>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_REV_WEIGHT_LIST);
auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
util::ShM<EdgeWeight, true>::vector geometry_rev_weight_list(
geometries_rev_weight_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
m_geometry_rev_weight_list = std::move(geometry_rev_weight_list);
auto datasources_list_ptr = data_layout->GetBlockPtr<uint8_t>(
shared_memory, storage::SharedDataLayout::DATASOURCES_LIST);
auto datasources_list_ptr =
data_layout.GetBlockPtr<uint8_t>(memory_block, storage::DataLayout::DATASOURCES_LIST);
util::ShM<uint8_t, true>::vector datasources_list(
datasources_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::DATASOURCES_LIST]);
datasources_list_ptr, data_layout.num_entries[storage::DataLayout::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);
auto datasource_name_data_ptr =
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::DATASOURCE_NAME_DATA);
util::ShM<char, true>::vector datasource_name_data(
datasource_name_data_ptr,
data_layout->num_entries[storage::SharedDataLayout::DATASOURCE_NAME_DATA]);
data_layout.num_entries[storage::DataLayout::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);
auto datasource_name_offsets_ptr = data_layout.GetBlockPtr<std::size_t>(
memory_block, storage::DataLayout::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]);
data_layout.num_entries[storage::DataLayout::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);
auto datasource_name_lengths_ptr = data_layout.GetBlockPtr<std::size_t>(
memory_block, storage::DataLayout::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]);
data_layout.num_entries[storage::DataLayout::DATASOURCE_NAME_LENGTHS]);
m_datasource_name_lengths = std::move(datasource_name_lengths);
}
void LoadIntersectionClasses()
void InitializeIntersectionClassPointers(storage::DataLayout &data_layout, char *memory_block)
{
auto bearing_class_id_ptr = data_layout->GetBlockPtr<BearingClassID>(
shared_memory, storage::SharedDataLayout::BEARING_CLASSID);
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
memory_block, storage::DataLayout::BEARING_CLASSID);
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
bearing_class_id_ptr,
data_layout->num_entries[storage::SharedDataLayout::BEARING_CLASSID]);
bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]);
m_bearing_class_id_table = std::move(bearing_class_id_table);
auto bearing_class_ptr = data_layout->GetBlockPtr<DiscreteBearing>(
shared_memory, storage::SharedDataLayout::BEARING_VALUES);
auto bearing_class_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
memory_block, storage::DataLayout::BEARING_VALUES);
typename util::ShM<DiscreteBearing, true>::vector bearing_class_table(
bearing_class_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_VALUES]);
bearing_class_ptr, data_layout.num_entries[storage::DataLayout::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);
auto offsets_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
auto blocks_ptr =
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::BEARING_BLOCKS);
util::ShM<unsigned, true>::vector bearing_offsets(
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_OFFSETS]);
offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]);
util::ShM<IndexBlock, true>::vector bearing_blocks(
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_BLOCKS]);
blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]);
m_bearing_ranges_table = std::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);
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
memory_block, storage::DataLayout::ENTRY_CLASS);
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
entry_class_ptr, data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASS]);
entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]);
m_entry_class_table = std::move(entry_class_table);
}
public:
// this function handle the deallocation of the shared memory it we can prove it will not be
// used anymore
virtual ~SharedDataFacade()
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
boost::interprocess::scoped_lock<boost::interprocess::named_sharable_mutex> exclusive_lock(
data_region == storage::DATA_1 ? shared_barriers->regions_1_mutex
: shared_barriers->regions_2_mutex,
boost::interprocess::defer_lock);
// if this returns false this is still in use
if (exclusive_lock.try_lock())
{
// Now check if this is still the newest dataset
const boost::interprocess::sharable_lock<boost::interprocess::named_upgradable_mutex>
lock(shared_barriers->current_regions_mutex);
auto shared_regions = storage::makeSharedMemory(storage::CURRENT_REGIONS);
const auto current_timestamp =
static_cast<const storage::SharedDataTimestamp *>(shared_regions->Ptr());
if (current_timestamp->timestamp == shared_timestamp)
{
util::SimpleLogger().Write(logDEBUG) << "Retaining data with shared timestamp "
<< shared_timestamp;
}
else
{
storage::SharedMemory::Remove(data_region);
storage::SharedMemory::Remove(layout_region);
}
}
}
SharedDataFacade(const std::shared_ptr<storage::SharedBarriers> &shared_barriers_,
storage::SharedDataType layout_region_,
storage::SharedDataType data_region_,
unsigned shared_timestamp_)
: shared_barriers(shared_barriers_), layout_region(layout_region_),
data_region(data_region_), shared_timestamp(shared_timestamp_)
{
util::SimpleLogger().Write(logDEBUG) << "Loading new data with shared timestamp "
<< shared_timestamp;
BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region));
m_layout_memory = storage::makeSharedMemory(layout_region);
data_layout = static_cast<storage::SharedDataLayout *>(m_layout_memory->Ptr());
BOOST_ASSERT(storage::SharedMemory::RegionExists(data_region));
m_large_memory = storage::makeSharedMemory(data_region);
shared_memory = (char *)(m_large_memory->Ptr());
LoadGraph();
LoadChecksum();
LoadNodeAndEdgeInformation();
LoadGeometries();
LoadTimestamp();
LoadViaNodeList();
LoadNames();
LoadTurnLaneDescriptions();
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
LoadIntersectionClasses();
InitializeGraphPointer(data_layout, memory_block);
InitializeChecksumPointer(data_layout, memory_block);
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
InitializeGeometryPointers(data_layout, memory_block);
InitializeTimestampPointer(data_layout, memory_block);
InitializeViaNodeListPointer(data_layout, memory_block);
InitializeNamePointers(data_layout, memory_block);
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
InitializeCoreInformationPointer(data_layout, memory_block);
InitializeProfilePropertiesPointer(data_layout, memory_block);
InitializeRTreePointers(data_layout, memory_block);
InitializeIntersectionClassPointers(data_layout, memory_block);
}
// search graph access
@@ -1000,4 +934,4 @@ class SharedDataFacade final : public BaseDataFacade
}
}
#endif // SHARED_DATAFACADE_HPP
#endif // CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP
@@ -1,974 +0,0 @@
#ifndef INTERNAL_DATAFACADE_HPP
#define INTERNAL_DATAFACADE_HPP
// implements all data storage when shared memory is _NOT_ used
#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 "extractor/compressed_edge_container.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "storage/io.hpp"
#include "storage/storage_config.hpp"
#include "engine/geospatial_query.hpp"
#include "util/graph_loader.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/io.hpp"
#include "util/packed_vector.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/typedefs.hpp"
#include "osrm/coordinate.hpp"
#include <cstddef>
#include <cstdlib>
#include <algorithm>
#include <fstream>
#include <ios>
#include <limits>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread/tss.hpp>
namespace osrm
{
namespace engine
{
namespace datafacade
{
class InternalDataFacade final : public BaseDataFacade
{
private:
using super = BaseDataFacade;
using QueryGraph = util::StaticGraph<typename super::EdgeData>;
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>;
InternalDataFacade() {}
unsigned m_check_sum;
std::unique_ptr<QueryGraph> m_query_graph;
std::string m_timestamp;
util::ShM<util::Coordinate, false>::vector m_coordinate_list;
util::PackedVector<OSMNodeID, false> m_osmnodeid_list;
util::ShM<GeometryID, false>::vector m_via_geometry_list;
util::ShM<unsigned, false>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_list;
util::ShM<LaneDataID, false>::vector m_lane_data_id;
util::ShM<util::guidance::LaneTupleIdPair, false>::vector m_lane_tuple_id_pairs;
util::ShM<extractor::TravelMode, false>::vector m_travel_mode_list;
util::ShM<char, false>::vector m_names_char_list;
util::ShM<unsigned, false>::vector m_geometry_indices;
util::ShM<NodeID, false>::vector m_geometry_node_list;
util::ShM<EdgeWeight, false>::vector m_geometry_fwd_weight_list;
util::ShM<EdgeWeight, false>::vector m_geometry_rev_weight_list;
util::ShM<bool, false>::vector m_is_core_node;
util::ShM<uint8_t, false>::vector m_datasource_list;
util::ShM<std::string, false>::vector m_datasource_names;
util::ShM<std::uint32_t, false>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, false>::vector m_lane_description_masks;
extractor::ProfileProperties m_profile_properties;
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;
// bearings pre/post turn
util::ShM<util::guidance::TurnBearing, false>::vector m_pre_turn_bearing;
util::ShM<util::guidance::TurnBearing, false>::vector m_post_turn_bearing;
// 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);
if (!in_stream)
{
throw util::exception("Could not open " + properties_path.string() + " for reading.");
}
const auto properties_size = storage::io::readPropertiesCount();
storage::io::readProperties(in_stream, &m_profile_properties, properties_size);
}
void LoadLaneTupleIdPairs(const boost::filesystem::path &lane_data_path)
{
boost::filesystem::ifstream in_stream(lane_data_path);
if (!in_stream)
{
throw util::exception("Could not open " + lane_data_path.string() + " for reading.");
}
std::uint64_t size;
in_stream.read(reinterpret_cast<char *>(&size), sizeof(size));
m_lane_tuple_id_pairs.resize(size);
in_stream.read(reinterpret_cast<char *>(&m_lane_tuple_id_pairs[0]),
sizeof(m_lane_tuple_id_pairs) * size);
}
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
{
util::SimpleLogger().Write() << "Loading Timestamp";
boost::filesystem::ifstream timestamp_stream(timestamp_path);
if (!timestamp_stream)
{
throw util::exception("Could not open " + timestamp_path.string() + " for reading.");
}
const auto timestamp_size = storage::io::readNumberOfBytes(timestamp_stream);
m_timestamp.resize(timestamp_size);
storage::io::readTimestamp(timestamp_stream, &m_timestamp.front(), timestamp_size);
}
void LoadGraph(const boost::filesystem::path &hsgr_path)
{
boost::filesystem::ifstream hsgr_input_stream(hsgr_path);
if (!hsgr_input_stream)
{
throw util::exception("Could not open " + hsgr_path.string() + " for reading.");
}
const auto header = storage::io::readHSGRHeader(hsgr_input_stream);
m_check_sum = header.checksum;
util::ShM<QueryGraph::NodeArrayEntry, false>::vector node_list(header.number_of_nodes);
util::ShM<QueryGraph::EdgeArrayEntry, false>::vector edge_list(header.number_of_edges);
storage::io::readHSGR(hsgr_input_stream,
node_list.data(),
header.number_of_nodes,
edge_list.data(),
header.number_of_edges);
m_query_graph = std::unique_ptr<QueryGraph>(new QueryGraph(node_list, edge_list));
util::SimpleLogger().Write() << "Data checksum is " << m_check_sum;
}
void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file_path,
const boost::filesystem::path &edges_file_path)
{
boost::filesystem::ifstream nodes_input_stream(nodes_file_path, std::ios::binary);
if (!nodes_input_stream)
{
throw util::exception("Could not open " + nodes_file_path.string() + " for reading.");
}
const auto number_of_coordinates = storage::io::readElementCount(nodes_input_stream);
m_coordinate_list.resize(number_of_coordinates);
m_osmnodeid_list.reserve(number_of_coordinates);
storage::io::readNodes(
nodes_input_stream, m_coordinate_list.data(), m_osmnodeid_list, number_of_coordinates);
boost::filesystem::ifstream edges_input_stream(edges_file_path, std::ios::binary);
if (!edges_input_stream)
{
throw util::exception("Could not open " + edges_file_path.string() + " for reading.");
}
const auto number_of_edges = storage::io::readElementCount(edges_input_stream);
m_via_geometry_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_lane_data_id.resize(number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_entry_class_id_list.resize(number_of_edges);
m_pre_turn_bearing.resize(number_of_edges);
m_post_turn_bearing.resize(number_of_edges);
storage::io::readEdges(edges_input_stream,
m_via_geometry_list.data(),
m_name_ID_list.data(),
m_turn_instruction_list.data(),
m_lane_data_id.data(),
m_travel_mode_list.data(),
m_entry_class_id_list.data(),
m_pre_turn_bearing.data(),
m_post_turn_bearing.data(),
number_of_edges);
}
void LoadCoreInformation(const boost::filesystem::path &core_data_file)
{
std::ifstream core_stream(core_data_file.string().c_str(), std::ios::binary);
unsigned number_of_markers;
core_stream.read((char *)&number_of_markers, sizeof(unsigned));
std::vector<char> unpacked_core_markers(number_of_markers);
core_stream.read((char *)unpacked_core_markers.data(), sizeof(char) * number_of_markers);
// in this case we have nothing to do
if (number_of_markers <= 0)
{
return;
}
m_is_core_node.resize(number_of_markers);
for (auto i = 0u; i < number_of_markers; ++i)
{
BOOST_ASSERT(unpacked_core_markers[i] == 0 || unpacked_core_markers[i] == 1);
m_is_core_node[i] = unpacked_core_markers[i] == 1;
}
}
void LoadGeometries(const boost::filesystem::path &geometry_file)
{
std::ifstream geometry_stream(geometry_file.string().c_str(), std::ios::binary);
unsigned number_of_indices = 0;
unsigned number_of_compressed_geometries = 0;
geometry_stream.read((char *)&number_of_indices, sizeof(unsigned));
m_geometry_indices.resize(number_of_indices);
if (number_of_indices > 0)
{
geometry_stream.read((char *)&(m_geometry_indices[0]),
number_of_indices * sizeof(unsigned));
}
geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
BOOST_ASSERT(m_geometry_indices.back() == number_of_compressed_geometries);
m_geometry_node_list.resize(number_of_compressed_geometries);
m_geometry_fwd_weight_list.resize(number_of_compressed_geometries);
m_geometry_rev_weight_list.resize(number_of_compressed_geometries);
if (number_of_compressed_geometries > 0)
{
geometry_stream.read((char *)&(m_geometry_node_list[0]),
number_of_compressed_geometries * sizeof(NodeID));
geometry_stream.read((char *)&(m_geometry_fwd_weight_list[0]),
number_of_compressed_geometries * sizeof(EdgeWeight));
geometry_stream.read((char *)&(m_geometry_rev_weight_list[0]),
number_of_compressed_geometries * sizeof(EdgeWeight));
}
}
void LoadDatasourceInfo(const boost::filesystem::path &datasource_names_file,
const boost::filesystem::path &datasource_indexes_file)
{
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!");
}
BOOST_ASSERT(datasources_stream);
const auto number_of_datasources = storage::io::readElementCount(datasources_stream);
if (number_of_datasources > 0)
{
m_datasource_list.resize(number_of_datasources);
storage::io::readDatasourceIndexes(
datasources_stream, &m_datasource_list.front(), number_of_datasources);
}
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!");
}
BOOST_ASSERT(datasourcenames_stream);
const auto datasource_names_data = storage::io::readDatasourceNames(datasourcenames_stream);
m_datasource_names.resize(datasource_names_data.lengths.size());
for (std::size_t i = 0; i < datasource_names_data.lengths.size(); ++i)
{
auto name_begin =
datasource_names_data.names.begin() + datasource_names_data.offsets[i];
auto name_end = datasource_names_data.names.begin() + datasource_names_data.offsets[i] +
datasource_names_data.lengths[i];
m_datasource_names[i] = std::string(name_begin, name_end);
}
}
void LoadRTree()
{
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(
new InternalGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadLaneDescriptions(const boost::filesystem::path &lane_description_file)
{
if (!util::deserializeAdjacencyArray(lane_description_file.string(),
m_lane_description_offsets,
m_lane_description_masks))
util::SimpleLogger().Write(logWARNING) << "Failed to read turn lane descriptions from "
<< lane_description_file.string();
}
void LoadStreetNames(const boost::filesystem::path &names_file)
{
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
name_stream >> m_name_table;
unsigned number_of_chars = 0;
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char));
if (0 == m_names_char_list.size())
{
util::SimpleLogger().Write(logWARNING) << "list of street names is empty";
}
}
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.read(reinterpret_cast<char *>(&num_bearings), sizeof(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()
{
m_static_rtree.reset();
m_geospatial_query.reset();
}
explicit InternalDataFacade(const storage::StorageConfig &config)
{
ram_index_path = config.ram_index_path;
file_index_path = config.file_index_path;
util::SimpleLogger().Write() << "loading graph data";
LoadGraph(config.hsgr_data_path);
util::SimpleLogger().Write() << "loading edge information";
LoadNodeAndEdgeInformation(config.nodes_data_path, config.edges_data_path);
util::SimpleLogger().Write() << "loading core information";
LoadCoreInformation(config.core_data_path);
util::SimpleLogger().Write() << "loading geometries";
LoadGeometries(config.geometries_path);
util::SimpleLogger().Write() << "loading datasource info";
LoadDatasourceInfo(config.datasource_names_path, config.datasource_indexes_path);
util::SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(config.timestamp_path);
util::SimpleLogger().Write() << "loading profile properties";
LoadProfileProperties(config.properties_path);
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading lane tags";
LoadLaneDescriptions(config.turn_lane_description_path);
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
util::SimpleLogger().Write() << "loading intersection class data";
LoadIntersectionClasses(config.intersection_class_path);
util::SimpleLogger().Write() << "Loading Lane Data Pairs";
LoadLaneTupleIdPairs(config.turn_lane_data_path);
}
// search graph access
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final
{
return m_query_graph->GetOutDegree(n);
}
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); }
EdgeData &GetEdgeData(const EdgeID e) const override final
{
return m_query_graph->GetEdgeData(e);
}
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); }
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return m_query_graph->GetAdjacentEdgeRange(node);
}
// searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const override final
{
return m_query_graph->FindEdge(from, to);
}
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final
{
return m_query_graph->FindEdgeInEitherDirection(from, to);
}
EdgeID
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final
{
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
}
EdgeID FindSmallestEdge(const NodeID from,
const NodeID to,
std::function<bool(EdgeData)> filter) const override final
{
return m_query_graph->FindSmallestEdge(from, to, filter);
}
// node and edge information access
util::Coordinate GetCoordinateOfNode(const unsigned id) const override final
{
return m_coordinate_list[id];
}
OSMNodeID GetOSMNodeIDOfNode(const unsigned id) const override final
{
return m_osmnodeid_list.at(id);
}
extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const unsigned id) const override final
{
return m_turn_instruction_list.at(id);
}
extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const override final
{
return m_travel_mode_list.at(id);
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) const override final
{
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);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(
input_coordinate, max_distance, bearing, bearing_range);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(
input_coordinate, max_results, bearing, bearing_range);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) const override final
{
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) const override final
{
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) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range);
}
unsigned GetCheckSum() const override final { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const override final
{
return m_name_ID_list.at(id);
}
std::string GetNameForID(const unsigned name_id) const override final
{
if (std::numeric_limits<unsigned>::max() == name_id)
{
return "";
}
auto range = m_name_table.GetRange(name_id);
std::string result;
result.reserve(range.size());
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_names_char_list.begin() + range.front(),
m_names_char_list.begin() + range.back() + 1,
result.begin());
}
return result;
}
std::string GetRefForID(const unsigned name_id) const override final
{
// We store the ref after the name, destination and pronunciation of a street.
// We do this to get around the street length limit of 255 which would hit
// if we concatenate these. Order (see extractor_callbacks):
// name (0), destination (1), pronunciation (2), ref (3)
return GetNameForID(name_id + 3);
}
std::string GetPronunciationForID(const unsigned name_id) const override final
{
// We store the pronunciation after the name and destination of a street.
// We do this to get around the street length limit of 255 which would hit
// if we concatenate these. Order (see extractor_callbacks):
// name (0), destination (1), pronunciation (2)
return GetNameForID(name_id + 2);
}
std::string GetDestinationsForID(const unsigned name_id) const override final
{
// We store the destination after the name of a street.
// We do this to get around the street length limit of 255 which would hit
// if we concatenate these. Order (see extractor_callbacks):
// name (0), destination (1), pronunciation (2)
return GetNameForID(name_id + 1);
}
virtual GeometryID GetGeometryIndexForEdgeID(const unsigned id) const override final
{
return m_via_geometry_list.at(id);
}
virtual std::size_t GetCoreSize() const override final { return m_is_core_node.size(); }
virtual bool IsCoreNode(const NodeID id) const override final
{
if (m_is_core_node.size() > 0)
{
return m_is_core_node[id];
}
else
{
return false;
}
}
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
{
/*
* NodeID's for geometries are stored in one place for
* both forward and reverse segments along the same bi-
* directional edge. The m_geometry_indices stores
* refences to where to find the beginning of the bi-
* directional edge in the m_geometry_node_list vector. For
* forward geometries of bi-directional edges, edges 2 to
* n of that edge need to be read.
*/
const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id + 1);
std::vector<NodeID> result_nodes;
result_nodes.resize(end - begin);
std::copy(m_geometry_node_list.begin() + begin,
m_geometry_node_list.begin() + end,
result_nodes.begin());
return result_nodes;
}
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const override final
{
/*
* NodeID's for geometries are stored in one place for
* both forward and reverse segments along the same bi-
* directional edge. The m_geometry_indices stores
* refences to where to find the beginning of the bi-
* directional edge in the m_geometry_node_list vector.
* */
const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id + 1);
std::vector<NodeID> result_nodes;
result_nodes.resize(end - begin);
std::copy(m_geometry_node_list.rbegin() + (m_geometry_node_list.size() - end),
m_geometry_node_list.rbegin() + (m_geometry_node_list.size() - begin),
result_nodes.begin());
return result_nodes;
}
virtual std::vector<EdgeWeight>
GetUncompressedForwardWeights(const EdgeID id) const override final
{
/*
* EdgeWeights's for geometries are stored in one place for
* both forward and reverse segments along the same bi-
* directional edge. The m_geometry_indices stores
* refences to where to find the beginning of the bi-
* directional edge in the m_geometry_fwd_weight_list vector.
* */
const unsigned begin = m_geometry_indices.at(id) + 1;
const unsigned end = m_geometry_indices.at(id + 1);
std::vector<EdgeWeight> result_weights;
result_weights.resize(end - begin);
std::copy(m_geometry_fwd_weight_list.begin() + begin,
m_geometry_fwd_weight_list.begin() + end,
result_weights.begin());
return result_weights;
}
virtual std::vector<EdgeWeight>
GetUncompressedReverseWeights(const EdgeID id) const override final
{
/*
* EdgeWeights for geometries are stored in one place for
* both forward and reverse segments along the same bi-
* directional edge. The m_geometry_indices stores
* refences to where to find the beginning of the bi-
* directional edge in the m_geometry_rev_weight_list vector. For
* reverse weights of bi-directional edges, edges 1 to
* n-1 of that edge need to be read in reverse.
*/
const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id + 1) - 1;
std::vector<EdgeWeight> result_weights;
result_weights.resize(end - begin);
std::copy(m_geometry_rev_weight_list.rbegin() + (m_geometry_rev_weight_list.size() - end),
m_geometry_rev_weight_list.rbegin() + (m_geometry_rev_weight_list.size() - begin),
result_weights.begin());
return result_weights;
}
// Returns the data source ids that were used to supply the edge
// weights.
virtual std::vector<uint8_t>
GetUncompressedForwardDatasources(const EdgeID id) const override final
{
/*
* Data sources for geometries are stored in one place for
* both forward and reverse segments along the same bi-
* directional edge. The m_geometry_indices stores
* refences to where to find the beginning of the bi-
* directional edge in the m_geometry_list vector. For
* forward datasources of bi-directional edges, edges 2 to
* n of that edge need to be read.
*/
const unsigned begin = m_geometry_indices.at(id) + 1;
const unsigned end = m_geometry_indices.at(id + 1);
std::vector<uint8_t> result_datasources;
result_datasources.resize(end - begin);
// If there was no datasource info, return an array of 0's.
if (m_datasource_list.empty())
{
for (unsigned i = 0; i < end - begin; ++i)
{
result_datasources.push_back(0);
}
}
else
{
std::copy(m_datasource_list.begin() + begin,
m_datasource_list.begin() + end,
result_datasources.begin());
}
return result_datasources;
}
// Returns the data source ids that were used to supply the edge
// weights.
virtual std::vector<uint8_t>
GetUncompressedReverseDatasources(const EdgeID id) const override final
{
/*
* Datasources for geometries are stored in one place for
* both forward and reverse segments along the same bi-
* directional edge. The m_geometry_indices stores
* refences to where to find the beginning of the bi-
* directional edge in the m_geometry_list vector. For
* reverse datasources of bi-directional edges, edges 1 to
* n-1 of that edge need to be read in reverse.
*/
const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id + 1) - 1;
std::vector<uint8_t> result_datasources;
result_datasources.resize(end - begin);
// If there was no datasource info, return an array of 0's.
if (m_datasource_list.empty())
{
for (unsigned i = 0; i < end - begin; ++i)
{
result_datasources.push_back(0);
}
}
else
{
std::copy(m_datasource_list.rbegin() + (m_datasource_list.size() - end),
m_datasource_list.rbegin() + (m_datasource_list.size() - begin),
result_datasources.begin());
}
return result_datasources;
}
virtual std::string GetDatasourceName(const uint8_t datasource_name_id) const override final
{
BOOST_ASSERT(m_datasource_names.size() >= 1);
BOOST_ASSERT(m_datasource_names.size() > datasource_name_id);
return m_datasource_names[datasource_name_id];
}
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetContinueStraightDefault() const override final
{
return m_profile_properties.continue_straight_at_waypoint;
}
double GetMapMatchingMaxSpeed() const override final
{
return m_profile_properties.max_speed_for_map_matching;
}
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::TurnBearing PreTurnBearing(const EdgeID eid) const override final
{
return m_pre_turn_bearing.at(eid);
}
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
{
return m_post_turn_bearing.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return m_lane_data_id[id] != INVALID_LANE_DATAID;
}
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tuple_id_pairs[m_lane_data_id[id]];
}
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const override final
{
if (lane_description_id == INVALID_LANE_DESCRIPTIONID)
return {};
else
return extractor::guidance::TurnLaneDescription(
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id],
m_lane_description_masks.begin() +
m_lane_description_offsets[lane_description_id + 1]);
}
};
}
}
}
#endif // INTERNAL_DATAFACADE_HPP
@@ -0,0 +1,52 @@
#ifndef PROCESS_MEMORY_DATAFACADE_HPP
#define PROCESS_MEMORY_DATAFACADE_HPP
// implements all data storage when shared memory is _NOT_ used
#include "storage/storage.hpp"
#include "engine/datafacade/contiguous_internalmem_datafacade_base.hpp"
namespace osrm
{
namespace engine
{
namespace datafacade
{
/**
* This datafacade uses a process-local memory block to load
* data into. The structure and layout is the same as when using
* shared memory, so this class, and the SharedMemoryDataFacade both
* share a common base.
* This class holds a unique_ptr to the memory block, so it
* is auto-freed upon destruction.
*/
class ProcessMemoryDataFacade final : public ContiguousInternalMemoryDataFacadeBase
{
private:
std::unique_ptr<char[]> internal_memory;
std::unique_ptr<storage::DataLayout> internal_layout;
public:
explicit ProcessMemoryDataFacade(const storage::StorageConfig &config)
{
storage::Storage storage(config);
// Calculate the layout/size of the memory block
internal_layout = std::make_unique<storage::DataLayout>();
storage.PopulateLayout(*internal_layout);
// Allocate the memory block, then load data from files into it
internal_memory = std::make_unique<char[]>(internal_layout->GetSizeOfLayout());
storage.PopulateData(*internal_layout, internal_memory.get());
// Adjust all the private m_* members to point to the right places
InitializeInternalPointers(*internal_layout.get(), internal_memory.get());
}
};
}
}
}
#endif // PROCESS_MEMORY_DATAFACADE_HPP
@@ -0,0 +1,101 @@
#ifndef SHARED_MEMORY_DATAFACADE_HPP
#define SHARED_MEMORY_DATAFACADE_HPP
// implements all data storage when shared memory _IS_ used
#include "storage/shared_barriers.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include "engine/datafacade/contiguous_internalmem_datafacade_base.hpp"
namespace osrm
{
namespace engine
{
namespace datafacade
{
/**
* This datafacade uses an IPC shared memory block as the data location.
* Many SharedMemoryDataFacade objects can be created that point to the same shared
* memory block.
*/
class SharedMemoryDataFacade : public ContiguousInternalMemoryDataFacadeBase
{
protected:
std::unique_ptr<storage::SharedMemory> m_layout_memory;
std::unique_ptr<storage::SharedMemory> m_large_memory;
std::shared_ptr<storage::SharedBarriers> shared_barriers;
storage::SharedDataType layout_region;
storage::SharedDataType data_region;
unsigned shared_timestamp;
SharedMemoryDataFacade() {}
public:
// this function handle the deallocation of the shared memory it we can prove it will not be
// used anymore. We crash hard here if something goes wrong (noexcept).
virtual ~SharedMemoryDataFacade() noexcept
{
// Now check if this is still the newest dataset
boost::interprocess::sharable_lock<boost::interprocess::named_upgradable_mutex>
current_regions_lock(shared_barriers->current_regions_mutex,
boost::interprocess::defer_lock);
boost::interprocess::scoped_lock<boost::interprocess::named_sharable_mutex> exclusive_lock(
data_region == storage::DATA_1 ? shared_barriers->regions_1_mutex
: shared_barriers->regions_2_mutex,
boost::interprocess::defer_lock);
// if this returns false this is still in use
if (current_regions_lock.try_lock() && exclusive_lock.try_lock())
{
if (storage::SharedMemory::RegionExists(data_region))
{
BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region));
auto shared_regions = storage::makeSharedMemory(storage::CURRENT_REGIONS);
const auto current_timestamp =
static_cast<const storage::SharedDataTimestamp *>(shared_regions->Ptr());
// check if the memory region referenced by this facade needs cleanup
if (current_timestamp->data == data_region)
{
BOOST_ASSERT(current_timestamp->layout == layout_region);
util::Log(logDEBUG) << "Retaining data with shared timestamp "
<< shared_timestamp;
}
else
{
storage::SharedMemory::Remove(data_region);
storage::SharedMemory::Remove(layout_region);
}
}
}
}
SharedMemoryDataFacade(const std::shared_ptr<storage::SharedBarriers> &shared_barriers_,
storage::SharedDataType layout_region_,
storage::SharedDataType data_region_,
unsigned shared_timestamp_)
: shared_barriers(shared_barriers_), layout_region(layout_region_),
data_region(data_region_), shared_timestamp(shared_timestamp_)
{
util::Log(logDEBUG) << "Loading new data with shared timestamp " << shared_timestamp;
BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region));
m_layout_memory = storage::makeSharedMemory(layout_region);
BOOST_ASSERT(storage::SharedMemory::RegionExists(data_region));
m_large_memory = storage::makeSharedMemory(data_region);
InitializeInternalPointers(*reinterpret_cast<storage::DataLayout *>(m_layout_memory->Ptr()),
reinterpret_cast<char *>(m_large_memory->Ptr()));
}
};
}
}
}
#endif // SHARED_MEMORY_DATAFACADE_HPP
+2
View File
@@ -18,6 +18,8 @@
#include "engine/plugins/trip.hpp"
#include "engine/plugins/viaroute.hpp"
#include "engine/status.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/json_container.hpp"
#include <memory>
+2 -1
View File
@@ -400,7 +400,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
}
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
{
reverse_weight *= 1.0 - ratio;
const EdgeWeight difference = reverse_weight * ratio;
reverse_weight -= difference;
}
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
@@ -6,7 +6,6 @@
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/toolkit.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
#include "util/coordinate.hpp"
+8 -12
View File
@@ -8,14 +8,12 @@
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/step_maneuver.hpp"
#include "engine/guidance/toolkit.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
@@ -156,7 +154,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
intersection.entry.push_back(entry_class.allowsEntry(idx));
}
std::int16_t bearing_in_driving_direction =
util::bearing::reverseBearing(std::round(bearings.first));
util::reverseBearing(std::round(bearings.first));
maneuver = {intersection.location,
bearing_in_driving_direction,
bearings.second,
@@ -216,14 +214,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
BOOST_ASSERT(segment_index == number_of_segments - 1);
bearings = detail::getArriveBearings(leg_geometry);
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
std::vector<bool>({true}),
0,
Intersection::NO_INDEX,
util::guidance::LaneTuple(),
{}};
intersection = {target_node.location,
std::vector<short>({static_cast<short>(util::reverseBearing(bearings.first))}),
std::vector<bool>({true}),
0,
Intersection::NO_INDEX,
util::guidance::LaneTuple(),
{}};
// This step has length zero, the only reason we need it is the target location
maneuver = {intersection.location,
@@ -233,7 +230,6 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
WaypointType::Arrive,
0};
BOOST_ASSERT(!leg_geometry.locations.empty());
steps.push_back(RouteStep{target_node.name_id,
facade.GetNameForID(target_node.name_id),
@@ -0,0 +1,53 @@
#ifndef OSRM_ENGINE_GUIDANCE_POSTPROCESSING_TOOLKIT_HPP_
#define OSRM_ENGINE_GUIDANCE_POSTPROCESSING_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include <iterator>
#include <utility>
namespace osrm
{
namespace engine
{
namespace guidance
{
// Runs fn on RouteStep sub-ranges determined to be roundabouts.
// The function fn is getting called with a roundabout range as in: [enter, .., leave].
//
// The following situations are taken care for (i.e. we discard them):
// - partial roundabout: enter without exit or exit without enter
// - data issues: no roundabout, exit before enter
template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, Iter last, Fn fn)
{
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
break;
(void)fn(std::make_pair(enter, leave));
// Skip to first step after the currently handled enter / leave pair
first = std::next(leave);
}
return fn;
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_POSTPROCESSING_TOOLKIT_HPP_ */
+29 -1
View File
@@ -11,10 +11,11 @@
#include "util/guidance/turn_lanes.hpp"
#include <cstddef>
#include <string>
#include <vector>
#include <boost/range/iterator_range.hpp>
namespace osrm
{
namespace engine
@@ -71,6 +72,33 @@ struct RouteStep
std::size_t geometry_begin;
std::size_t geometry_end;
std::vector<Intersection> intersections;
LaneID numLanesToTheRight() const
{
return intersections.front().lanes.first_lane_from_the_right;
}
LaneID numLanesToTheLeft() const
{
LaneID const total = intersections.front().lane_description.size();
return total - (intersections.front().lanes.lanes_in_turn +
intersections.front().lanes.first_lane_from_the_right);
}
auto lanesToTheLeft() const
{
const auto &description = intersections.front().lane_description;
LaneID num_lanes_left = numLanesToTheLeft();
return boost::make_iterator_range(description.begin(),
description.begin() + num_lanes_left);
}
auto lanesToTheRight() const
{
const auto &description = intersections.front().lane_description;
LaneID num_lanes_right = numLanesToTheRight();
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
};
inline RouteStep getInvalidRouteStep()
-108
View File
@@ -1,108 +0,0 @@
#ifndef OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#define OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/bearing.hpp"
#include "util/guidance/toolkit.hpp"
#include <algorithm>
#include <iterator>
#include <utility>
namespace osrm
{
namespace engine
{
namespace guidance
{
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
using util::guidance::staysOnRoundabout;
// Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::NoTurn ||
instruction.type == extractor::guidance::TurnType::Suppressed ||
instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(const double bearing)
{
if (bearing < 135)
{
return extractor::guidance::DirectionModifier::Right;
}
if (bearing <= 225)
{
return extractor::guidance::DirectionModifier::Straight;
}
return extractor::guidance::DirectionModifier::Left;
}
// Runs fn on RouteStep sub-ranges determined to be roundabouts.
// The function fn is getting called with a roundabout range as in: [enter, .., leave].
//
// The following situations are taken care for (i.e. we discard them):
// - partial roundabout: enter without exit or exit without enter
// - data issues: no roundabout, exit before enter
template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, Iter last, Fn fn)
{
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
break;
(void)fn(std::make_pair(enter, leave));
// Skip to first step after the currently handled enter / leave pair
first = std::next(leave);
}
return fn;
}
LaneID inline numLanesToTheRight(const engine::guidance::RouteStep &step)
{
return step.intersections.front().lanes.first_lane_from_the_right;
}
LaneID inline numLanesToTheLeft(const engine::guidance::RouteStep &step)
{
LaneID const total = step.intersections.front().lane_description.size();
return total - (step.intersections.front().lanes.lanes_in_turn +
step.intersections.front().lanes.first_lane_from_the_right);
}
auto inline lanesToTheLeft(const engine::guidance::RouteStep &step)
{
const auto &description = step.intersections.front().lane_description;
LaneID num_lanes_left = numLanesToTheLeft(step);
return boost::make_iterator_range(description.begin(), description.begin() + num_lanes_left);
}
auto inline lanesToTheRight(const engine::guidance::RouteStep &step)
{
const auto &description = step.intersections.front().lane_description;
LaneID num_lanes_right = numLanesToTheRight(step);
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_ */
+11 -8
View File
@@ -3,8 +3,8 @@
#include "util/coordinate.hpp"
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/assert.hpp>
#include <string>
#include <vector>
@@ -13,17 +13,17 @@ namespace osrm
namespace engine
{
namespace detail
{
constexpr double POLYLINE_DECODING_PRECISION = 1e5;
constexpr double POLYLINE_TO_COORDINATE = COORDINATE_PRECISION / POLYLINE_DECODING_PRECISION;
{
constexpr double POLYLINE_DECODING_PRECISION = 1e5;
constexpr double POLYLINE_TO_COORDINATE = COORDINATE_PRECISION / POLYLINE_DECODING_PRECISION;
std::string encode(std::vector<int> &numbers);
}
std::string encode(std::vector<int> &numbers);
}
using CoordVectorForwardIter = std::vector<util::Coordinate>::const_iterator;
// Encodes geometry into polyline format.
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
template<unsigned POLYLINE_PRECISION=100000>
template <unsigned POLYLINE_PRECISION = 100000>
std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter end)
{
double coordinate_to_polyline = POLYLINE_PRECISION / COORDINATE_PRECISION;
@@ -39,7 +39,10 @@ std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter
int current_lat = 0;
int current_lon = 0;
std::for_each(
begin, end, [&delta_numbers, &current_lat, &current_lon, coordinate_to_polyline](const util::Coordinate loc) {
begin,
end,
[&delta_numbers, &current_lat, &current_lon, coordinate_to_polyline](
const util::Coordinate loc) {
const int lat_diff =
std::round(static_cast<int>(loc.lat) * coordinate_to_polyline) - current_lat;
const int lon_diff =
@@ -235,10 +235,10 @@ class AlternativeRouting final
}
}
// util::SimpleLogger().Write(logDEBUG) << "fwd_search_space size: " <<
// util::Log(logDEBUG) << "fwd_search_space size: " <<
// forward_search_space.size() << ", marked " << approximated_forward_sharing.size() << "
// nodes";
// util::SimpleLogger().Write(logDEBUG) << "rev_search_space size: " <<
// util::Log(logDEBUG) << "rev_search_space size: " <<
// reverse_search_space.size() << ", marked " << approximated_reverse_sharing.size() << "
// nodes";
@@ -601,7 +601,7 @@ class AlternativeRouting final
// //compute forward sharing
// while( (packed_alternate_path[aindex] == packed_shortest_path[aindex]) &&
// (packed_alternate_path[aindex+1] == packed_shortest_path[aindex+1]) ) {
// // util::SimpleLogger().Write() << "retrieving edge (" <<
// // util::Log() << "retrieving edge (" <<
// packed_alternate_path[aindex] << "," << packed_alternate_path[aindex+1] << ")";
// EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex],
// packed_alternate_path[aindex+1]);
@@ -640,7 +640,7 @@ class AlternativeRouting final
const NodeID node = forward_heap.DeleteMin();
const int weight = forward_heap.GetKey(node);
// const NodeID parentnode = forward_heap.GetData(node).parent;
// util::SimpleLogger().Write() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled
// util::Log() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled
// edge ("
// << parentnode << "," << node << "), dist: " << weight;
@@ -665,11 +665,11 @@ class AlternativeRouting final
{
*middle_node = node;
*upper_bound_to_shortest_path_weight = new_weight;
// util::SimpleLogger().Write() << "accepted middle_node " << *middle_node
// util::Log() << "accepted middle_node " << *middle_node
// << " at
// weight " << new_weight;
// } else {
// util::SimpleLogger().Write() << "discarded middle_node " << *middle_node
// util::Log() << "discarded middle_node " << *middle_node
// << "
// at weight " << new_weight;
}
+1 -1
View File
@@ -2,7 +2,7 @@
#define TRIP_BRUTE_FORCE_HPP
#include "util/dist_table_wrapper.hpp"
#include "util/simple_logger.hpp"
#include "util/log.hpp"
#include "util/typedefs.hpp"
#include "osrm/json_container.hpp"
@@ -3,7 +3,6 @@
#include "util/dist_table_wrapper.hpp"
#include "util/typedefs.hpp"
#include "util/typedefs.hpp"
#include "osrm/json_container.hpp"
#include <boost/assert.hpp>
@@ -2,7 +2,7 @@
#define TRIP_NEAREST_NEIGHBOUR_HPP
#include "util/dist_table_wrapper.hpp"
#include "util/simple_logger.hpp"
#include "util/log.hpp"
#include "util/typedefs.hpp"
#include "osrm/json_container.hpp"
+7 -13
View File
@@ -3,6 +3,7 @@
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include <tuple>
namespace osrm
{
@@ -60,19 +61,12 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
inline bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
{
if (source == other.source)
{
if (target == other.target)
{
if (weight == other.weight)
{
return forward && backward && ((!other.forward) || (!other.backward));
}
return weight < other.weight;
}
return target < other.target;
}
return source < other.source;
const auto unidirectional = (!forward || !backward);
const auto other_is_unidirectional = (!other.forward || !other.backward);
// if all items are the same, we want to keep bidirectional edges. due to the `<` operator,
// preferring 0 (false) over 1 (true), we need to compare the inverse of `bidirectional`
return std::tie(source, target, weight, unidirectional) <
std::tie(other.source, other.target, other.weight, other_is_unidirectional);
}
} // ns extractor
} // ns osrm
@@ -29,7 +29,6 @@
#include <memory>
#include <queue>
#include <string>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -32,6 +32,7 @@ class ExtractionContainers
#else
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
void FlushVectors();
void PrepareNodes();
void PrepareRestrictions();
void PrepareEdges(ScriptingEnvironment &scripting_environment);
@@ -12,7 +12,7 @@
#include <limits>
#include <string>
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/parsing_toolkit.hpp"
namespace osrm
{
@@ -109,13 +109,13 @@ inline unsigned parseDuration(const std::string &s)
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
return extractor::guidance::trimLaneString(std::move(lane_string), count_left, count_right);
return guidance::trimLaneString(std::move(lane_string), count_left, count_right);
}
inline std::string applyAccessTokens(const std::string &lane_string,
const std::string &access_tokens)
{
return extractor::guidance::applyAccessTokens(lane_string, access_tokens);
return guidance::applyAccessTokens(lane_string, access_tokens);
}
// Takes a string representing a list separated by delim and canonicalizes containing spaces.
+36 -2
View File
@@ -13,6 +13,20 @@ namespace osrm
{
namespace extractor
{
namespace detail
{
inline void maybeSetString(std::string &str, const char *value)
{
if (value == nullptr)
{
str.clear();
}
else
{
str = std::string(value);
}
}
}
/**
* This struct is the direct result of the call to ```way_function```
@@ -30,8 +44,8 @@ struct ExtractionWay
backward_speed = -1;
duration = -1;
roundabout = false;
circular = false;
is_startpoint = true;
is_access_restricted = false;
name.clear();
ref.clear();
pronunciation.clear();
@@ -50,6 +64,26 @@ struct ExtractionWay
void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
TravelMode get_backward_mode() const { return backward_travel_mode; }
// wrappers to allow assigning nil (nullptr) to string values
void SetName(const char *value) { detail::maybeSetString(name, value); }
const char *GetName() const { return name.c_str(); }
void SetRef(const char *value) { detail::maybeSetString(ref, value); }
const char *GetRef() const { return ref.c_str(); }
void SetDestinations(const char *value) { detail::maybeSetString(destinations, value); }
const char *GetDestinations() const { return destinations.c_str(); }
void SetPronunciation(const char *value) { detail::maybeSetString(pronunciation, value); }
const char *GetPronunciation() const { return pronunciation.c_str(); }
void SetTurnLanesForward(const char *value)
{
detail::maybeSetString(turn_lanes_forward, value);
}
const char *GetTurnLanesForward() const { return turn_lanes_forward.c_str(); }
void SetTurnLanesBackward(const char *value)
{
detail::maybeSetString(turn_lanes_backward, value);
}
const char *GetTurnLanesBackward() const { return turn_lanes_backward.c_str(); }
double forward_speed;
double backward_speed;
double duration;
@@ -60,7 +94,7 @@ struct ExtractionWay
std::string turn_lanes_forward;
std::string turn_lanes_backward;
bool roundabout;
bool is_access_restricted;
bool circular;
bool is_startpoint;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
+2 -1
View File
@@ -11,7 +11,8 @@
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include <boost/optional.hpp>
namespace osrm
{
@@ -1,13 +1,14 @@
#ifndef OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
#define OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
#include <utility>
#include <vector>
#include "extractor/query_node.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "util/attributes.hpp"
#include "util/coordinate.hpp"
#include "util/node_based_graph.hpp"
namespace osrm
@@ -27,24 +28,52 @@ class CoordinateExtractor
/* Find a interpolated coordinate a long the compressed geometries. The desired coordinate
* should be in a certain distance. This method is dedicated to find representative coordinates
* at turns.
* Note: The segment between intersection and turn coordinate can be zero, if the OSM modelling
* is unfortunate. See https://github.com/Project-OSRM/osrm-backend/issues/3470
*/
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCoordinateAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node,
const std::uint8_t number_of_in_lanes) const;
// instead of finding only a single coordinate, we can also list all coordinates along a road.
std::vector<util::Coordinate> GetCoordinatesAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
// Given a set of precomputed coordinates, select the representative coordinate along the road
// that best describes the turn
OSRM_ATTR_WARN_UNUSED
util::Coordinate
ExtractRepresentativeCoordinate(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node,
const std::uint8_t intersection_lanes,
std::vector<util::Coordinate> coordinates) const;
// instead of finding only a single coordinate, we can also list all coordinates along a
// road.
OSRM_ATTR_WARN_UNUSED std::vector<util::Coordinate>
GetCoordinatesAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
// wrapper in case of normal forward edges (traversed_in_reverse = false, to_node =
// node_based_graph.GetTarget(turn_edge)
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
const EdgeID turn_edge) const;
// a less precise way to compute coordinates along a route. Due to the heavy interaction of
// graph traversal and turn instructions, we often don't care for high precision. We only want
// to check for available connections in order, or find (with room for error) the straightmost
// turn. This function will offer a bit more error potential but allow for much higher
// performance
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
* of them, though.
*
@@ -61,14 +90,25 @@ class CoordinateExtractor
* For calculating the turn angle for the intersection at `a`, we do not care about the turn
* between `v` and `b`. This calculation trims the coordinates to the ones immediately at the
* intersection.
*
* The optional length cache needs to store the accumulated distance up to the respective
* coordinate index [0,d(0,1),...]
*/
std::vector<util::Coordinate> TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates,
const double desired_length) const;
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate>
TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates,
const double desired_length,
const std::vector<double> &length_cache = {}) const;
OSRM_ATTR_WARN_UNUSED
std::vector<double> PrepareLengthCache(const std::vector<util::Coordinate> &coordinates,
const double limit) const;
/* when looking at a set of coordinates, this function allows trimming the vector to a smaller,
* only containing coordinates up to a given distance along the path. The last coordinate might
* be interpolated
*/
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate>
TrimCoordinatesByLengthFront(std::vector<util::Coordinate> coordinates,
const double desired_length) const;
@@ -94,6 +134,7 @@ class CoordinateExtractor
*
* for fixpoint `b`, vector_base `d` and vector_head `e`
*/
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
const util::Coordinate vector_base,
const util::Coordinate vector_head) const;
@@ -106,6 +147,7 @@ class CoordinateExtractor
* Into:
* x -- x -- x -- x -- x - x
*/
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate>
SampleCoordinates(const std::vector<util::Coordinate> &coordinates,
const double length,
@@ -199,6 +241,14 @@ class CoordinateExtractor
const double segment_length,
const std::vector<double> &segment_distances,
const std::uint8_t considered_lanes) const;
// find the coordinate at a specific location in the vector
util::Coordinate ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates,
const std::vector<double> &length_cache) const;
util::Coordinate
ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates) const;
};
} // namespace guidance
+160 -37
View File
@@ -1,14 +1,23 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_HPP_
#include <algorithm>
#include <functional>
#include <limits>
#include <string>
#include <type_traits>
#include <vector>
#include "extractor/guidance/turn_instruction.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/bearing.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" // EdgeID
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
@@ -16,22 +25,50 @@ namespace extractor
namespace guidance
{
// Every Turn Operation describes a way of switching onto a segment, indicated by an EdgeID. The
// associated turn is described by an angle and an instruction that is used to announce it.
// The Turn Operation indicates what is exposed to the outside of the turn analysis.
struct TurnOperation
// the shape of an intersection only knows about edge IDs and bearings
struct IntersectionShapeData
{
EdgeID eid;
double angle;
double bearing;
TurnInstruction instruction;
LaneDataID lane_data_id;
double segment_length;
};
inline auto makeCompareShapeDataByBearing(const double base_bearing)
{
return [base_bearing](const auto &lhs, const auto &rhs) {
return util::angleBetweenBearings(base_bearing, lhs.bearing) <
util::angleBetweenBearings(base_bearing, rhs.bearing);
};
}
inline auto makeCompareAngularDeviation(const double angle)
{
return [angle](const auto &lhs, const auto &rhs) {
return util::angularDeviation(lhs.angle, angle) < util::angularDeviation(rhs.angle, angle);
};
}
// When viewing an intersection from an incoming edge, we can transform a shape into a view which
// gives additional information on angles and whether a turn is allowed
struct IntersectionViewData : IntersectionShapeData
{
IntersectionViewData(const IntersectionShapeData &shape,
const bool entry_allowed,
const double angle)
: IntersectionShapeData(shape), entry_allowed(entry_allowed), angle(angle)
{
}
bool entry_allowed;
double angle;
bool CompareByAngle(const IntersectionViewData &other) const;
};
// A Connected Road is the internal representation of a potential turn. Internally, we require
// full list of all connected roads to determine the outcome.
// The reasoning behind is that even invalid turns can influence the perceived angles, or even
// instructions themselves. An pososible example can be described like this:
// instructions themselves. An possible example can be described like this:
//
// aaa(2)aa
// a - bbbbb
@@ -39,8 +76,7 @@ struct TurnOperation
//
// will not be perceived as a turn from (1) -> b, and as a U-turn from (1) -> (2).
// In addition, they can influence whether a turn is obvious or not. b->(2) would also be no
// turn-operation,
// but rather a name change.
// turn-operation, but rather a name change.
//
// If this were a normal intersection with
//
@@ -49,14 +85,17 @@ struct TurnOperation
// aaaaaaaa
//
// We would perceive a->c as a sharp turn, a->b as a slight turn, and b->c as a slight turn.
struct ConnectedRoad final : public TurnOperation
struct ConnectedRoad final : IntersectionViewData
{
using Base = TurnOperation;
ConnectedRoad(const IntersectionViewData &view,
const TurnInstruction instruction,
const LaneDataID lane_data_id)
: IntersectionViewData(view), instruction(instruction), lane_data_id(lane_data_id)
{
}
ConnectedRoad(const TurnOperation turn, const bool entry_allowed = false);
// a turn may be relevant to good instructions, even if we cannot enter the road
bool entry_allowed;
TurnInstruction instruction;
LaneDataID lane_data_id;
// used to sort the set of connected roads (we require sorting throughout turn handling)
bool compareByAngle(const ConnectedRoad &other) const;
@@ -71,32 +110,116 @@ struct ConnectedRoad final : public TurnOperation
// small helper function to print the content of a connected road
std::string toString(const ConnectedRoad &road);
struct Intersection final : public std::vector<ConnectedRoad>
// Intersections are sorted roads: [0] being the UTurn road, then from sharp right to sharp left.
using IntersectionShape = std::vector<IntersectionShapeData>;
// Common operations shared among IntersectionView and Intersections.
// Inherit to enable those operations on your compatible type. CRTP pattern.
template <typename Self> struct EnableIntersectionOps
{
using Base = std::vector<ConnectedRoad>;
// Find the turn whose angle offers the least angular deviation to the specified angle
// For turn angles [0, 90, 260] and a query of 180 we return the 260 degree turn.
auto findClosestTurn(double angle) const
{
auto comp = makeCompareAngularDeviation(angle);
return std::min_element(self()->begin(), self()->end(), comp);
}
/*
* find the turn whose angle offers the least angularDeviation to the specified angle
* E.g. for turn angles [0,90,260] and a query of 180 we return the 260 degree turn (difference
* 80 over the difference of 90 to the 90 degree turn)
*/
Base::iterator findClosestTurn(double angle);
Base::const_iterator findClosestTurn(double angle) const;
// Check validity of the intersection object. We assume a few basic properties every set of
// connected roads should follow throughout guidance pre-processing. This utility function
// allows checking intersections for validity
auto valid() const
{
if (self()->empty())
return false;
/*
* Check validity of the intersection object. We assume a few basic properties every set of
* connected roads should follow throughout guidance pre-processing. This utility function
* allows checking intersections for validity
*/
bool valid() const;
auto comp = [](const auto &lhs, const auto &rhs) { return lhs.CompareByAngle(rhs); };
// given all possible turns, which is the highest connected number of lanes per turn. This value
// is used, for example, during generation of intersections.
std::uint8_t getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &) const;
const auto ordered = std::is_sorted(self()->begin(), self()->end(), comp);
if (!ordered)
return false;
const auto uturn = self()->operator[](0).angle < std::numeric_limits<double>::epsilon();
if (!uturn)
return false;
return true;
}
// Given all possible turns which is the highest connected number of lanes per turn.
// This value is used for example during generation of intersections.
auto getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &graph) const
{
const std::function<std::uint8_t(const ConnectedRoad &)> to_lane_count =
[&](const ConnectedRoad &road) {
return graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
};
std::uint8_t max_lanes = 0;
const auto extract_maximal_value = [&max_lanes](std::uint8_t value) {
max_lanes = std::max(max_lanes, value);
return false;
};
const auto view = *self() | boost::adaptors::transformed(to_lane_count);
boost::range::find_if(view, extract_maximal_value);
return max_lanes;
}
// Returns the UTurn road we took to arrive at this intersection.
const auto &getUTurnRoad() const { return self()->operator[](0); }
// Returns the right-most road at this intersection.
const auto &getRightmostRoad() const
{
return self()->size() > 1 ? self()->operator[](1) : self()->getUTurnRoad();
}
// Returns the left-most road at this intersection.
const auto &getLeftmostRoad() const
{
return self()->size() > 1 ? self()->back() : self()->getUTurnRoad();
}
// Can this be skipped over?
auto isTrafficSignalOrBarrier() const { return self()->size() == 2; }
// Checks if there is at least one road available (except UTurn road) on which to continue.
auto isDeadEnd() const
{
auto pred = [](const auto &road) { return road.entry_allowed; };
return !std::any_of(self()->begin() + 1, self()->end(), pred);
}
// Returns the number of roads we can enter at this intersection, respectively.
auto countEnterable() const
{
auto pred = [](const auto &road) { return road.entry_allowed; };
return std::count_if(self()->begin(), self()->end(), pred);
}
// Returns the number of roads we can not enter at this intersection, respectively.
auto countNonEnterable() const { return self()->size() - self()->countEnterable(); }
private:
auto self() { return static_cast<Self *>(this); }
auto self() const { return static_cast<const Self *>(this); }
};
Intersection::const_iterator findClosestTurn(const Intersection &intersection, const double angle);
Intersection::iterator findClosestTurn(Intersection &intersection, const double angle);
struct IntersectionView final : std::vector<IntersectionViewData>, //
EnableIntersectionOps<IntersectionView> //
{
using Base = std::vector<IntersectionViewData>;
};
struct Intersection final : std::vector<ConnectedRoad>, //
EnableIntersectionOps<Intersection> //
{
using Base = std::vector<ConnectedRoad>;
};
} // namespace guidance
} // namespace extractor
@@ -6,15 +6,16 @@
#include "extractor/guidance/intersection.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "extractor/suffix_table.hpp"
#include "util/attributes.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <unordered_set>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
namespace osrm
{
namespace extractor
@@ -25,7 +26,6 @@ namespace guidance
// from it. For this all turn possibilities are analysed.
// We consider turn restrictions to indicate possible turns. U-turns are generated based on profile
// decisions.
class IntersectionGenerator
{
public:
@@ -33,80 +33,89 @@ class IntersectionGenerator
const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes,
const std::vector<QueryNode> &node_info_list,
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
const CompressedEdgeContainer &compressed_edge_container);
Intersection operator()(const NodeID nid, const EdgeID via_eid) const;
// For a source node `a` and a via edge `ab` creates an intersection at target `b`.
//
// a . . . b . .
// .
// .
//
IntersectionView operator()(const NodeID nid, const EdgeID via_eid) const;
/*
* Compute the shape of an intersection, returning a set of connected roads, without any further
* concern for which of the entries are actually allowed.
* The shape also only comes with turn bearings, not with turn angles. All turn angles will be
* set to zero
*/
OSRM_ATTR_WARN_UNUSED
IntersectionShape
ComputeIntersectionShape(const NodeID center_node,
const boost::optional<NodeID> sorting_base = boost::none,
bool use_low_precision_angles = false) const;
// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
// intermediate intersection, if there is a traffic light in between. If we want to look farther
// down a road, finding the next actual decision requires the look at multiple intersections.
// Here we follow the road until we either reach a dead end or find the next intersection with
// more than a single next road.
Intersection GetActualNextIntersection(const NodeID starting_node,
const EdgeID via_edge,
NodeID *resulting_from_node,
EdgeID *resulting_via_edge) const;
// more than a single next road. This function skips over degree two nodes to find coorect input
// for GetConnectedRoads.
OSRM_ATTR_WARN_UNUSED
std::pair<NodeID, EdgeID> SkipDegreeTwoNodes(const NodeID starting_node,
const EdgeID via_edge) const;
// Allow access to the coordinate extractor for all owners
const CoordinateExtractor &GetCoordinateExtractor() const;
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
// the
// node reached
// from `from_node` via `via_eid`
// The resulting candidates have to be analysed for their actual instructions later on.
// the node reached from `from_node` via `via_eid`. The resulting candidates have to be analysed
// for their actual instructions later on.
// The switch for `use_low_precision_angles` enables a faster mode that will procude less
// accurate coordinates. It should be good enough to check order of turns, find striaghtmost
// turns. Even good enough to do some simple angle verifications. It is mostly available to
// allow for faster graph traversal in the extraction phase.
OSRM_ATTR_WARN_UNUSED
Intersection GetConnectedRoads(const NodeID from_node, const EdgeID via_eid) const;
IntersectionView GetConnectedRoads(const NodeID from_node,
const EdgeID via_eid,
const bool use_low_precision_angles = false) const;
/*
* To be used in the road network, we need to check for valid/restricted turns. These two
* functions transform a basic intersection / a normalised intersection into the
* correct view when entering via a given edge.
*/
OSRM_ATTR_WARN_UNUSED
IntersectionView
TransformIntersectionShapeIntoView(const NodeID previous_node,
const EdgeID entering_via_edge,
const IntersectionShape &intersection) const;
// version for normalised intersection
OSRM_ATTR_WARN_UNUSED
IntersectionView TransformIntersectionShapeIntoView(
const NodeID previous_node,
const EdgeID entering_via_edge,
const IntersectionShape &normalised_intersection,
const IntersectionShape &intersection,
const std::vector<std::pair<EdgeID, EdgeID>> &merging_map) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes;
const std::vector<QueryNode> &node_info_list;
// own state, used to find the correct coordinates along a road
const CoordinateExtractor coordinate_extractor;
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
// check if two indices in an intersection can be seen as a single road in the perceived
// intersection representation. See below for an example. Utility function for
// MergeSegregatedRoads
bool CanMerge(const NodeID intersection_node,
const Intersection &intersection,
std::size_t first_index,
std::size_t second_index) const;
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
// one.
// This function combines roads the following way:
//
// * *
// * is converted to *
// v ^ +
// v ^ +
//
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
// 160
OSRM_ATTR_WARN_UNUSED
Intersection MergeSegregatedRoads(const NodeID intersection_node,
Intersection intersection) const;
// The counterpiece to mergeSegregatedRoads. While we can adjust roads that split up at the
// intersection itself, it can also happen that intersections are connected to joining roads.
//
// * *
// * is converted to *
// v a --- a ---
// v ^ +
// v ^ +
// b
//
// for the local view of b at a.
OSRM_ATTR_WARN_UNUSED
Intersection AdjustForJoiningRoads(const NodeID node_at_intersection,
Intersection intersection) const;
// check turn restrictions to find a node that is the only allowed target when coming from a
// node to an intersection
// d
// |
// a - b - c and `only_straight_on ab | bc would return `c` for `a,b`
boost::optional<NodeID> GetOnlyAllowedTurnIfExistent(const NodeID coming_from_node,
const NodeID node_at_intersection) const;
};
} // namespace guidance
@@ -3,15 +3,22 @@
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/node_based_graph_walker.hpp"
#include "extractor/query_node.hpp"
#include "extractor/suffix_table.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/name_announcements.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include <algorithm>
#include <cstddef>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
namespace osrm
{
namespace extractor
@@ -48,9 +55,7 @@ class IntersectionHandler
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
const IntersectionGenerator &intersection_generator;
// counts the number on allowed entry roads
std::size_t countValid(const Intersection &intersection) const;
const NodeBasedGraphWalker graph_walker; // for skipping traffic signal, distances etc.
// Decide on a basic turn types
TurnType::Enum findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const;
@@ -59,7 +64,8 @@ class IntersectionHandler
// determining whether there is a road that can be seen as obvious turn in the presence of many
// other possible turns. The function will consider road categories and other inputs like the
// turn angles.
std::size_t findObviousTurn(const EdgeID via_edge, const Intersection &intersection) const;
template <typename IntersectionType> // works with Intersection and IntersectionView
std::size_t findObviousTurn(const EdgeID via_edge, const IntersectionType &intersection) const;
// Obvious turns can still take multiple forms. This function looks at the turn onto a road
// candidate when coming from a via_edge and determines the best instruction to emit.
@@ -83,9 +89,458 @@ class IntersectionHandler
const std::size_t begin,
const std::size_t end) const;
// Checks the intersection for a through street connected to `intersection[index]`
bool isThroughStreet(const std::size_t index, const Intersection &intersection) const;
// See `getNextIntersection`
struct IntersectionViewAndNode final
{
IntersectionView intersection; // < actual intersection
NodeID node; // < node at this intersection
};
// Skips over artificial intersections i.e. traffic lights, barriers etc.
// Returns the next non-artificial intersection and its node in the node based
// graph if an intersection could be found or none otherwise.
//
// a ... tl ... b .. c
// .
// .
// d
//
// ^ at
// ^ via
//
// For this scenario returns intersection at `b` and `b`.
boost::optional<IntersectionHandler::IntersectionViewAndNode>
getNextIntersection(const NodeID at, const EdgeID via) const;
};
// Impl.
template <typename IntersectionType> // works with Intersection and IntersectionView
std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const IntersectionType &intersection) const
{
using Road = typename IntersectionType::value_type;
using EdgeData = osrm::util::NodeBasedDynamicGraph::EdgeData;
using osrm::util::angularDeviation;
// no obvious road
if (intersection.size() == 1)
return 0;
// a single non u-turn is obvious
if (intersection.size() == 2)
return 1;
const EdgeData &in_way_data = node_based_graph.GetEdgeData(via_edge);
// the strategy for picking the most obvious turn involves deciding between
// an overall best candidate and a best candidate that shares the same name
// as the in road, i.e. a continue road
std::size_t best_option = 0;
double best_option_deviation = 180;
std::size_t best_continue = 0;
double best_continue_deviation = 180;
/* helper functions */
const auto IsContinueRoad = [&](const EdgeData &way_data) {
return !util::guidance::requiresNameAnnounced(
in_way_data.name_id, way_data.name_id, name_table, street_name_suffix_table);
};
auto sameOrHigherPriority = [&in_way_data](const auto &way_data) {
return way_data.road_classification.GetPriority() <=
in_way_data.road_classification.GetPriority();
};
auto IsLowPriority = [](const auto &way_data) {
return way_data.road_classification.IsLowPriorityRoadClass();
};
// These two Compare functions are used for sifting out best option and continue
// candidates by evaluating all the ways in an intersection by what they share
// with the in way. Ideal candidates are of similar road class with the in way
// and are require relatively straight turns.
const auto RoadCompare = [&](const auto &lhs, const auto &rhs) {
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
const auto lhs_deviation = angularDeviation(lhs.angle, STRAIGHT_ANGLE);
const auto rhs_deviation = angularDeviation(rhs.angle, STRAIGHT_ANGLE);
const bool rhs_same_classification =
rhs_data.road_classification == in_way_data.road_classification;
const bool lhs_same_classification =
lhs_data.road_classification == in_way_data.road_classification;
const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_data);
const bool rhs_low_priority = IsLowPriority(rhs_data);
const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_data);
const bool lhs_low_priority = IsLowPriority(lhs_data);
auto left_tie = std::tie(lhs.entry_allowed,
lhs_same_or_higher_priority,
rhs_low_priority,
rhs_deviation,
lhs_same_classification);
auto right_tie = std::tie(rhs.entry_allowed,
rhs_same_or_higher_priority,
lhs_low_priority,
lhs_deviation,
rhs_same_classification);
return left_tie > right_tie;
};
const auto RoadCompareSameName = [&](const auto &lhs, const auto &rhs) {
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
const auto lhs_continues = IsContinueRoad(lhs_data);
const auto rhs_continues = IsContinueRoad(rhs_data);
const auto left_tie = std::tie(lhs.entry_allowed, lhs_continues);
const auto right_tie = std::tie(rhs.entry_allowed, rhs_continues);
return left_tie > right_tie || (left_tie == right_tie && RoadCompare(lhs, rhs));
};
auto best_option_it = std::min_element(begin(intersection), end(intersection), RoadCompare);
// min element should only return end() when vector is empty
BOOST_ASSERT(best_option_it != end(intersection));
best_option = std::distance(begin(intersection), best_option_it);
best_option_deviation = angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE);
const auto &best_option_data = node_based_graph.GetEdgeData(intersection[best_option].eid);
// Unless the in way is also low priority, it is generally undesirable to
// indicate that a low priority road is obvious
if (IsLowPriority(best_option_data) &&
best_option_data.road_classification != in_way_data.road_classification)
{
best_option = 0;
best_option_deviation = 180;
}
// double check if the way with the lowest deviation from straight is still be better choice
const auto straightest = intersection.findClosestTurn(STRAIGHT_ANGLE);
if (straightest != best_option_it)
{
const EdgeData &straightest_data = node_based_graph.GetEdgeData(straightest->eid);
double straightest_data_deviation = angularDeviation(straightest->angle, STRAIGHT_ANGLE);
const auto deviation_diff =
std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE;
const auto not_ramp_class = !straightest_data.road_classification.IsRampClass();
const auto not_link_class = !straightest_data.road_classification.IsLinkClass();
if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class &&
not_link_class && !IsContinueRoad(best_option_data))
{
best_option = std::distance(begin(intersection), straightest);
best_option_deviation =
angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE);
}
}
// No non-low priority roads? Declare no obvious turn
if (best_option == 0)
return 0;
auto best_continue_it =
std::min_element(begin(intersection), end(intersection), RoadCompareSameName);
const auto best_continue_data = node_based_graph.GetEdgeData(best_continue_it->eid);
if (IsContinueRoad(best_continue_data) ||
(in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID))
{
best_continue = std::distance(begin(intersection), best_continue_it);
best_continue_deviation =
angularDeviation(intersection[best_continue].angle, STRAIGHT_ANGLE);
}
// if the best angle is going straight but the road is turning, declare no obvious turn
if (0 != best_continue && best_option != best_continue &&
best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification ==
best_option_data.road_classification)
{
return 0;
}
// get a count of number of ways from that intersection that qualify to have
// continue instruction because they share a name with the approaching way
const std::int64_t continue_count =
count_if(++begin(intersection), end(intersection), [&](const auto &way) {
return IsContinueRoad(node_based_graph.GetEdgeData(way.eid));
});
const std::int64_t continue_count_valid =
count_if(++begin(intersection), end(intersection), [&](const auto &way) {
return IsContinueRoad(node_based_graph.GetEdgeData(way.eid)) && way.entry_allowed;
});
// checks if continue candidates are sharp turns
const bool all_continues_are_narrow = [&]() {
return std::count_if(begin(intersection), end(intersection), [&](const Road &road) {
const EdgeData &road_data = node_based_graph.GetEdgeData(road.eid);
const double &road_angle = angularDeviation(road.angle, STRAIGHT_ANGLE);
return IsContinueRoad(road_data) && (road_angle < NARROW_TURN_ANGLE);
}) == continue_count;
}();
// return true if the best_option candidate is more promising than the best_continue candidate
// otherwise return false, the best_continue candidate is more promising
const auto best_over_best_continue = [&]() {
// no continue road exists
if (best_continue == 0)
return true;
// we have multiple continues and not all are narrow. This suggests that
// the continue candidates are ambiguous
if (!all_continues_are_narrow && (continue_count >= 2 && intersection.size() >= 4))
return true;
// if the best continue is not narrow and we also have at least 2 possible choices, the
// intersection size does not matter anymore
if (continue_count_valid >= 2 && best_continue_deviation >= 2 * NARROW_TURN_ANGLE)
return true;
// continue data now most certainly exists
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
// best_continue is obvious by road class
if (obviousByRoadClass(in_way_data.road_classification,
continue_data.road_classification,
best_option_data.road_classification))
return false;
// best_option is obvious by road class
if (obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
continue_data.road_classification))
return true;
// the best_option deviation is very straight and not a ramp
if (best_option_deviation < best_continue_deviation &&
best_option_deviation < FUZZY_ANGLE_DIFFERENCE &&
!best_option_data.road_classification.IsRampClass())
return true;
// the continue road is of a lower priority, while the road continues on the same priority
// with a better angle
if (best_option_deviation < best_continue_deviation &&
in_way_data.road_classification == best_option_data.road_classification &&
continue_data.road_classification.GetPriority() >
best_option_data.road_classification.GetPriority())
return true;
return false;
}();
if (best_over_best_continue)
{
// Find left/right deviation
// skipping over service roads
const std::size_t left_index = [&]() {
const auto index_candidate = (best_option + 1) % intersection.size();
if (index_candidate == 0)
return index_candidate;
const auto &candidate_data =
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
if (obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
candidate_data.road_classification))
return (index_candidate + 1) % intersection.size();
else
return index_candidate;
}();
const auto right_index = [&]() {
BOOST_ASSERT(best_option > 0);
const auto index_candidate = best_option - 1;
if (index_candidate == 0)
return index_candidate;
const auto candidate_data =
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
if (obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
candidate_data.road_classification))
return index_candidate - 1;
else
return index_candidate;
}();
const double left_deviation =
angularDeviation(intersection[left_index].angle, STRAIGHT_ANGLE);
const double right_deviation =
angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
// return best_option candidate if it is nearly straight and distinct from the nearest other
// out
// way
if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best_option;
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid);
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid);
const bool obvious_to_left =
left_index == 0 || obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
left_data.road_classification);
const bool obvious_to_right =
right_index == 0 || obviousByRoadClass(in_way_data.road_classification,
best_option_data.road_classification,
right_data.road_classification);
// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
// consider the
// turn obvious
const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) {
return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
FUZZY_ANGLE_DIFFERENCE &&
(best_option_deviation > NARROW_TURN_ANGLE || intersection[index].entry_allowed);
};
// other narrow turns?
if (check_narrow(right_index) && !obvious_to_right)
return 0;
if (check_narrow(left_index) && !obvious_to_left)
return 0;
// checks if a given way in the intersection is distinct enough from the best_option
// candidate
const auto isDistinct = [&](const std::size_t index, const double deviation) {
/*
If the neighbor is not possible to enter, we allow for a lower
distinction rate. If the road category is smaller, its also adjusted. Only
roads of the same priority require the full distinction ratio.
*/
const auto &best_option_data =
node_based_graph.GetEdgeData(intersection[best_option].eid);
const auto adjusted_distinction_ratio = [&]() {
// not allowed competitors are easily distinct
if (!intersection[index].entry_allowed)
return 0.7 * DISTINCTION_RATIO;
// a bit less obvious are road classes
else if (in_way_data.road_classification == best_option_data.road_classification &&
best_option_data.road_classification.GetPriority() <
node_based_graph.GetEdgeData(intersection[index].eid)
.road_classification.GetPriority())
return 0.8 * DISTINCTION_RATIO;
// if road classes are the same, we use the full ratio
else
return DISTINCTION_RATIO;
}();
return index == 0 || deviation / best_option_deviation >= adjusted_distinction_ratio ||
(deviation <= NARROW_TURN_ANGLE && !intersection[index].entry_allowed);
};
const bool distinct_to_left = isDistinct(left_index, left_deviation);
const bool distinct_to_right = isDistinct(right_index, right_deviation);
// Well distinct turn that is nearly straight
if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
return best_option;
}
else
{
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
if (std::abs(best_continue_deviation) < 1)
return best_continue;
// check if any other similar best continues exist
std::size_t i, last = intersection.size();
for (i = 1; i < last; ++i)
{
if (i == best_continue || !intersection[i].entry_allowed)
continue;
const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].eid);
const bool is_obvious_by_road_class =
obviousByRoadClass(in_way_data.road_classification,
continue_data.road_classification,
turn_data.road_classification);
// if the main road is obvious by class, we ignore the current road as a potential
// prevention of obviousness
if (is_obvious_by_road_class)
continue;
// continuation could be grouped with a straight turn and the turning road is a ramp
if (turn_data.road_classification.IsRampClass() &&
best_continue_deviation < GROUP_ANGLE &&
!continue_data.road_classification.IsRampClass())
continue;
// perfectly straight turns prevent obviousness
const auto turn_deviation = angularDeviation(intersection[i].angle, STRAIGHT_ANGLE);
if (turn_deviation < FUZZY_ANGLE_DIFFERENCE)
return 0;
const auto deviation_ratio = turn_deviation / best_continue_deviation;
// in comparison to normal deviations, a continue road can offer a smaller distinction
// ratio. Other roads close to the turn angle are not as obvious, if one road continues.
if (deviation_ratio < DISTINCTION_RATIO / 1.5)
return 0;
/* in comparison to another continuing road, we need a better distinction. This prevents
situations where the turn is probably less obvious. An example are places that have a
road with the same name entering/exiting:
d
/
/
a -- b
\
\
c
*/
const auto same_name = !util::guidance::requiresNameAnnounced(
turn_data.name_id, continue_data.name_id, name_table, street_name_suffix_table);
if (same_name && deviation_ratio < 1.5 * DISTINCTION_RATIO)
return 0;
}
// Segregated intersections can result in us finding an obvious turn, even though its only
// obvious due to a very short segment in between. So if the segment coming in is very
// short, we check the previous intersection for other continues in the opposite bearing.
const auto node_at_intersection = node_based_graph.GetTarget(via_edge);
const double constexpr MAX_COLLAPSE_DISTANCE = 30;
const auto distance_at_u_turn = intersection[0].segment_length;
if (distance_at_u_turn < MAX_COLLAPSE_DISTANCE)
{
// this request here actually goes against the direction of the ingoing edgeid. This can
// even reverse the direction. Since we don't want to compute actual turns but simply
// try to find whether there is a turn going to the opposite direction of our obvious
// turn, this should be alright.
NodeID new_node;
const auto previous_intersection = [&]() {
EdgeID turn_edge;
std::tie(new_node, turn_edge) = intersection_generator.SkipDegreeTwoNodes(
node_at_intersection, intersection[0].eid);
return intersection_generator.GetConnectedRoads(new_node, turn_edge);
}();
if (new_node != node_at_intersection)
{
const auto continue_road = intersection[best_continue];
for (const auto &comparison_road : previous_intersection)
{
// since we look at the intersection in the wrong direction, a similar angle
// actually represents a near 180 degree different in bearings between the two
// roads. So if there is a road that is enterable in the opposite direction just
// prior, a turn is not obvious
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.eid);
if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
angularDeviation(comparison_road.angle, continue_road.angle) <
FUZZY_ANGLE_DIFFERENCE &&
!turn_data.reversed && continue_data.CanCombineWith(turn_data))
return 0;
}
}
}
return best_continue;
}
return 0;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -0,0 +1,118 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
#include "util/typedefs.hpp"
#include "util/attributes.hpp"
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/query_node.hpp"
#include "extractor/suffix_table.hpp"
#include "util/name_table.hpp"
#include <utility>
#include <vector>
namespace osrm
{
namespace extractor
{
namespace guidance
{
/*
* An intersection is a central part in computing guidance decisions. However the model in OSM and
* the view we want to use in guidance are not necessarily the same thing. We have to account for
* some models that are chosen explicitly in OSM and that don't actually describe how a human would
* experience an intersection.
*
* For example, if a small pedestrian island is located at a traffic light right in the middle of a
* road, OSM tends to model the road as two separate ways. A human would consider these two ways a
* single road, though. In this normalizer, we try to account for these subtle differences between
* OSM data and human perception to improve our decision base for guidance later on.
*/
class IntersectionNormalizer
{
public:
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<extractor::QueryNode> &node_coordinates,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
// The function takes an intersection an converts it to a `perceived` intersection which closer
// represents how a human might experience the intersection
OSRM_ATTR_WARN_UNUSED
std::pair<IntersectionShape, std::vector<std::pair<EdgeID, EdgeID>>>
operator()(const NodeID node_at_intersection, IntersectionShape intersection) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const std::vector<extractor::QueryNode> &node_coordinates;
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
const IntersectionGenerator &intersection_generator;
/* check if two indices in an intersection can be seen as a single road in the perceived
* intersection representation. See below for an example. Utility function for
* MergeSegregatedRoads. It also checks for neighboring merges.
* This is due possible segments where multiple roads could end up being merged into one.
* We only support merging two roads, not three or more, though.
* c c
* / /
* a - b -> a - b - (c,d) but not a - b d -> a,b,(cde)
* \ \
* d e
*/
bool CanMerge(const NodeID intersection_node,
const IntersectionShape &intersection,
std::size_t first_index,
std::size_t second_index) const;
// A tool called by CanMerge. It checks whether two indices can be merged, not concerned without
// remaining parts of the intersection.
bool InnerCanMerge(const NodeID intersection_node,
const IntersectionShape &intersection,
std::size_t first_index,
std::size_t second_index) const;
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
// one.
// This function combines roads the following way:
//
// * *
// * is converted to *
// v ^ +
// v ^ +
//
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
// 160
OSRM_ATTR_WARN_UNUSED
std::pair<IntersectionShape, std::vector<std::pair<EdgeID, EdgeID>>>
MergeSegregatedRoads(const NodeID intersection_node, IntersectionShape intersection) const;
// The counterpiece to mergeSegregatedRoads. While we can adjust roads that split up at the
// intersection itself, it can also happen that intersections are connected to joining roads.
//
// * *
// * is converted to *
// v a --- a ---
// v ^ +
// v ^ +
// b
//
// for the local view of b at a.
OSRM_ATTR_WARN_UNUSED
IntersectionShape AdjustBearingsForMergeAtDestination(const NodeID node_at_intersection,
IntersectionShape intersection) const;
};
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /* OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_ */
@@ -1,22 +0,0 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_SCENARIO_THREE_WAY_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_SCENARIO_THREE_WAY_HPP_
#include "extractor/guidance/intersection.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
// Ending in a T-Intersection
bool isEndOfRoad(const ConnectedRoad &uturn,
const ConnectedRoad &possible_right_turn,
const ConnectedRoad &possible_left_turn);
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /*OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_SCENARIO_THREE_WAY_HPP_*/
@@ -3,9 +3,8 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
@@ -21,9 +20,6 @@ namespace extractor
namespace guidance
{
// forward declaration to allow interaction between the intersection generator and the graph hopper
class IntersectionGenerator;
/*
* The graph hopper is a utility that lets you find certain intersections with a node based graph,
* accumulating information along the way
@@ -46,7 +42,7 @@ class NodeBasedGraphWalker
boost::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
EdgeID following_edge_id,
accumulator_type &accumulator,
const selector_type &selector);
const selector_type &selector) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
@@ -90,7 +86,8 @@ struct LengthLimitedCoordinateAccumulator
};
/*
* The SelectRoadByNameOnlyChoiceAndStraightness tries to follow a given name along a route. We offer methods to skip
* The SelectRoadByNameOnlyChoiceAndStraightness tries to follow a given name along a route. We
* offer methods to skip
* over bridges/similar situations if desired, following narrow turns
* This struct offers an example implementation of a possible road selector for traversing the
* node-based graph using the NodeBasedGraphWalker
@@ -118,14 +115,13 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
// find the next intersection given a hop limit
struct IntersectionFinderAccumulator
{
IntersectionFinderAccumulator(const std::uint8_t hop_limit, const IntersectionGenerator &intersection_generator);
IntersectionFinderAccumulator(const std::uint8_t hop_limit,
const IntersectionGenerator &intersection_generator);
// true if the path has traversed enough distance
bool terminate();
// update the accumulator
void update(const NodeID from_node,
const EdgeID via_edge,
const NodeID to_node);
void update(const NodeID from_node, const EdgeID via_edge, const NodeID to_node);
std::uint8_t hops;
const std::uint8_t hop_limit;
@@ -136,17 +132,15 @@ struct IntersectionFinderAccumulator
// the result we are looking for
NodeID nid;
EdgeID via_edge_id;
Intersection intersection;
IntersectionView intersection;
};
template <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>>
NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
EdgeID current_edge_id,
accumulator_type &accumulator,
const selector_type &selector)
const selector_type &selector) const
{
/*
* since graph hopping is used in many ways, we don't generate an adjusted intersection
@@ -197,6 +191,60 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
return {};
}
struct SkipTrafficSignalBarrierRoadSelector
{
boost::optional<EdgeID> operator()(const NodeID,
const EdgeID,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &) const
{
if (intersection.isTrafficSignalOrBarrier())
{
return boost::make_optional(intersection[1].eid);
}
else
{
return boost::none;
}
}
};
struct DistanceToNextIntersectionAccumulator
{
DistanceToNextIntersectionAccumulator(
const extractor::guidance::CoordinateExtractor &extractor_,
const util::NodeBasedDynamicGraph &graph_,
const double threshold)
: extractor{extractor_}, graph{graph_}, threshold{threshold}
{
}
bool terminate()
{
if (distance > threshold)
{
too_far_away = true;
return true;
}
return false;
}
void update(const NodeID start, const EdgeID onto, const NodeID)
{
using namespace util::coordinate_calculation;
const auto coords = extractor.GetForwardCoordinatesAlongRoad(start, onto);
distance += getLength(coords, &haversineDistance);
}
const extractor::guidance::CoordinateExtractor &extractor;
const util::NodeBasedDynamicGraph &graph;
const double threshold;
bool too_far_away = false;
double distance = 0.;
};
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -0,0 +1,112 @@
#ifndef OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
#define OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
#include <cstdint>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include "util/attributes.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
// Public service vehicle lanes and similar can introduce additional lanes into the lane string that
// are not specifically marked for left/right turns. This function can be used from the profile to
// trim the lane string appropriately
//
// left|throught|
// in combination with lanes:psv:forward=1
// will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through
OSRM_ATTR_WARN_UNUSED
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
if (count_left)
{
bool sane = count_left < static_cast<std::int32_t>(lane_string.size());
for (std::int32_t i = 0; i < count_left; ++i)
// this is adjusted for our fake pipe. The moment cucumber can handle multiple escaped
// pipes, the '&' part can be removed
if (lane_string[i] != '|')
{
sane = false;
break;
}
if (sane)
{
lane_string.erase(lane_string.begin(), lane_string.begin() + count_left);
}
}
if (count_right)
{
bool sane = count_right < static_cast<std::int32_t>(lane_string.size());
for (auto itr = lane_string.rbegin();
itr != lane_string.rend() && itr != lane_string.rbegin() + count_right;
++itr)
{
if (*itr != '|')
{
sane = false;
break;
}
}
if (sane)
lane_string.resize(lane_string.size() - count_right);
}
return lane_string;
}
// https://github.com/Project-OSRM/osrm-backend/issues/2638
// It can happen that some lanes are not drivable by car. Here we handle this tagging scheme
// (vehicle:lanes) to filter out not-allowed roads
// lanes=3
// turn:lanes=left|through|through|right
// vehicle:lanes=yes|yes|no|yes
// bicycle:lanes=yes|no|designated|yes
OSRM_ATTR_WARN_UNUSED
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
{
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(lane_string, sep);
tokenizer access(access_tokens, sep);
// strings don't match, don't do anything
if (std::distance(std::begin(tokens), std::end(tokens)) !=
std::distance(std::begin(access), std::end(access)))
return lane_string;
std::string result_string = "";
const static std::string yes = "yes";
for (auto token_itr = std::begin(tokens), access_itr = std::begin(access);
token_itr != std::end(tokens);
++token_itr, ++access_itr)
{
if (*access_itr == yes)
{
// we have to add this in front, because the next token could be invalid. Doing this on
// non-empty strings makes sure that the token string will be valid in the end
if (!result_string.empty())
result_string += '|';
result_string += *token_itr;
}
}
return result_string;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
@@ -4,9 +4,8 @@
#include <cmath>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <osmium/osm.hpp>
#include "extractor/guidance/constants.hpp"
namespace osrm
{
@@ -65,7 +64,7 @@ class RoadClassification
public:
// default construction
RoadClassification()
: motorway_class(0), link_class(0), may_be_ignored(1),
: motorway_class(0), link_class(0), may_be_ignored(0),
road_priority_class(RoadPriorityClass::CONNECTIVITY), number_of_lanes(0)
{
}
@@ -126,6 +125,22 @@ inline bool canBeSeenAsFork(const RoadClassification first, const RoadClassifica
return std::abs(static_cast<int>(first.GetPriority()) -
static_cast<int>(second.GetPriority())) <= 1;
}
inline bool obviousByRoadClass(const RoadClassification in_classification,
const RoadClassification obvious_candidate,
const RoadClassification compare_candidate)
{
// lower numbers are of higher priority
const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
compare_candidate.GetPriority();
const bool continues_on_same_class = in_classification == obvious_candidate;
return (has_high_priority && continues_on_same_class) ||
(!obvious_candidate.IsLowPriorityRoadClass() &&
!in_classification.IsLowPriorityRoadClass() &&
compare_candidate.IsLowPriorityRoadClass());
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -15,7 +15,6 @@
#include "util/typedefs.hpp"
#include <unordered_set>
#include <utility>
#include <vector>
namespace osrm
@@ -9,10 +9,10 @@
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include <cstddef>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
namespace osrm
{
namespace extractor
@@ -22,7 +22,7 @@ namespace guidance
// Intersection handlers deal with all issues related to intersections.
// They assign appropriate turn operations to the TurnOperations.
class SliproadHandler : public IntersectionHandler
class SliproadHandler final : public IntersectionHandler
{
public:
SliproadHandler(const IntersectionGenerator &intersection_generator,
@@ -42,6 +42,37 @@ class SliproadHandler : public IntersectionHandler
Intersection operator()(const NodeID nid,
const EdgeID via_eid,
Intersection intersection) const override final;
private:
boost::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection,
const NodeID at) const;
// Next intersection from `start` onto `onto` is too far away for a Siproad scenario
bool nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const;
// Through street: does a road continue with from's name at the intersection
bool isThroughStreet(const EdgeID from, const IntersectionView &intersection) const;
// Does the road from `current` to `next` continue
bool roadContinues(const EdgeID current, const EdgeID next) const;
// Is the area under the triangle a valid Sliproad triangle
bool isValidSliproadArea(const double max_area, const NodeID, const NodeID, const NodeID) const;
// Is the Sliproad a link the both roads it shortcuts must not be links
bool isValidSliproadLink(const IntersectionViewData &sliproad,
const IntersectionViewData &first,
const IntersectionViewData &second) const;
// Could a Sliproad reach this intersection?
static bool canBeTargetOfSliproad(const IntersectionView &intersection);
// Scales a threshold based on the underlying road classification.
// Example: a 100 m threshold for a highway if different on living streets.
// The return value is guaranteed to not be larger than `threshold`.
static double scaledThresholdByRoadClass(const double max_threshold,
const RoadClassification &classification);
};
} // namespace guidance
-240
View File
@@ -1,240 +0,0 @@
#ifndef OSRM_GUIDANCE_TOOLKIT_HPP_
#define OSRM_GUIDANCE_TOOLKIT_HPP_
#include "util/attributes.hpp"
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/road_classification.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/functional/hash.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/tokenizer.hpp>
namespace osrm
{
namespace extractor
{
namespace guidance
{
using util::guidance::LaneTupleIdPair;
using LaneDataIdMap = std::unordered_map<LaneTupleIdPair, LaneDataID, boost::hash<LaneTupleIdPair>>;
using util::guidance::angularDeviation;
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
// To simplify handling of Left/Right hand turns, we can mirror turns and write an intersection
// handler only for one side. The mirror function turns a left-hand turn in a equivalent right-hand
// turn and vice versa.
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace extractor::guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto *first = valid_types;
const auto *last = first + sizeof(valid_types) / sizeof(valid_types[0]);
return std::find(first, last, instruction.type) != last;
}
// Public service vehicle lanes and similar can introduce additional lanes into the lane string that
// are not specifically marked for left/right turns. This function can be used from the profile to
// trim the lane string appropriately
//
// left|throught|
// in combination with lanes:psv:forward=1
// will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through
OSRM_ATTR_WARN_UNUSED
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
if (count_left)
{
bool sane = count_left < static_cast<std::int32_t>(lane_string.size());
for (std::int32_t i = 0; i < count_left; ++i)
// this is adjusted for our fake pipe. The moment cucumber can handle multiple escaped
// pipes, the '&' part can be removed
if (lane_string[i] != '|')
{
sane = false;
break;
}
if (sane)
{
lane_string.erase(lane_string.begin(), lane_string.begin() + count_left);
}
}
if (count_right)
{
bool sane = count_right < static_cast<std::int32_t>(lane_string.size());
for (auto itr = lane_string.rbegin();
itr != lane_string.rend() && itr != lane_string.rbegin() + count_right;
++itr)
{
if (*itr != '|')
{
sane = false;
break;
}
}
if (sane)
lane_string.resize(lane_string.size() - count_right);
}
return lane_string;
}
// https://github.com/Project-OSRM/osrm-backend/issues/2638
// It can happen that some lanes are not drivable by car. Here we handle this tagging scheme
// (vehicle:lanes) to filter out not-allowed roads
// lanes=3
// turn:lanes=left|through|through|right
// vehicle:lanes=yes|yes|no|yes
// bicycle:lanes=yes|no|designated|yes
OSRM_ATTR_WARN_UNUSED
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
{
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(lane_string, sep);
tokenizer access(access_tokens, sep);
// strings don't match, don't do anything
if (std::distance(std::begin(tokens), std::end(tokens)) !=
std::distance(std::begin(access), std::end(access)))
return lane_string;
std::string result_string = "";
const static std::string yes = "yes";
for (auto token_itr = std::begin(tokens), access_itr = std::begin(access);
token_itr != std::end(tokens);
++token_itr, ++access_itr)
{
if (*access_itr == yes)
{
// we have to add this in front, because the next token could be invalid. Doing this on
// non-empty strings makes sure that the token string will be valid in the end
if (!result_string.empty())
result_string += '|';
result_string += *token_itr;
}
}
return result_string;
}
inline bool obviousByRoadClass(const RoadClassification in_classification,
const RoadClassification obvious_candidate,
const RoadClassification compare_candidate)
{
const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
compare_candidate.GetPriority();
const bool continues_on_same_class = in_classification == obvious_candidate;
return (has_high_priority && continues_on_same_class) ||
(!obvious_candidate.IsLowPriorityRoadClass() &&
!in_classification.IsLowPriorityRoadClass() &&
compare_candidate.IsLowPriorityRoadClass());
}
/* We use the sum of least squares to calculate a linear regression through our
* coordinates.
* This regression gives a good idea of how the road can be perceived and corrects for
* initial and final corrections
*/
inline std::pair<util::Coordinate, util::Coordinate>
leastSquareRegression(const std::vector<util::Coordinate> &coordinates)
{
BOOST_ASSERT(coordinates.size() >= 2);
double sum_lon = 0, sum_lat = 0, sum_lon_lat = 0, sum_lon_lon = 0;
double min_lon = static_cast<double>(toFloating(coordinates.front().lon));
double max_lon = static_cast<double>(toFloating(coordinates.front().lon));
for (const auto coord : coordinates)
{
min_lon = std::min(min_lon, static_cast<double>(toFloating(coord.lon)));
max_lon = std::max(max_lon, static_cast<double>(toFloating(coord.lon)));
sum_lon += static_cast<double>(toFloating(coord.lon));
sum_lon_lon +=
static_cast<double>(toFloating(coord.lon)) * static_cast<double>(toFloating(coord.lon));
sum_lat += static_cast<double>(toFloating(coord.lat));
sum_lon_lat +=
static_cast<double>(toFloating(coord.lon)) * static_cast<double>(toFloating(coord.lat));
}
const auto dividend = coordinates.size() * sum_lon_lat - sum_lon * sum_lat;
const auto divisor = coordinates.size() * sum_lon_lon - sum_lon * sum_lon;
if (std::abs(divisor) < std::numeric_limits<double>::epsilon())
return std::make_pair(coordinates.front(), coordinates.back());
// slope of the regression line
const auto slope = dividend / divisor;
const auto intercept = (sum_lat - slope * sum_lon) / coordinates.size();
const auto GetLatAtLon = [intercept,
slope](const util::FloatLongitude longitude) -> util::FloatLatitude {
return {intercept + slope * static_cast<double>((longitude))};
};
const util::Coordinate regression_first = {
toFixed(util::FloatLongitude{min_lon - 1}),
toFixed(util::FloatLatitude(GetLatAtLon(util::FloatLongitude{min_lon - 1})))};
const util::Coordinate regression_end = {
toFixed(util::FloatLongitude{max_lon + 1}),
toFixed(util::FloatLatitude(GetLatAtLon(util::FloatLongitude{max_lon + 1})))};
return {regression_first, regression_end};
}
inline std::uint8_t getLaneCountAtIntersection(const NodeID intersection_node,
const util::NodeBasedDynamicGraph &node_based_graph)
{
std::uint8_t lanes = 0;
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(intersection_node))
lanes = std::max(
lanes, node_based_graph.GetEdgeData(onto_edge).road_classification.GetNumberOfLanes());
return lanes;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_GUIDANCE_TOOLKIT_HPP_
+33 -9
View File
@@ -4,16 +4,17 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_normalizer.hpp"
#include "extractor/guidance/motorway_handler.hpp"
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/sliproad_handler.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_classification.hpp"
#include "extractor/guidance/turn_handler.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "extractor/suffix_table.hpp"
#include "util/attributes.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
@@ -21,6 +22,7 @@
#include <memory>
#include <string>
#include <tuple>
#include <unordered_set>
#include <utility>
#include <vector>
@@ -34,7 +36,6 @@ namespace guidance
class TurnAnalysis
{
public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
@@ -45,19 +46,42 @@ class TurnAnalysis
const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties);
// the entry into the turn analysis
Intersection getIntersection(const NodeID from_node, const EdgeID via_eid) const;
Intersection
assignTurnTypes(const NodeID from_node, const EdgeID via_eid, Intersection intersection) const;
/* Full Analysis Process for a single node/edge combination. Use with caution, as the process is
* relatively expensive */
OSRM_ATTR_WARN_UNUSED
Intersection operator()(const NodeID node_prior_to_intersection,
const EdgeID entering_via_edge) const;
std::vector<TurnOperation>
transformIntersectionIntoTurns(const Intersection &intersection) const;
/*
* Returns a normalized intersection without any assigned turn types.
* This intersection can be used as input for intersection classification, turn lane assignment
* and similar.
*/
struct ShapeResult
{
// the basic shape, containing all turns
IntersectionShape intersection_shape;
// normalised shape, merged some roads into others, adjusted bearings
// see intersection_normaliser for further explanations
IntersectionShape normalised_intersection_shape;
// map containing information about which road was merged into which
std::vector<std::pair<EdgeID, EdgeID>> merging_map;
};
OSRM_ATTR_WARN_UNUSED
ShapeResult ComputeIntersectionShapes(const NodeID node_at_center_of_intersection) const;
const IntersectionGenerator &getGenerator() const;
// Select turn types based on the intersection shape
OSRM_ATTR_WARN_UNUSED
Intersection AssignTurnTypes(const NodeID from_node,
const EdgeID via_eid,
const IntersectionView &intersection) const;
const IntersectionGenerator &GetIntersectionGenerator() const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const IntersectionGenerator intersection_generator;
const IntersectionNormalizer intersection_normalizer;
const RoundaboutHandler roundabout_handler;
const MotorwayHandler motorway_handler;
const TurnHandler turn_handler;
@@ -1,21 +1,12 @@
#ifndef OSRM_GUIDANCE_TURN_CLASSIFICATION_HPP_
#define OSRM_GUIDANCE_TURN_CLASSIFICATION_HPP_
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/query_node.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <cstddef>
#include <utility>
#include <vector>
namespace osrm
{
@@ -2,11 +2,9 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_DISCOVERY_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "util/typedefs.hpp"
#include <string>
namespace osrm
{
namespace extractor
@@ -22,13 +20,13 @@ namespace lanes
bool findPreviousIntersection(
const NodeID node,
const EdgeID via_edge,
const Intersection intersection,
const TurnAnalysis &turn_analysis, // to generate other intersections
const Intersection &intersection,
const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, // query edge data
// output parameters, will be in an arbitrary state on failure
NodeID &result_node,
EdgeID &result_via_edge,
Intersection &result_intersection);
IntersectionView &result_intersection);
} // namespace lanes
} // namespace guidance
+158 -2
View File
@@ -1,11 +1,11 @@
#ifndef OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#include <algorithm>
#include <cstdint>
#include <boost/assert.hpp>
#include "extractor/guidance/roundabout_type.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp"
namespace osrm
@@ -150,6 +150,162 @@ inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs)
return lhs.type == rhs.type && lhs.direction_modifier == rhs.direction_modifier;
}
// check if a instruction is associated in any form with a roundabout
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace extractor::guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto *first = valid_types;
const auto *last = first + sizeof(valid_types) / sizeof(valid_types[0]);
return std::find(first, last, instruction.type) != last;
}
inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruction)
{
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::EnterAndExitRoundaboutIntersection);
}
inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruction)
{
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::EnterAndExitRoundaboutIntersection);
}
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
// Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::NoTurn ||
instruction.type == extractor::guidance::TurnType::Suppressed ||
instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline bool hasRampType(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::OffRamp ||
instruction.type == extractor::guidance::TurnType::OnRamp;
}
inline extractor::guidance::DirectionModifier::Enum getTurnDirection(const double angle)
{
// An angle of zero is a u-turn
// 180 goes perfectly straight
// 0-180 are right turns
// 180-360 are left turns
if (angle > 0 && angle < 60)
return extractor::guidance::DirectionModifier::SharpRight;
if (angle >= 60 && angle < 140)
return extractor::guidance::DirectionModifier::Right;
if (angle >= 140 && angle < 160)
return extractor::guidance::DirectionModifier::SlightRight;
if (angle >= 160 && angle <= 200)
return extractor::guidance::DirectionModifier::Straight;
if (angle > 200 && angle <= 220)
return extractor::guidance::DirectionModifier::SlightLeft;
if (angle > 220 && angle <= 300)
return extractor::guidance::DirectionModifier::Left;
if (angle > 300 && angle < 360)
return extractor::guidance::DirectionModifier::SharpLeft;
return extractor::guidance::DirectionModifier::UTurn;
}
// swaps left <-> right modifier types
OSRM_ATTR_WARN_UNUSED
inline extractor::guidance::DirectionModifier::Enum
mirrorDirectionModifier(const extractor::guidance::DirectionModifier::Enum modifier)
{
const constexpr extractor::guidance::DirectionModifier::Enum results[] = {
extractor::guidance::DirectionModifier::UTurn,
extractor::guidance::DirectionModifier::SharpLeft,
extractor::guidance::DirectionModifier::Left,
extractor::guidance::DirectionModifier::SlightLeft,
extractor::guidance::DirectionModifier::Straight,
extractor::guidance::DirectionModifier::SlightRight,
extractor::guidance::DirectionModifier::Right,
extractor::guidance::DirectionModifier::SharpRight};
return results[modifier];
}
inline bool hasLeftModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpLeft ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Left ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightLeft;
}
inline bool hasRightModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpRight ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Right ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightRight;
}
inline bool isLeftTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case TurnType::Merge:
return hasRightModifier(instruction);
default:
return hasLeftModifier(instruction);
}
}
inline bool isRightTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case TurnType::Merge:
return hasLeftModifier(instruction);
default:
return hasRightModifier(instruction);
}
}
inline DirectionModifier::Enum bearingToDirectionModifier(const double bearing)
{
if (bearing < 135)
{
return extractor::guidance::DirectionModifier::Right;
}
if (bearing <= 225)
{
return extractor::guidance::DirectionModifier::Straight;
}
return extractor::guidance::DirectionModifier::Left;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -4,7 +4,6 @@
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp"
#include <string>
#include <vector>
namespace osrm
@@ -2,7 +2,6 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
@@ -74,7 +73,7 @@ class TurnLaneHandler
std::vector<TurnLaneType::Mask> &turn_lane_masks,
LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis,
LaneDataIdMap &id_map);
util::guidance::LaneDataIdMap &id_map);
~TurnLaneHandler();
@@ -91,7 +90,7 @@ class TurnLaneHandler
std::vector<TurnLaneType::Mask> &turn_lane_masks;
LaneDescriptionMap &lane_description_map;
const TurnAnalysis &turn_analysis;
LaneDataIdMap &id_map;
util::guidance::LaneDataIdMap &id_map;
// Find out which scenario we have to handle
TurnLaneScenario deduceScenario(const NodeID at,
@@ -2,7 +2,6 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_MATCHER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
@@ -10,8 +9,6 @@
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include <unordered_map>
namespace osrm
{
namespace extractor
@@ -47,7 +44,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &lane_data_to_id);
util::guidance::LaneDataIdMap &lane_data_to_id);
} // namespace lanes
} // namespace guidance
@@ -8,11 +8,9 @@
#include <unordered_map>
#include <vector>
#include <boost/assert.hpp>
#include <boost/functional/hash.hpp>
#include "util/json_container.hpp"
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
namespace osrm
+17 -17
View File
@@ -43,11 +43,11 @@ struct InternalExtractorEdge
MIN_OSM_NODEID,
0,
0,
false,
false,
false,
false,
true,
false, // forward
false, // backward
false, // roundabout
false, // circular
true, // can be startpoint
TRAVEL_MODE_INACCESSIBLE,
false,
guidance::TurnLaneType::empty,
@@ -62,7 +62,7 @@ struct InternalExtractorEdge
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool circular,
bool startpoint,
TravelMode travel_mode,
bool is_split,
@@ -75,7 +75,7 @@ struct InternalExtractorEdge
forward,
backward,
roundabout,
access_restricted,
circular,
startpoint,
travel_mode,
is_split,
@@ -99,11 +99,11 @@ struct InternalExtractorEdge
MIN_OSM_NODEID,
0,
WeightData(),
false,
false,
false,
false,
true,
false, // forward
false, // backward
false, // roundabout
false, // circular
true, // can be startpoint
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID,
@@ -115,11 +115,11 @@ struct InternalExtractorEdge
MAX_OSM_NODEID,
SPECIAL_NODEID,
WeightData(),
false,
false,
false,
false,
true,
false, // forward
false, // backward
false, // roundabout
false, // circular
true, // can be startpoint
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID,
+11 -11
View File
@@ -22,7 +22,7 @@ struct NodeBasedEdge
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool circular,
bool startpoint,
TravelMode travel_mode,
bool is_split,
@@ -38,7 +38,7 @@ struct NodeBasedEdge
bool forward : 1;
bool backward : 1;
bool roundabout : 1;
bool access_restricted : 1;
bool circular : 1;
bool startpoint : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
@@ -55,7 +55,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool circular,
bool startpoint,
TravelMode travel_mode,
bool is_split,
@@ -70,8 +70,8 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
backward(false), roundabout(false), access_restricted(false), startpoint(true),
is_split(false), travel_mode(false), lane_description_id(INVALID_LANE_DESCRIPTIONID)
backward(false), roundabout(false), circular(false), startpoint(true), is_split(false),
travel_mode(false), lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@@ -82,16 +82,16 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool circular,
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification)
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
backward(backward), roundabout(roundabout), access_restricted(access_restricted),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
backward(backward), roundabout(roundabout), circular(circular), startpoint(startpoint),
is_split(is_split), travel_mode(travel_mode), lane_description_id(lane_description_id),
road_classification(std::move(road_classification))
{
}
@@ -119,7 +119,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
bool forward,
bool backward,
bool roundabout,
bool access_restricted,
bool circular,
bool startpoint,
TravelMode travel_mode,
bool is_split,
@@ -132,7 +132,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
forward,
backward,
roundabout,
access_restricted,
circular,
startpoint,
travel_mode,
is_split,
+9 -13
View File
@@ -10,6 +10,7 @@
#include <boost/filesystem/fstream.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <storage/io.hpp>
#include <iterator>
#include <unordered_map>
@@ -43,20 +44,14 @@ class RasterGrid
ydim = _ydim;
_data.reserve(ydim * xdim);
boost::filesystem::ifstream stream(filepath, std::ios::binary);
if (!stream)
{
throw util::exception("Unable to open raster file.");
}
storage::io::FileReader file_reader(filepath, storage::io::FileReader::HasNoFingerprint);
stream.seekg(0, std::ios_base::end);
std::string buffer;
buffer.resize(static_cast<std::size_t>(stream.tellg()));
stream.seekg(0, std::ios_base::beg);
buffer.resize(file_reader.Size());
BOOST_ASSERT(buffer.size() > 1);
stream.read(&buffer[0], static_cast<std::streamsize>(buffer.size()));
file_reader.ReadInto(&buffer[0], buffer.size());
boost::algorithm::trim(buffer);
@@ -71,13 +66,14 @@ class RasterGrid
}
catch (std::exception const &ex)
{
throw util::exception(
std::string("Failed to read from raster source with exception: ") + ex.what());
throw util::exception("Failed to read from raster source " + filepath.string() + ": " +
ex.what() + SOURCE_REF);
}
if (!r || itr != end)
{
throw util::exception("Failed to parse raster source correctly.");
throw util::exception("Failed to parse raster source: " + filepath.string() +
SOURCE_REF);
}
}
+4 -4
View File
@@ -8,7 +8,7 @@
#include "util/typedefs.hpp"
#include "util/integer_range.hpp"
#include "util/simple_logger.hpp"
#include "util/log.hpp"
#include "util/std_hash.hpp"
#include "util/timing_util.hpp"
@@ -146,8 +146,8 @@ template <typename GraphT> class TarjanSCC
if (size_of_current_component > 1000)
{
util::SimpleLogger().Write() << "large component [" << component_index
<< "]=" << size_of_current_component;
util::Log() << "large component [" << component_index
<< "]=" << size_of_current_component;
}
++component_index;
@@ -158,7 +158,7 @@ template <typename GraphT> class TarjanSCC
}
TIMER_STOP(SCC_RUN);
util::SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s";
util::Log() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s";
size_one_counter = std::count_if(component_size_vector.begin(),
component_size_vector.end(),
+3 -4
View File
@@ -6,7 +6,7 @@
#include "server/service_handler.hpp"
#include "util/integer_range.hpp"
#include "util/simple_logger.hpp"
#include "util/log.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
@@ -36,8 +36,7 @@ class Server
static std::shared_ptr<Server>
CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads)
{
util::SimpleLogger().Write() << "http 1.1 compression handled by zlib version "
<< zlibVersion();
util::Log() << "http 1.1 compression handled by zlib version " << zlibVersion();
const unsigned hardware_threads = std::max(1u, std::thread::hardware_concurrency());
const unsigned real_num_threads = std::min(hardware_threads, requested_num_threads);
return std::make_shared<Server>(ip_address, ip_port, real_num_threads);
@@ -62,7 +61,7 @@ class Server
acceptor.bind(endpoint);
acceptor.listen();
util::SimpleLogger().Write() << "Listening on: " << acceptor.local_endpoint();
util::Log() << "Listening on: " << acceptor.local_endpoint();
acceptor.async_accept(
new_connection->socket(),
+1 -1
View File
@@ -5,7 +5,7 @@
#include "osrm/osrm.hpp"
#include "util/coordinate.hpp"
#include <variant/variant.hpp>
#include <mapbox/variant.hpp>
#include <string>
#include <vector>
+211 -184
View File
@@ -1,17 +1,17 @@
#ifndef OSRM_STORAGE_IO_HPP_
#define OSRM_STORAGE_IO_HPP_
#include "contractor/query_edge.hpp"
#include "extractor/extractor.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/query_node.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/fingerprint.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include "util/log.hpp"
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/seek.hpp>
#include <cstring>
#include <tuple>
#include <type_traits>
namespace osrm
{
@@ -20,201 +20,228 @@ namespace storage
namespace io
{
// Reads the count of elements that is written in the file header and returns the number
inline std::uint64_t readElementCount(boost::filesystem::ifstream &input_stream)
class FileReader
{
std::uint64_t number_of_elements = 0;
input_stream.read((char *)&number_of_elements, sizeof(std::uint64_t));
return number_of_elements;
}
private:
const boost::filesystem::path filepath;
boost::filesystem::ifstream input_stream;
// To make function calls consistent, this function returns the fixed number of properties
inline std::size_t readPropertiesCount() { return 1; }
public:
class LineWrapper : public std::string
{
friend std::istream &operator>>(std::istream &is, LineWrapper &line)
{
return std::getline(is, line);
}
};
auto GetLineIteratorBegin() { return std::istream_iterator<LineWrapper>(input_stream); }
auto GetLineIteratorEnd() { return std::istream_iterator<LineWrapper>(); }
// Returns the number of bytes in a file
inline std::size_t readNumberOfBytes(boost::filesystem::ifstream &input_stream)
{
input_stream.seekg(0, input_stream.end);
auto length = input_stream.tellg();
input_stream.seekg(0, input_stream.beg);
return length;
}
enum FingerprintFlag
{
VerifyFingerprint,
HasNoFingerprint
};
FileReader(const std::string &filename, const FingerprintFlag flag)
: FileReader(boost::filesystem::path(filename), flag)
{
}
#pragma pack(push, 1)
struct HSGRHeader
{
std::uint32_t checksum;
std::uint64_t number_of_nodes;
std::uint64_t number_of_edges;
FileReader(const boost::filesystem::path &filepath_, const FingerprintFlag flag)
: filepath(filepath_)
{
input_stream.open(filepath, std::ios::binary);
if (!input_stream)
throw util::exception("Error opening " + filepath.string());
if (flag == VerifyFingerprint && !ReadAndCheckFingerprint())
{
throw util::exception("Fingerprint mismatch in " + filepath_.string() + SOURCE_REF);
}
}
/* Read count objects of type T into pointer dest */
template <typename T> void ReadInto(T *dest, const std::size_t count)
{
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value,
"bytewise reading requires trivially copyable type");
#endif
if (count == 0)
return;
const auto &result = input_stream.read(reinterpret_cast<char *>(dest), count * sizeof(T));
if (!result)
{
if (result.eof())
{
throw util::exception("Error reading from " + filepath.string() +
": Unexpected end of file " + SOURCE_REF);
}
throw util::exception("Error reading from " + filepath.string() + " " + SOURCE_REF);
}
}
template <typename T> void ReadInto(std::vector<T> &target)
{
ReadInto(target.data(), target.size());
}
template <typename T> void ReadInto(T &target) { ReadInto(&target, 1); }
template <typename T> T ReadOne()
{
T tmp;
ReadInto(tmp);
return tmp;
}
template <typename T> void Skip(const std::size_t element_count)
{
boost::iostreams::seek(input_stream, element_count * sizeof(T), BOOST_IOS::cur);
}
/*******************************************/
std::uint32_t ReadElementCount32() { return ReadOne<std::uint32_t>(); }
std::uint64_t ReadElementCount64() { return ReadOne<std::uint64_t>(); }
template <typename T> void DeserializeVector(std::vector<T> &data)
{
const auto count = ReadElementCount64();
data.resize(count);
ReadInto(data.data(), count);
}
bool ReadAndCheckFingerprint()
{
auto fingerprint = ReadOne<util::FingerPrint>();
const auto valid = util::FingerPrint::GetValid();
// compare the compilation state stored in the fingerprint
return valid.IsMagicNumberOK(fingerprint) && valid.TestContractor(fingerprint) &&
valid.TestGraphUtil(fingerprint) && valid.TestRTree(fingerprint) &&
valid.TestQueryObjects(fingerprint);
}
std::size_t Size()
{
auto current_pos = input_stream.tellg();
input_stream.seekg(0, input_stream.end);
auto length = input_stream.tellg();
input_stream.seekg(current_pos, input_stream.beg);
return length;
}
std::vector<std::string> ReadLines()
{
std::vector<std::string> result;
std::string thisline;
try
{
while (std::getline(input_stream, thisline))
{
result.push_back(thisline);
}
}
catch (const std::ios_base::failure &e)
{
// EOF is OK here, everything else, re-throw
if (!input_stream.eof())
throw;
}
return result;
}
std::string ReadLine()
{
std::string thisline;
try
{
std::getline(input_stream, thisline);
}
catch (const std::ios_base::failure & /*e*/)
{
// EOF is OK here, everything else, re-throw
if (!input_stream.eof())
throw;
}
return thisline;
}
};
#pragma pack(pop)
static_assert(sizeof(HSGRHeader) == 20, "HSGRHeader is not packed");
// Reads the checksum, number of nodes and number of edges written in the header file of a `.hsgr`
// file and returns them in a HSGRHeader struct
inline HSGRHeader readHSGRHeader(boost::filesystem::ifstream &input_stream)
class FileWriter
{
const util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid();
util::FingerPrint fingerprint_loaded;
input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(util::FingerPrint));
if (!fingerprint_loaded.TestGraphUtil(fingerprint_valid))
private:
const boost::filesystem::path filepath;
boost::filesystem::ofstream output_stream;
public:
enum FingerprintFlag
{
GenerateFingerprint,
HasNoFingerprint
};
FileWriter(const std::string &filename, const FingerprintFlag flag)
: FileWriter(boost::filesystem::path(filename), flag)
{
util::SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
HSGRHeader header;
input_stream.read(reinterpret_cast<char *>(&header.checksum), sizeof(header.checksum));
input_stream.read(reinterpret_cast<char *>(&header.number_of_nodes),
sizeof(header.number_of_nodes));
input_stream.read(reinterpret_cast<char *>(&header.number_of_edges),
sizeof(header.number_of_edges));
BOOST_ASSERT_MSG(0 != header.number_of_nodes, "number of nodes is zero");
// number of edges can be zero, this is the case in a few test fixtures
return header;
}
// Reads the graph data of a `.hsgr` file into memory
// Needs to be called after readHSGRHeader() to get the correct offset in the stream
using NodeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::NodeArrayEntry;
using EdgeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::EdgeArrayEntry;
inline void readHSGR(boost::filesystem::ifstream &input_stream,
NodeT *node_buffer,
const std::uint64_t number_of_nodes,
EdgeT *edge_buffer,
const std::uint64_t number_of_edges)
{
BOOST_ASSERT(node_buffer);
BOOST_ASSERT(edge_buffer);
input_stream.read(reinterpret_cast<char *>(node_buffer), number_of_nodes * sizeof(NodeT));
input_stream.read(reinterpret_cast<char *>(edge_buffer), number_of_edges * sizeof(EdgeT));
}
// Loads properties from a `.properties` file into memory
inline void readProperties(boost::filesystem::ifstream &properties_stream,
extractor::ProfileProperties *properties,
const std::size_t properties_size)
{
BOOST_ASSERT(properties);
properties_stream.read(reinterpret_cast<char *>(properties), properties_size);
}
// Reads the timestamp in a `.timestamp` file
// Use readNumberOfBytes() beforehand to get the length of the file
inline void readTimestamp(boost::filesystem::ifstream &timestamp_input_stream,
char *timestamp,
const std::size_t timestamp_length)
{
BOOST_ASSERT(timestamp);
timestamp_input_stream.read(timestamp, timestamp_length * sizeof(char));
}
// Loads datasource_indexes from .datasource_indexes into memory
// Needs to be called after readElementCount() to get the correct offset in the stream
inline void readDatasourceIndexes(boost::filesystem::ifstream &datasource_indexes_input_stream,
uint8_t *datasource_buffer,
const std::uint64_t number_of_datasource_indexes)
{
BOOST_ASSERT(datasource_buffer);
datasource_indexes_input_stream.read(reinterpret_cast<char *>(datasource_buffer),
number_of_datasource_indexes * sizeof(std::uint8_t));
}
// Loads edge data from .edge files into memory which includes its
// geometry, name ID, turn instruction, lane data ID, travel mode, entry class ID
// Needs to be called after readElementCount() to get the correct offset in the stream
inline void readEdges(boost::filesystem::ifstream &edges_input_stream,
GeometryID *geometry_list,
NameID *name_id_list,
extractor::guidance::TurnInstruction *turn_instruction_list,
LaneDataID *lane_data_id_list,
extractor::TravelMode *travel_mode_list,
EntryClassID *entry_class_id_list,
util::guidance::TurnBearing *pre_turn_bearing_list,
util::guidance::TurnBearing *post_turn_bearing_list,
const std::uint64_t number_of_edges)
{
BOOST_ASSERT(geometry_list);
BOOST_ASSERT(name_id_list);
BOOST_ASSERT(turn_instruction_list);
BOOST_ASSERT(lane_data_id_list);
BOOST_ASSERT(travel_mode_list);
BOOST_ASSERT(entry_class_id_list);
extractor::OriginalEdgeData current_edge_data;
for (std::uint64_t i = 0; i < number_of_edges; ++i)
FileWriter(const boost::filesystem::path &filepath_, const FingerprintFlag flag)
: filepath(filepath_)
{
edges_input_stream.read((char *)&(current_edge_data), sizeof(extractor::OriginalEdgeData));
output_stream.open(filepath, std::ios::binary);
if (!output_stream)
throw util::exception("Error opening " + filepath.string());
geometry_list[i] = current_edge_data.via_geometry;
name_id_list[i] = current_edge_data.name_id;
turn_instruction_list[i] = current_edge_data.turn_instruction;
lane_data_id_list[i] = current_edge_data.lane_data_id;
travel_mode_list[i] = current_edge_data.travel_mode;
entry_class_id_list[i] = current_edge_data.entry_classid;
pre_turn_bearing_list[i] = current_edge_data.pre_turn_bearing;
post_turn_bearing_list[i] = current_edge_data.post_turn_bearing;
if (flag == GenerateFingerprint)
{
WriteFingerprint();
}
}
}
// Loads coordinates and OSM node IDs from .nodes files into memory
// Needs to be called after readElementCount() to get the correct offset in the stream
template <typename OSMNodeIDVectorT>
void readNodes(boost::filesystem::ifstream &nodes_input_stream,
util::Coordinate *coordinate_list,
OSMNodeIDVectorT &osmnodeid_list,
const std::uint64_t number_of_coordinates)
{
BOOST_ASSERT(coordinate_list);
extractor::QueryNode current_node;
for (std::uint64_t i = 0; i < number_of_coordinates; ++i)
/* Write count objects of type T from pointer src to output stream */
template <typename T> bool WriteFrom(T *src, const std::size_t count)
{
nodes_input_stream.read((char *)&current_node, sizeof(extractor::QueryNode));
coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
osmnodeid_list.push_back(current_node.node_id);
BOOST_ASSERT(coordinate_list[i].IsValid());
}
}
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value,
"bytewise writing requires trivially copyable type");
#endif
// Reads datasource names out of .datasource_names files and metadata such as
// the length and offset of each name
struct DatasourceNamesData
{
std::vector<char> names;
std::vector<std::size_t> offsets;
std::vector<std::size_t> lengths;
if (count == 0)
return true;
const auto &result = output_stream.write(reinterpret_cast<char *>(src), count * sizeof(T));
if (!result)
{
throw util::exception("Error writing to " + filepath.string());
}
return static_cast<bool>(output_stream);
}
template <typename T> bool WriteFrom(T &target) { return WriteFrom(&target, 1); }
template <typename T> bool WriteOne(T tmp) { return WriteFrom(tmp); }
bool WriteElementCount32(const std::uint32_t count) { return WriteOne<std::uint32_t>(count); }
bool WriteElementCount64(const std::uint64_t count) { return WriteOne<std::uint64_t>(count); }
template <typename T> bool SerializeVector(std::vector<T> &data)
{
const auto count = data.size();
WriteElementCount64(count);
return WriteFrom(data.data(), count);
}
bool WriteFingerprint()
{
const auto fingerprint = util::FingerPrint::GetValid();
return WriteOne(fingerprint);
}
};
inline DatasourceNamesData
readDatasourceNames(boost::filesystem::ifstream &datasource_names_input_stream)
{
DatasourceNamesData datasource_names_data;
std::string name;
while (std::getline(datasource_names_input_stream, name))
{
datasource_names_data.offsets.push_back(datasource_names_data.names.size());
datasource_names_data.lengths.push_back(name.size());
std::copy(name.c_str(),
name.c_str() + name.size(),
std::back_inserter(datasource_names_data.names));
}
return datasource_names_data;
}
// Loads ram indexes of R-Trees from `.ramIndex` files into memory
// Needs to be called after readElementCount() to get the correct offset in the stream
// template <bool UseSharedMemory>
// NB Cannot be written without templated type because of cyclic depencies between
// `static_rtree.hpp` and `io.hpp`
template <typename RTreeNodeT>
void readRamIndex(boost::filesystem::ifstream &ram_index_input_stream,
RTreeNodeT *rtree_buffer,
const std::uint64_t tree_size)
{
BOOST_ASSERT(rtree_buffer);
ram_index_input_stream.read(reinterpret_cast<char *>(rtree_buffer),
sizeof(RTreeNodeT) * tree_size);
}
}
}
}

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