Compare commits

...

154 Commits

Author SHA1 Message Date
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
309 changed files with 12442 additions and 7194 deletions
+7
View File
@@ -0,0 +1,7 @@
{
"presets": [
"stage-0",
"es2015",
"react"
]
}
+57 -45
View File
@@ -25,7 +25,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 +40,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 +48,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 +97,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 +117,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 +155,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 +171,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 +184,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
+11
View File
@@ -5,6 +5,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)
@@ -22,8 +26,15 @@
- 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
- 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
+129 -61
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,45 @@ 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_MINOR 5)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
# 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)
@@ -129,6 +138,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 +193,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 +209,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 +275,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 +322,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 +334,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 +416,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 +439,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 +482,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 +527,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 +543,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}
@@ -618,9 +662,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 +675,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 +727,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) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
- `name`: The name of the way along which travel proceeds.
- `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 |
+2 -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 |
+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 | | | | |
+10 -10
View File
@@ -72,16 +72,16 @@ Feature: Turn Lane Guidance
Given the node map
"""
e
a b c g
d
f
i h j
a - - b.-.- - c-g
| ' 'd
| f
|
|
|
|
|
|
i - - h - - - j
"""
And the ways
@@ -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 |
+56 -37
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
"""
@@ -707,11 +724,11 @@ 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 |
| waypoints | route | turns |
| a,g | road,cross,cross | depart,turn left,arrive |
| a,e | road,road,road | depart,continue straight,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 |
| a,f | road,road,cross,cross | depart,continue straight,turn right,arrive |
Scenario: On-Off on Highway
Given the node map
@@ -738,12 +755,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 +772,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 +947,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 +1014,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 |
+10 -10
View File
@@ -32,9 +32,9 @@ Feature: Slipways and Dedicated Turn Lanes
| 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
@@ -63,9 +63,9 @@ Feature: Slipways and Dedicated Turn Lanes
| 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,8 +119,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: Inner city expressway with on road
Given the node map
+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 |
+13 -13
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
@@ -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,road | depart,turn left,arrive | g,e,f |
| 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
@@ -775,7 +775,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
+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 |
+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 |
+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;
+2 -1
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)};
}
+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"
@@ -47,9 +42,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 +64,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,35 +112,35 @@ 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);
m_check_sum =
*data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::HSGR_CHECKSUM);
util::SimpleLogger().Write() << "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))
{
@@ -158,325 +149,266 @@ class SharedDataFacade final : public BaseDataFacade
"Is any data loaded into shared memory?");
}
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 +932,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,94 @@
#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
{
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);
}
}
}
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::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);
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 -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,
@@ -233,7 +233,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),
+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 =
+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
@@ -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);
+36
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,6 +44,7 @@ struct ExtractionWay
backward_speed = -1;
duration = -1;
roundabout = false;
circular = false;
is_startpoint = true;
is_access_restricted = false;
name.clear();
@@ -50,6 +65,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,6 +95,7 @@ struct ExtractionWay
std::string turn_lanes_forward;
std::string turn_lanes_backward;
bool roundabout;
bool circular;
bool is_access_restricted;
bool is_startpoint;
TravelMode forward_travel_mode : 4;
@@ -1,13 +1,15 @@
#ifndef OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
#define OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
#include <utility>
#include <vector>
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "util/attributes.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/node_based_graph.hpp"
namespace osrm
@@ -27,24 +29,51 @@ 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.
* Since we are computing the length of the segment anyhow, we also return it.
*/
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
+54 -15
View File
@@ -5,6 +5,7 @@
#include <vector>
#include "extractor/guidance/turn_instruction.hpp"
#include "util/bearing.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" // EdgeID
@@ -16,16 +17,37 @@ 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 IntersectionShapeData &lhs, const IntersectionShapeData &rhs) {
return util::bearing::angleBetweenBearings(base_bearing, lhs.bearing) <
util::bearing::angleBetweenBearings(base_bearing, rhs.bearing);
};
};
// 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
@@ -49,14 +71,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,10 +96,24 @@ 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>
using IntersectionShape = std::vector<IntersectionShapeData>;
struct IntersectionView final : std::vector<IntersectionViewData>
{
using Base = std::vector<IntersectionViewData>;
bool valid() const
{
return std::is_sorted(begin(), end(), std::mem_fn(&IntersectionViewData::CompareByAngle));
};
Base::iterator findClosestTurn(double angle);
Base::const_iterator findClosestTurn(double angle) const;
};
struct Intersection final : std::vector<ConnectedRoad>
{
using Base = std::vector<ConnectedRoad>;
/*
* 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
@@ -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,11 +33,20 @@ 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;
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
*/
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
@@ -45,68 +54,61 @@ class IntersectionGenerator
// 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;
IntersectionView GetActualNextIntersection(const NodeID starting_node,
const EdgeID via_edge,
NodeID *resulting_from_node,
EdgeID *resulting_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
@@ -0,0 +1,117 @@
#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_*/
@@ -21,9 +21,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
@@ -90,7 +87,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 +116,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,11 +133,9 @@ 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,
@@ -65,7 +65,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)
{
}
+1
View File
@@ -165,6 +165,7 @@ 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();
+33 -8
View File
@@ -4,6 +4,7 @@
#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"
@@ -14,6 +15,7 @@
#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 +23,7 @@
#include <memory>
#include <string>
#include <tuple>
#include <unordered_set>
#include <utility>
#include <vector>
@@ -34,7 +37,6 @@ namespace guidance
class TurnAnalysis
{
public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
@@ -45,19 +47,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;
@@ -2,7 +2,7 @@
#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>
@@ -22,13 +22,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
+20 -15
View File
@@ -43,11 +43,12 @@ struct InternalExtractorEdge
MIN_OSM_NODEID,
0,
0,
false,
false,
false,
false,
true,
false, // forward
false, // backward
false, // roundabout
false, // circular
false, // access restricted
true, // can be startpoint
TRAVEL_MODE_INACCESSIBLE,
false,
guidance::TurnLaneType::empty,
@@ -62,6 +63,7 @@ struct InternalExtractorEdge
bool forward,
bool backward,
bool roundabout,
bool circular,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
@@ -75,6 +77,7 @@ struct InternalExtractorEdge
forward,
backward,
roundabout,
circular,
access_restricted,
startpoint,
travel_mode,
@@ -99,11 +102,12 @@ struct InternalExtractorEdge
MIN_OSM_NODEID,
0,
WeightData(),
false,
false,
false,
false,
true,
false, // forward
false, // backward
false, // roundabout
false, // circular
false, // access restricted
true, // can be startpoint
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID,
@@ -115,11 +119,12 @@ struct InternalExtractorEdge
MAX_OSM_NODEID,
SPECIAL_NODEID,
WeightData(),
false,
false,
false,
false,
true,
false, // forward
false, // backward
false, // roundabout
false, // circular
false, // access restricted
true, // can be startpoint
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID,
+13 -5
View File
@@ -22,6 +22,7 @@ struct NodeBasedEdge
bool forward,
bool backward,
bool roundabout,
bool circular,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
@@ -38,6 +39,7 @@ struct NodeBasedEdge
bool forward : 1;
bool backward : 1;
bool roundabout : 1;
bool circular : 1;
bool access_restricted : 1;
bool startpoint : 1;
bool is_split : 1;
@@ -55,6 +57,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool forward,
bool backward,
bool roundabout,
bool circular,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
@@ -70,8 +73,9 @@ 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), access_restricted(false),
startpoint(true), is_split(false), travel_mode(false),
lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@@ -82,6 +86,7 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
bool forward,
bool backward,
bool roundabout,
bool circular,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
@@ -89,9 +94,10 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
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),
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))
{
}
@@ -119,6 +125,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
bool forward,
bool backward,
bool roundabout,
bool circular,
bool access_restricted,
bool startpoint,
TravelMode travel_mode,
@@ -132,6 +139,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
forward,
backward,
roundabout,
circular,
access_restricted,
startpoint,
travel_mode,
+5 -10
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);
+150 -195
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/fingerprint.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/seek.hpp>
#include <cerrno>
#include <cstring>
#include <tuple>
#include <type_traits>
namespace osrm
{
@@ -20,201 +20,156 @@ 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 std::string filename;
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 &filename_, const FingerprintFlag flag)
: filename(filename_.string())
{
input_stream.open(filename_, std::ios::binary);
if (!input_stream)
throw util::exception("Error opening " + filename + ":" + std::strerror(errno));
if (flag == VerifyFingerprint && !ReadAndCheckFingerprint())
{
throw util::exception("Fingerprint mismatch in " + filename);
}
}
/* 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 " + filename +
": Unexpected end of file");
}
throw util::exception("Error reading from " + filename + ": " + std::strerror(errno));
}
}
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)
{
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))
{
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)
{
edges_input_stream.read((char *)&(current_edge_data), sizeof(extractor::OriginalEdgeData));
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;
}
}
// 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)
{
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());
}
}
// 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;
};
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);
}
}
}
}
+171
View File
@@ -0,0 +1,171 @@
#ifndef OSRM_STORAGE_SERIALIZATION_HPP_
#define OSRM_STORAGE_SERIALIZATION_HPP_
#include "contractor/query_edge.hpp"
#include "extractor/extractor.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/query_node.hpp"
#include "storage/io.hpp"
#include "util/exception.hpp"
#include "util/fingerprint.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/seek.hpp>
#include <cerrno>
#include <cstring>
#include <tuple>
#include <type_traits>
namespace osrm
{
namespace storage
{
namespace serialization
{
// To make function calls consistent, this function returns the fixed number of properties
inline std::size_t readPropertiesCount() { return 1; }
struct HSGRHeader
{
std::uint32_t checksum;
std::uint64_t number_of_nodes;
std::uint64_t number_of_edges;
};
// Reads the checksum, number of nodes and number of edges written in the header file of a `.hsgr`
// file and returns them in a HSGRHeader struct
inline HSGRHeader readHSGRHeader(io::FileReader &input_file)
{
const util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid();
const auto fingerprint_loaded = input_file.ReadOne<util::FingerPrint>();
if (!fingerprint_loaded.TestGraphUtil(fingerprint_valid))
{
util::SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
HSGRHeader header;
input_file.ReadInto(header.checksum);
input_file.ReadInto(header.number_of_nodes);
input_file.ReadInto(header.number_of_edges);
// If we have edges, then we must have nodes.
// However, there can be nodes with no edges (some test cases create this)
BOOST_ASSERT_MSG(header.number_of_edges == 0 || header.number_of_nodes > 0,
"edges exist, but there are no nodes");
return header;
}
// Reads the graph data of a `.hsgr` file into memory
// Needs to be called after readHSGRHeader() to get the correct offset in the stream
using NodeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::NodeArrayEntry;
using EdgeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::EdgeArrayEntry;
inline void readHSGR(io::FileReader &input_file,
NodeT *node_buffer,
const std::uint64_t number_of_nodes,
EdgeT *edge_buffer,
const std::uint64_t number_of_edges)
{
BOOST_ASSERT(node_buffer);
BOOST_ASSERT(edge_buffer);
input_file.ReadInto(node_buffer, number_of_nodes);
input_file.ReadInto(edge_buffer, number_of_edges);
}
// Loads datasource_indexes from .datasource_indexes into memory
// Needs to be called after readElementCount() to get the correct offset in the stream
inline void readDatasourceIndexes(io::FileReader &datasource_indexes_file,
uint8_t *datasource_buffer,
const std::uint64_t number_of_datasource_indexes)
{
BOOST_ASSERT(datasource_buffer);
datasource_indexes_file.ReadInto(datasource_buffer, number_of_datasource_indexes);
}
// Loads edge data from .edge files into memory which includes its
// geometry, name ID, turn instruction, lane data ID, travel mode, entry class ID
// Needs to be called after readElementCount() to get the correct offset in the stream
inline void readEdges(io::FileReader &edges_input_file,
GeometryID *geometry_list,
NameID *name_id_list,
extractor::guidance::TurnInstruction *turn_instruction_list,
LaneDataID *lane_data_id_list,
extractor::TravelMode *travel_mode_list,
EntryClassID *entry_class_id_list,
util::guidance::TurnBearing *pre_turn_bearing_list,
util::guidance::TurnBearing *post_turn_bearing_list,
const std::uint64_t number_of_edges)
{
BOOST_ASSERT(geometry_list);
BOOST_ASSERT(name_id_list);
BOOST_ASSERT(turn_instruction_list);
BOOST_ASSERT(lane_data_id_list);
BOOST_ASSERT(travel_mode_list);
BOOST_ASSERT(entry_class_id_list);
extractor::OriginalEdgeData current_edge_data;
for (std::uint64_t i = 0; i < number_of_edges; ++i)
{
edges_input_file.ReadInto(current_edge_data);
geometry_list[i] = current_edge_data.via_geometry;
name_id_list[i] = current_edge_data.name_id;
turn_instruction_list[i] = current_edge_data.turn_instruction;
lane_data_id_list[i] = current_edge_data.lane_data_id;
travel_mode_list[i] = current_edge_data.travel_mode;
entry_class_id_list[i] = current_edge_data.entry_classid;
pre_turn_bearing_list[i] = current_edge_data.pre_turn_bearing;
post_turn_bearing_list[i] = current_edge_data.post_turn_bearing;
}
}
// Loads coordinates and OSM node IDs from .nodes files into memory
// Needs to be called after readElementCount() to get the correct offset in the stream
template <typename OSMNodeIDVectorT>
void readNodes(io::FileReader &nodes_file,
util::Coordinate *coordinate_list,
OSMNodeIDVectorT &osmnodeid_list,
const std::uint64_t number_of_coordinates)
{
BOOST_ASSERT(coordinate_list);
extractor::QueryNode current_node;
for (std::uint64_t i = 0; i < number_of_coordinates; ++i)
{
nodes_file.ReadInto(current_node);
coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
osmnodeid_list.push_back(current_node.node_id);
BOOST_ASSERT(coordinate_list[i].IsValid());
}
}
// 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;
};
inline DatasourceNamesData readDatasourceNames(io::FileReader &datasource_names_file)
{
DatasourceNamesData datasource_names_data;
std::vector<std::string> lines = datasource_names_file.ReadLines();
for (const auto &name : lines)
{
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;
}
}
}
}
#endif
+47 -31
View File
@@ -4,9 +4,8 @@
#include "util/exception.hpp"
#include "util/simple_logger.hpp"
#include <cstdint>
#include <array>
#include <cstdint>
namespace osrm
{
@@ -54,7 +53,7 @@ const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
"LANE_DESCRIPTION_OFFSETS",
"LANE_DESCRIPTION_MASKS"};
struct SharedDataLayout
struct DataLayout
{
enum BlockID
{
@@ -98,21 +97,17 @@ struct SharedDataLayout
NUM_BLOCKS
};
std::array<uint64_t, NUM_BLOCKS> num_entries;
std::array<uint64_t, NUM_BLOCKS> entry_size;
std::array<std::uint64_t, NUM_BLOCKS> num_entries;
std::array<std::size_t, NUM_BLOCKS> entry_size;
std::array<std::size_t, NUM_BLOCKS> entry_align;
SharedDataLayout() : num_entries(), entry_size() {}
DataLayout() : num_entries(), entry_size(), entry_align() {}
template <typename T> inline void SetBlockSize(BlockID bid, uint64_t entries)
{
num_entries[bid] = entries;
entry_size[bid] = sizeof(T);
}
inline uint64_t AlignBlockSize(uint64_t block_size) const
{
const uint64_t alignment = 4;
return (block_size + (alignment - 1)) & ~(alignment - 1);
entry_align[bid] = alignof(T);
}
inline uint64_t GetBlockSize(BlockID bid) const
@@ -120,41 +115,62 @@ struct SharedDataLayout
// special bit encoding
if (bid == CORE_MARKER)
{
return AlignBlockSize((num_entries[bid] / 32 + 1) * entry_size[bid]);
return (num_entries[bid] / 32 + 1) * entry_size[bid];
}
return AlignBlockSize(num_entries[bid] * entry_size[bid]);
return num_entries[bid] * entry_size[bid];
}
inline uint64_t GetSizeOfLayout() const
{
return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS * 2 * sizeof(CANARY);
}
inline uint64_t GetBlockOffset(BlockID bid) const
{
uint64_t result = sizeof(CANARY);
for (auto i = 0; i < bid; i++)
uint64_t result = 0;
for (auto i = 0; i < NUM_BLOCKS; i++)
{
result += GetBlockSize((BlockID)i) + 2 * sizeof(CANARY);
result += 2 * sizeof(CANARY) + GetBlockSize((BlockID)i) + entry_align[i];
}
return result;
}
template <typename T, bool WRITE_CANARY = false>
inline T *GetBlockPtr(char *shared_memory, BlockID bid)
// \brief Fit aligned storage in buffer.
// Interface Similar to [ptr.align] but omits space computation.
// The method can be removed and changed directly to an std::align
// function call after dropping gcc < 5 support.
inline void *align(std::size_t align, std::size_t, void *&ptr) const noexcept
{
T *ptr = (T *)(shared_memory + GetBlockOffset(bid));
const auto intptr = reinterpret_cast<uintptr_t>(ptr);
const auto aligned = (intptr - 1u + align) & -align;
return ptr = reinterpret_cast<void *>(aligned);
}
inline void *GetAlignedBlockPtr(void *ptr, BlockID bid) const
{
for (auto i = 0; i < bid; i++)
{
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
ptr = align(entry_align[i], entry_size[i], ptr);
ptr = static_cast<char *>(ptr) + GetBlockSize((BlockID)i);
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
}
ptr = static_cast<char *>(ptr) + sizeof(CANARY);
ptr = align(entry_align[bid], entry_size[bid], ptr);
return ptr;
}
template <typename T, bool WRITE_CANARY = false>
inline T *GetBlockPtr(char *shared_memory, BlockID bid) const
{
char *ptr = (char *)GetAlignedBlockPtr(shared_memory, bid);
if (WRITE_CANARY)
{
char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY);
char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid);
char *start_canary_ptr = ptr - sizeof(CANARY);
char *end_canary_ptr = ptr + GetBlockSize(bid);
std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr);
std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
}
else
{
char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY);
char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid);
char *start_canary_ptr = ptr - sizeof(CANARY);
char *end_canary_ptr = ptr + GetBlockSize(bid);
bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr);
bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
if (!start_canary_alive)
@@ -169,7 +185,7 @@ struct SharedDataLayout
}
}
return ptr;
return (T *)ptr;
}
};
@@ -214,7 +230,7 @@ inline std::string regionToString(const SharedDataType region)
}
}
static_assert(sizeof(block_id_to_name) / sizeof(*block_id_to_name) == SharedDataLayout::NUM_BLOCKS,
static_assert(sizeof(block_id_to_name) / sizeof(*block_id_to_name) == DataLayout::NUM_BLOCKS,
"Number of blocks needs to match the number of Block names.");
}
}
+4
View File
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STORAGE_HPP
#define STORAGE_HPP
#include "storage/shared_datatype.hpp"
#include "storage/storage_config.hpp"
#include <boost/filesystem/path.hpp>
@@ -52,6 +53,9 @@ class Storage
ReturnCode Run(int max_wait);
void PopulateLayout(DataLayout &layout);
void PopulateData(const DataLayout &layout, char *memory_ptr);
private:
StorageConfig config;
};
+35 -3
View File
@@ -8,9 +8,9 @@ namespace osrm
{
namespace util
{
namespace bearing
{
inline std::string get(const double heading)
{
BOOST_ASSERT(heading >= 0);
@@ -96,8 +96,40 @@ inline double reverseBearing(const double bearing)
return bearing - 180.;
return bearing + 180;
}
}
}
// Compute the angle between two bearings on a normal turn circle
//
// Bearings Angles
//
// 0 180
// 315 45 225 135
//
// 270 x 90 270 x 90
//
// 225 135 315 45
// 180 0
//
// A turn from north to north-east offerst bearing 0 and 45 has to be translated
// into a turn of 135 degrees. The same holdes for 90 - 135 (east to south
// east).
// For north, the transformation works by angle = 540 (360 + 180) - exit_bearing
// % 360;
// All other cases are handled by first rotating both bearings to an
// entry_bearing of 0.
inline double angleBetweenBearings(const double entry_bearing, const double exit_bearing)
{
const double offset = 360 - entry_bearing;
const double rotated_exit = [](double bearing, const double offset) {
bearing += offset;
return bearing > 360 ? bearing - 360 : bearing;
}(exit_bearing, offset);
const auto angle = 540 - rotated_exit;
return angle >= 360 ? angle - 360 : angle;
}
} // namespace bearing
} // namespace util
} // namespace osrm
#endif // BEARING_HPP
+4 -3
View File
@@ -25,8 +25,8 @@ inline void print(const engine::guidance::RouteStep &step)
{
std::cout << static_cast<int>(step.maneuver.instruction.type) << " "
<< static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
<< static_cast<int>(step.maneuver.waypoint_type) << " "
<< step.maneuver.location << " "
<< static_cast<int>(step.maneuver.waypoint_type) << " " << step.maneuver.location
<< " "
<< " Duration: " << step.duration << " Distance: " << step.distance
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
<< "\n\tIntersections: " << step.intersections.size() << " [";
@@ -44,7 +44,8 @@ inline void print(const engine::guidance::RouteStep &step)
std::cout << " " << (entry ? "true" : "false");
std::cout << ")";
}
std::cout << "] name[" << step.name_id << "]: " << step.name << " Ref: " << step.ref << " Pronunciation: " << step.pronunciation;
std::cout << "] name[" << step.name_id << "]: " << step.name << " Ref: " << step.ref
<< " Pronunciation: " << step.pronunciation;
}
inline void print(const std::vector<engine::guidance::RouteStep> &steps)
+37 -51
View File
@@ -5,6 +5,7 @@
#include "extractor/node_based_edge.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction.hpp"
#include "storage/io.hpp"
#include "util/exception.hpp"
#include "util/fingerprint.hpp"
#include "util/simple_logger.hpp"
@@ -20,6 +21,7 @@
#include <fstream>
#include <ios>
#include <unordered_set>
#include <vector>
namespace osrm
@@ -32,25 +34,14 @@ namespace util
* The since the restrictions reference nodes using their external node id,
* we need to renumber it to the new internal id.
*/
unsigned loadRestrictionsFromFile(std::istream &input_stream,
std::vector<extractor::TurnRestriction> &restriction_list)
inline unsigned loadRestrictionsFromFile(storage::io::FileReader &file_reader,
std::vector<extractor::TurnRestriction> &restriction_list)
{
const FingerPrint fingerprint_valid = FingerPrint::GetValid();
FingerPrint fingerprint_loaded;
unsigned number_of_usable_restrictions = 0;
input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
if (!fingerprint_loaded.TestContractor(fingerprint_valid))
{
SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
input_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
unsigned number_of_usable_restrictions = file_reader.ReadElementCount32();
restriction_list.resize(number_of_usable_restrictions);
if (number_of_usable_restrictions > 0)
{
input_stream.read((char *)restriction_list.data(),
number_of_usable_restrictions * sizeof(extractor::TurnRestriction));
file_reader.ReadInto(restriction_list.data(), number_of_usable_restrictions);
}
return number_of_usable_restrictions;
@@ -58,64 +49,59 @@ unsigned loadRestrictionsFromFile(std::istream &input_stream,
/**
* Reads the beginning of an .osrm file and produces:
* - list of barrier nodes
* - list of traffic lights
* - barrier nodes
* - traffic lights
* - nodes indexed by their internal (non-osm) id
*/
NodeID loadNodesFromFile(std::istream &input_stream,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
template <typename BarrierOutIter, typename TrafficSignalsOutIter>
NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
BarrierOutIter barriers,
TrafficSignalsOutIter traffic_signals,
std::vector<extractor::QueryNode> &node_array)
{
const FingerPrint fingerprint_valid = FingerPrint::GetValid();
FingerPrint fingerprint_loaded;
input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
NodeID number_of_nodes = file_reader.ReadElementCount32();
SimpleLogger().Write() << "Importing number_of_nodes new = " << number_of_nodes << " nodes ";
if (!fingerprint_loaded.TestContractor(fingerprint_valid))
{
SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
NodeID n;
input_stream.read(reinterpret_cast<char *>(&n), sizeof(NodeID));
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
node_array.resize(number_of_nodes);
extractor::ExternalMemoryNode current_node;
for (NodeID i = 0; i < n; ++i)
for (NodeID i = 0; i < number_of_nodes; ++i)
{
input_stream.read(reinterpret_cast<char *>(&current_node),
sizeof(extractor::ExternalMemoryNode));
node_array.emplace_back(current_node.lon, current_node.lat, current_node.node_id);
file_reader.ReadInto(&current_node, 1);
node_array[i].lon = current_node.lon;
node_array[i].lat = current_node.lat;
node_array[i].node_id = current_node.node_id;
if (current_node.barrier)
{
barrier_node_list.emplace_back(i);
*barriers = i;
++barriers;
}
if (current_node.traffic_lights)
{
traffic_light_node_list.emplace_back(i);
*traffic_signals = i;
++traffic_signals;
}
}
// tighten vector sizes
barrier_node_list.shrink_to_fit();
traffic_light_node_list.shrink_to_fit();
return n;
return number_of_nodes;
}
/**
* Reads a .osrm file and produces the edges.
*/
NodeID loadEdgesFromFile(std::istream &input_stream,
std::vector<extractor::NodeBasedEdge> &edge_list)
inline NodeID loadEdgesFromFile(storage::io::FileReader &file_reader,
std::vector<extractor::NodeBasedEdge> &edge_list)
{
EdgeID m;
input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
edge_list.resize(m);
SimpleLogger().Write() << " and " << m << " edges ";
EdgeID number_of_edges = file_reader.ReadElementCount32();
BOOST_ASSERT(sizeof(EdgeID) == sizeof(number_of_edges));
input_stream.read((char *)edge_list.data(), m * sizeof(extractor::NodeBasedEdge));
edge_list.resize(number_of_edges);
SimpleLogger().Write() << " and " << number_of_edges << " edges ";
file_reader.ReadInto(edge_list.data(), number_of_edges);
BOOST_ASSERT(edge_list.size() > 0);
@@ -145,7 +131,7 @@ NodeID loadEdgesFromFile(std::istream &input_stream,
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
return m;
return number_of_edges;
}
}
}
+2
View File
@@ -39,6 +39,8 @@ namespace guidance
class BearingClass
{
public:
BearingClass();
// Add a bearing to the set
void add(const DiscreteBearing bearing);
+1
View File
@@ -4,6 +4,7 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <type_traits>
#include <bitset>
+4 -3
View File
@@ -3,6 +3,7 @@
/* A set of tools required for guidance in both pre and post-processing */
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/suffix_table.hpp"
#include "engine/guidance/route_step.hpp"
@@ -50,11 +51,11 @@ inline extractor::guidance::DirectionModifier::Enum getTurnDirection(const doubl
return extractor::guidance::DirectionModifier::SharpRight;
if (angle >= 60 && angle < 140)
return extractor::guidance::DirectionModifier::Right;
if (angle >= 140 && angle < 170)
if (angle >= 140 && angle < 160)
return extractor::guidance::DirectionModifier::SlightRight;
if (angle >= 165 && angle <= 195)
if (angle >= 160 && angle <= 200)
return extractor::guidance::DirectionModifier::Straight;
if (angle > 190 && angle <= 220)
if (angle > 200 && angle <= 220)
return extractor::guidance::DirectionModifier::SlightLeft;
if (angle > 220 && angle <= 300)
return extractor::guidance::DirectionModifier::Left;
+23 -1
View File
@@ -17,6 +17,7 @@ namespace util
namespace guidance
{
class LaneTuple;
class LaneTupleIdPair;
} // namespace guidance
} // namespace util
} // namespace osrm
@@ -27,6 +28,11 @@ template <> struct hash<::osrm::util::guidance::LaneTuple>
{
inline std::size_t operator()(const ::osrm::util::guidance::LaneTuple &bearing_class) const;
};
template <> struct hash<::osrm::util::guidance::LaneTupleIdPair>
{
inline std::size_t
operator()(const ::osrm::util::guidance::LaneTupleIdPair &bearing_class) const;
};
} // namespace std
namespace osrm
@@ -73,7 +79,23 @@ class LaneTuple
}
};
using LaneTupleIdPair = std::pair<util::guidance::LaneTuple, LaneDescriptionID>;
class LaneTupleIdPair
{
public:
util::guidance::LaneTuple first;
LaneDescriptionID second;
bool operator==(const LaneTupleIdPair &other) const;
friend std::size_t hash_value(const LaneTupleIdPair &pair)
{
std::size_t seed{0};
boost::hash_combine(seed, pair.first);
boost::hash_combine(seed, pair.second);
return seed;
}
};
} // namespace guidance
} // namespace util
} // namespace osrm
+58 -1
View File
@@ -3,6 +3,7 @@
#include "osrm/coordinate.hpp"
#include <climits>
#include <cstdint>
namespace osrm
@@ -10,8 +11,64 @@ namespace osrm
namespace util
{
// Transform x and y to Hilbert SFC linear coordinate
// using N most significant bits of x and y.
// References:
// [1] Arndt, Jörg. Matters Computational Ideas, Algorithms, Source Code, 2010. 1.31.1 The Hilbert
// curve p. 86
// [2] FSM implementation from http://www.hackersdelight.org/hdcodetxt/hilbert/hil_s_from_xy.c.txt
// The method is to employ the following state transition table:
// ----------------------------------------------------------
// If the current And the next bits then append and enter
// state is of x and y are to result state
// ----------------------------------------------------------
// A (0, 0) 00 B
// A (0, 1) 01 A
// A (1, 0) 11 D
// A (1, 1) 10 A
// B (0, 0) 00 A
// B (0, 1) 11 C
// B (1, 0) 01 B
// B (1, 1) 10 B
// C (0, 0) 10 D
// C (0, 1) 11 B
// C (1, 0) 01 C
// C (1, 1) 00 D
// D (0, 0) 10 C
// D (0, 1) 01 D
// D (1, 0) 11 A
// D (1, 1) 00 C
template <int N = 32, typename T = std::uint32_t, typename R = std::uint64_t>
inline R HilbertToLinear(T x, T y)
{
static_assert(N <= sizeof(T) * CHAR_BIT, "input type is smaller than N");
static_assert(2 * N <= sizeof(R) * CHAR_BIT, "output type is smaller than 2N");
R result = 0;
unsigned state = 0;
for (int i = 0; i < N; ++i)
{
const unsigned xi = (x >> (sizeof(T) * CHAR_BIT - 1)) & 1;
const unsigned yi = (y >> (sizeof(T) * CHAR_BIT - 1)) & 1;
x <<= 1;
y <<= 1;
const unsigned row = 4 * state | 2 * xi | yi;
result = (result << 2) | ((0x361E9CB4 >> 2 * row) & 3);
state = (0x8FE65831 >> 2 * row) & 3;
}
return result;
}
// Computes a 64 bit value that corresponds to the hilbert space filling curve
std::uint64_t hilbertCode(const Coordinate coordinate);
inline std::uint64_t GetHilbertCode(const Coordinate &coordinate)
{
const std::uint32_t x = static_cast<std::int32_t>(coordinate.lon) +
static_cast<std::int32_t>(180 * COORDINATE_PRECISION);
const std::uint32_t y = static_cast<std::int32_t>(coordinate.lat) +
static_cast<std::int32_t>(90 * COORDINATE_PRECISION);
return HilbertToLinear(x, y);
}
}
}
+12 -82
View File
@@ -14,6 +14,7 @@
#include <stxxl/vector>
#include <vector>
#include "storage/io.hpp"
#include "util/fingerprint.hpp"
namespace osrm
@@ -28,31 +29,6 @@ inline bool writeFingerprint(std::ostream &stream)
return static_cast<bool>(stream);
}
inline bool readAndCheckFingerprint(std::istream &stream)
{
FingerPrint fingerprint;
const auto valid = FingerPrint::GetValid();
stream.read(reinterpret_cast<char *>(&fingerprint), sizeof(fingerprint));
// compare the compilation state stored in the fingerprint
return static_cast<bool>(stream) && valid.IsMagicNumberOK(fingerprint) &&
valid.TestContractor(fingerprint) && valid.TestGraphUtil(fingerprint) &&
valid.TestRTree(fingerprint) && valid.TestQueryObjects(fingerprint);
}
template <typename simple_type>
bool serializeVector(const std::string &filename, const std::vector<simple_type> &data)
{
std::ofstream stream(filename, std::ios::binary);
writeFingerprint(stream);
std::uint64_t count = data.size();
stream.write(reinterpret_cast<const char *>(&count), sizeof(count));
if (!data.empty())
stream.write(reinterpret_cast<const char *>(&data[0]), sizeof(simple_type) * count);
return static_cast<bool>(stream);
}
template <typename simple_type>
bool serializeVector(std::ostream &stream, const std::vector<simple_type> &data)
{
@@ -64,30 +40,13 @@ bool serializeVector(std::ostream &stream, const std::vector<simple_type> &data)
}
template <typename simple_type>
bool deserializeVector(const std::string &filename, std::vector<simple_type> &data)
bool serializeVector(const std::string &filename, const std::vector<simple_type> &data)
{
std::ifstream stream(filename, std::ios::binary);
std::ofstream stream(filename, std::ios::binary);
if (!readAndCheckFingerprint(stream))
return false;
writeFingerprint(stream);
std::uint64_t count = 0;
stream.read(reinterpret_cast<char *>(&count), sizeof(count));
data.resize(count);
if (count)
stream.read(reinterpret_cast<char *>(&data[0]), sizeof(simple_type) * count);
return static_cast<bool>(stream);
}
template <typename simple_type>
bool deserializeVector(std::istream &stream, std::vector<simple_type> &data)
{
std::uint64_t count = 0;
stream.read(reinterpret_cast<char *>(&count), sizeof(count));
data.resize(count);
if (count)
stream.read(reinterpret_cast<char *>(&data[0]), sizeof(simple_type) * count);
return static_cast<bool>(stream);
return serializeVector(stream, data);
}
// serializes a vector of vectors into an adjacency array (creates a copy of the data internally)
@@ -149,23 +108,20 @@ bool serializeVector(std::ofstream &out_stream, const stxxl::vector<simple_type>
}
template <typename simple_type>
bool deserializeAdjacencyArray(const std::string &filename,
void deserializeAdjacencyArray(const std::string &filename,
std::vector<std::uint32_t> &offsets,
std::vector<simple_type> &data)
{
std::ifstream in_stream(filename, std::ios::binary);
storage::io::FileReader file(filename, storage::io::FileReader::HasNoFingerprint);
if (!deserializeVector(in_stream, offsets))
return false;
if (!deserializeVector(in_stream, data))
return false;
file.DeserializeVector(offsets);
file.DeserializeVector(data);
// offsets have to match up with the size of the data
if (offsets.empty() || (offsets.back() != boost::numeric_cast<std::uint32_t>(data.size())))
return false;
return static_cast<bool>(in_stream);
throw util::exception("Error in " + filename + (offsets.empty()
? "Offsets are empty"
: "Offset and data size do not match"));
}
inline bool serializeFlags(const boost::filesystem::path &path, const std::vector<bool> &flags)
@@ -196,32 +152,6 @@ inline bool serializeFlags(const boost::filesystem::path &path, const std::vecto
return static_cast<bool>(flag_stream);
}
inline bool deserializeFlags(const boost::filesystem::path &path, std::vector<bool> &flags)
{
SimpleLogger().Write() << "Reading flags from " << path;
std::ifstream flag_stream(path.string(), std::ios::binary);
if (!readAndCheckFingerprint(flag_stream))
return false;
std::uint32_t number_of_bits;
flag_stream.read(reinterpret_cast<char *>(&number_of_bits), sizeof(number_of_bits));
flags.resize(number_of_bits);
// putting bits in ints
std::uint32_t chunks = (number_of_bits + 31) / 32;
std::size_t bit_position = 0;
std::uint32_t chunk;
for (std::size_t chunk_id = 0; chunk_id < chunks; ++chunk_id)
{
flag_stream.read(reinterpret_cast<char *>(&chunk), sizeof(chunk));
std::bitset<32> chunk_bits(chunk);
for (std::size_t bit = 0; bit < 32 && bit_position < number_of_bits; ++bit, ++bit_position)
flags[bit_position] = chunk_bits[bit];
}
SimpleLogger().Write() << "Read " << number_of_bits << " bits in " << chunks
<< " Chunks from disk.";
return static_cast<bool>(flag_stream);
}
} // namespace util
} // namespace osrm
+32
View File
@@ -0,0 +1,32 @@
#ifndef ISATTY_HPP
#define ISATTY_HPP
// For isatty()
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#else
#ifdef WIN32
#include <io.h>
#define isatty _isatty
#define fileno _fileno
#else
#error Unknown platform - isatty implementation required
#endif // win32
#endif // unix
#include <cstdio>
namespace osrm
{
namespace util
{
// Returns true if stdout is a tty, false otherwise
// Useful for when you want to do something different when
// output is redirected to a logfile
inline bool IsStdoutATTY() { return isatty(fileno(stdout)); }
} // namespace util
} // namespace osrm
#endif
+1 -1
View File
@@ -18,7 +18,7 @@ class NameTable
{
private:
// FIXME should this use shared memory
RangeTable<16, false> m_name_table;
util::RangeTable<16, false> m_name_table;
ShM<char, false>::vector m_names_char_list;
public:
+8 -3
View File
@@ -20,7 +20,7 @@ struct NodeBasedEdgeData
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false), reversed(false),
roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
roundabout(false), circular(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@@ -31,12 +31,14 @@ struct NodeBasedEdgeData
bool access_restricted,
bool reversed,
bool roundabout,
bool circular,
bool startpoint,
extractor::TravelMode travel_mode,
const LaneDescriptionID lane_description_id)
: distance(distance), edge_id(edge_id), name_id(name_id),
access_restricted(access_restricted), reversed(reversed), roundabout(roundabout),
startpoint(startpoint), travel_mode(travel_mode), lane_description_id(lane_description_id)
circular(circular), startpoint(startpoint), travel_mode(travel_mode),
lane_description_id(lane_description_id)
{
}
@@ -46,6 +48,7 @@ struct NodeBasedEdgeData
bool access_restricted : 1;
bool reversed : 1;
bool roundabout : 1;
bool circular : 1;
bool startpoint : 1;
extractor::TravelMode travel_mode : 4;
LaneDescriptionID lane_description_id;
@@ -54,7 +57,8 @@ struct NodeBasedEdgeData
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
{
return (reversed == other.reversed) && (roundabout == other.roundabout) &&
(startpoint == other.startpoint) && (access_restricted == other.access_restricted) &&
(circular == other.circular) && (startpoint == other.startpoint) &&
(access_restricted == other.access_restricted) &&
(travel_mode == other.travel_mode) &&
(road_classification == other.road_classification);
}
@@ -82,6 +86,7 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
BOOST_ASSERT(output_edge.data.distance > 0);
output_edge.data.roundabout = input_edge.roundabout;
output_edge.data.circular = input_edge.circular;
output_edge.data.name_id = input_edge.name_id;
output_edge.data.access_restricted = input_edge.access_restricted;
output_edge.data.travel_mode = input_edge.travel_mode;
+8
View File
@@ -4,6 +4,8 @@
#include <atomic>
#include <iostream>
#include "util/isatty.hpp"
namespace osrm
{
namespace util
@@ -71,6 +73,12 @@ class Percent
{
std::cout << ".";
}
// When not on a TTY, print newlines after each progress indicator so
// so that progress is visible to line-buffered logging systems
if (!IsStdoutATTY())
std::cout << std::endl;
std::cout.flush();
}
}
+16
View File
@@ -1,6 +1,7 @@
#ifndef RANGE_TABLE_HPP
#define RANGE_TABLE_HPP
#include "storage/io.hpp"
#include "util/integer_range.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
@@ -138,6 +139,21 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
sum_lengths = lengths_prefix_sum;
}
void ReadARangeTable(osrm::storage::io::FileReader &filereader)
{
unsigned number_of_blocks = filereader.ReadElementCount32();
// read total length
filereader.ReadInto(&sum_lengths, 1);
block_offsets.resize(number_of_blocks);
diff_blocks.resize(number_of_blocks);
// read block offsets
filereader.ReadInto(block_offsets.data(), number_of_blocks);
// read blocks
filereader.ReadInto(diff_blocks.data(), number_of_blocks);
}
inline RangeT GetRange(const unsigned id) const
{
BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
+5 -13
View File
@@ -198,7 +198,7 @@ class StaticRTree
COORDINATE_PRECISION *
web_mercator::latToY(toFloating(current_centroid.lat)))};
current_wrapper.m_hilbert_value = hilbertCode(current_centroid);
current_wrapper.m_hilbert_value = GetHilbertCode(current_centroid);
}
});
@@ -346,21 +346,13 @@ class StaticRTree
const CoordinateListT &coordinate_list)
: m_coordinate_list(coordinate_list)
{
// open tree node file and load into RAM.
if (!boost::filesystem::exists(node_file))
{
throw exception("ram index file does not exist");
}
if (boost::filesystem::file_size(node_file) == 0)
{
throw exception("ram index file is empty");
}
boost::filesystem::ifstream tree_node_file(node_file, std::ios::binary);
storage::io::FileReader tree_node_file(node_file,
storage::io::FileReader::HasNoFingerprint);
const auto tree_size = storage::io::readElementCount(tree_node_file);
const auto tree_size = tree_node_file.ReadElementCount64();
m_search_tree.resize(tree_size);
storage::io::readRamIndex(tree_node_file, &m_search_tree[0], tree_size);
tree_node_file.ReadInto(&m_search_tree[0], tree_size);
MapLeafNodesFile(leaf_file);
}
+9 -1
View File
@@ -17,11 +17,18 @@
"bin": {
"cucumber": "./node_modules/cucumber/bin/cucumber.js"
},
"browserify": {
"transform": [
"babelify",
"brfs"
]
},
"scripts": {
"lint": "eslint -c ./.eslintrc features/step_definitions/ features/support/",
"test": "npm run lint && ./node_modules/cucumber/bin/cucumber.js features/ -p verify",
"clean-test": "rm -rf test/cache",
"cucumber": "./node_modules/cucumber/bin/cucumber.js"
"cucumber": "./node_modules/cucumber/bin/cucumber.js",
"build-api-docs": "./scripts/build_api_docs.sh"
},
"repository": {
"type": "git",
@@ -37,6 +44,7 @@
"node": ">=4.0.0"
},
"devDependencies": {
"docbox": "^1.0.2",
"eslint": "^2.4.0"
}
}
+7 -4
View File
@@ -221,9 +221,12 @@ function way_function (way, result)
end
-- roundabout handling
if junction and "roundabout" == junction then
if junction and ("roundabout" == junction) then
result.roundabout = true
end
if junction and ("circular" == junction) then
result.circular = true;
end
-- speed
local bridge_speed = bridge_speeds[bridge]
@@ -281,7 +284,7 @@ function way_function (way, result)
else
-- biking not allowed, maybe we can push our bike?
-- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike
if foot ~= 'no' and junction ~= "roundabout" then
if foot ~= 'no' and (junction ~= "roundabout" and junction ~= "circular") then
if pedestrian_speeds[highway] then
-- pedestrian-only ways and areas
result.forward_speed = pedestrian_speeds[highway]
@@ -313,7 +316,7 @@ function way_function (way, result)
-- direction
local impliedOneway = false
if junction == "roundabout" or highway == "motorway" then
if junction == "roundabout" or junction == "circular" or highway == "motorway" then
impliedOneway = true
end
@@ -353,7 +356,7 @@ function way_function (way, result)
-- pushing bikes
if bicycle_speeds[highway] or pedestrian_speeds[highway] then
if foot ~= "no" and junction ~= "roundabout" then
if foot ~= "no" and junction ~= "roundabout" and junction ~= "circular" then
if result.backward_mode == mode.inaccessible then
result.backward_speed = walking_speed
result.backward_mode = mode.pushing_bike
+402 -223
View File
@@ -3,48 +3,100 @@ local find_access_tag = require("lib/access").find_access_tag
local get_destination = require("lib/destination").get_destination
local set_classification = require("lib/guidance").set_classification
local get_turn_lanes = require("lib/guidance").get_turn_lanes
local Set = require('lib/set')
local Sequence = require('lib/sequence')
-- Begin of globals
barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["lift_gate"] = true, ["no"] = true, ["entrance"] = true }
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true, ["destination"] = true }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true, ["psv"] = true, ["delivery"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags_hierarchy = { "motorcar", "motor_vehicle", "vehicle", "access" }
service_tag_restricted = { ["parking_aisle"] = true, ["parking"] = true }
service_tag_forbidden = { ["emergency_access"] = true }
restrictions = { "motorcar", "motor_vehicle", "vehicle" }
barrier_whitelist = Set {
'cattle_grid',
'border_control',
'checkpoint',
'toll_booth',
'sally_port',
'gate',
'lift_gate',
'no',
'entrance'
}
access_tag_whitelist = Set {
'yes',
'motorcar',
'motor_vehicle',
'vehicle',
'permissive',
'designated',
'destination'
}
access_tag_blacklist = Set {
'no',
'private',
'agricultural',
'forestry',
'emergency',
'psv',
'delivery'
}
access_tag_restricted = Set {
'destination',
'delivery'
}
access_tags_hierarchy = Sequence {
'motorcar',
'motor_vehicle',
'vehicle',
'access'
}
service_tag_restricted = Set {
'parking_aisle',
'parking'
}
service_tag_forbidden = Set {
'emergency_access'
}
restrictions = Sequence {
'motorcar', "motor_vehicle", "vehicle" }
-- A list of suffixes to suppress in name change instructions
suffix_list = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "North", "South", "West", "East" }
-- Note: a Set does not work here because it's read from C++
suffix_list = {
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
}
speed_profile = {
["motorway"] = 90,
["motorway_link"] = 45,
["trunk"] = 85,
["trunk_link"] = 40,
["primary"] = 65,
["primary_link"] = 30,
["secondary"] = 55,
["secondary_link"] = 25,
["tertiary"] = 40,
["tertiary_link"] = 20,
["unclassified"] = 25,
["residential"] = 25,
["living_street"] = 10,
["service"] = 15,
-- ["track"] = 5,
["ferry"] = 5,
["movable"] = 5,
["shuttle_train"] = 10,
["default"] = 10
motorway = 90,
motorway_link = 45,
trunk = 85,
trunk_link = 40,
primary = 65,
primary_link = 30,
secondary = 55,
secondary_link = 25,
tertiary = 40,
tertiary_link = 20,
unclassified = 25,
residential = 25,
living_street = 10,
service = 15,
--track = 5,
ferry = 5,
movable = 5,
shuttle_train = 10,
default = 10
}
-- service speeds
service_speeds = {
["alley"] = 5,
["parking"] = 5,
["parking_aisle"] = 5,
["driveway"] = 5,
alley = 5,
parking = 5,
parking_aisle = 5,
driveway = 5,
["drive-through"] = 5
}
@@ -53,67 +105,67 @@ service_speeds = {
-- max speed for surfaces
surface_speeds = {
["asphalt"] = nil, -- nil mean no limit. removing the line has the same effect
["concrete"] = nil,
asphalt = nil, -- nil mean no limit. removing the line has the same effect
concrete = nil,
["concrete:plates"] = nil,
["concrete:lanes"] = nil,
["paved"] = nil,
paved = nil,
["cement"] = 80,
["compacted"] = 80,
["fine_gravel"] = 80,
cement = 80,
compacted = 80,
fine_gravel = 80,
["paving_stones"] = 60,
["metal"] = 60,
["bricks"] = 60,
paving_stones = 60,
metal = 60,
bricks = 60,
["grass"] = 40,
["wood"] = 40,
["sett"] = 40,
["grass_paver"] = 40,
["gravel"] = 40,
["unpaved"] = 40,
["ground"] = 40,
["dirt"] = 40,
["pebblestone"] = 40,
["tartan"] = 40,
grass = 40,
wood = 40,
sett = 40,
grass_paver = 40,
gravel = 40,
unpaved = 40,
ground = 40,
dirt = 40,
pebblestone = 40,
tartan = 40,
["cobblestone"] = 30,
["clay"] = 30,
cobblestone = 30,
clay = 30,
["earth"] = 20,
["stone"] = 20,
["rocky"] = 20,
["sand"] = 20,
earth = 20,
stone = 20,
rocky = 20,
sand = 20,
["mud"] = 10
mud = 10
}
-- max speed for tracktypes
tracktype_speeds = {
["grade1"] = 60,
["grade2"] = 40,
["grade3"] = 30,
["grade4"] = 25,
["grade5"] = 20
grade1 = 60,
grade2 = 40,
grade3 = 30,
grade4 = 25,
grade5 = 20
}
-- max speed for smoothnesses
smoothness_speeds = {
["intermediate"] = 80,
["bad"] = 40,
["very_bad"] = 20,
["horrible"] = 10,
["very_horrible"] = 5,
["impassable"] = 0
intermediate = 80,
bad = 40,
very_bad = 20,
horrible = 10,
very_horrible = 5,
impassable = 0
}
-- http://wiki.openstreetmap.org/wiki/Speed_limits
maxspeed_table_default = {
["urban"] = 50,
["rural"] = 90,
["trunk"] = 110,
["motorway"] = 130
urban = 50,
rural = 90,
trunk = 110,
motorway = 130
}
-- List only exceptions
@@ -209,13 +261,13 @@ end
function node_function (node, result)
-- parse access and barrier tags
local access = find_access_tag(node, access_tags_hierarchy)
if access and access ~= "" then
if access then
if access_tag_blacklist[access] then
result.barrier = true
end
else
local barrier = node:get_value_by_key("barrier")
if barrier and "" ~= barrier then
if barrier then
-- make an exception for rising bollard barriers
local bollard = node:get_value_by_key("bollard")
local rising_bollard = bollard and "rising" == bollard
@@ -228,35 +280,27 @@ function node_function (node, result)
-- check if node is a traffic light
local tag = node:get_value_by_key("highway")
if tag and "traffic_signals" == tag then
if "traffic_signals" == tag then
result.traffic_lights = true
end
end
function way_function (way, result)
local highway = way:get_value_by_key("highway")
local route = way:get_value_by_key("route")
local bridge = way:get_value_by_key("bridge")
-- abort early if this way is obviouslt not routable
function initial_routability_check(way,result,data)
data.speed_type = way:get_value_by_key('highway')
if not ((highway and highway ~= "") or (route and route ~= "") or (bridge and bridge ~= "")) then
return
end
-- default to driving mode, may get overwritten below
result.forward_mode = mode.driving
result.backward_mode = mode.driving
-- we dont route over areas
local area = way:get_value_by_key("area")
if ignore_areas and area and "yes" == area then
return
end
return data.speed_type ~= nil or
way:get_value_by_key('route') ~= nil or
way:get_value_by_key('bridge') ~= nil
end
-- handle high occupancy vehicle tags
function handle_hov(way,result)
-- respect user-preference for HOV-only ways
if ignore_hov_ways then
local hov = way:get_value_by_key("hov")
if hov and "designated" == hov then
return
if "designated" == hov then
return false
end
-- also respect user-preference for HOV-only ways when all lanes are HOV-designated
@@ -277,18 +321,18 @@ function way_function (way, result)
local hov_lanes_forward = way:get_value_by_key("hov:lanes:forward")
local hov_lanes_backward = way:get_value_by_key("hov:lanes:backward")
local hov_all_designated = hov_lanes and hov_lanes ~= ""
and has_all_designated_hov_lanes(hov_lanes)
local hov_all_designated = hov_lanes and
has_all_designated_hov_lanes(hov_lanes)
local hov_all_designated_forward = hov_lanes_forward and hov_lanes_forward ~= ""
and has_all_designated_hov_lanes(hov_lanes_forward)
local hov_all_designated_forward = hov_lanes_forward and
has_all_designated_hov_lanes(hov_lanes_forward)
local hov_all_designated_backward = hov_lanes_backward and hov_lanes_backward ~= ""
and has_all_designated_hov_lanes(hov_lanes_backward)
local hov_all_designated_backward = hov_lanes_backward and
has_all_designated_hov_lanes(hov_lanes_backward)
-- forward/backward lane depend on a way's direction
local oneway = way:get_value_by_key("oneway")
local reverse = oneway and oneway == "-1"
local reverse = oneway == "-1"
if hov_all_designated or hov_all_designated_forward then
if reverse then
@@ -306,72 +350,97 @@ function way_function (way, result)
end
end
end -- hov handling
end
end
-- handle various that can block access
function is_way_blocked(way,result)
-- we dont route over areas
local area = way:get_value_by_key("area")
if ignore_areas and "yes" == area then
return false
end
-- respect user-preference for toll=yes ways
local toll = way:get_value_by_key("toll")
if ignore_toll_ways and toll and "yes" == toll then
return
if ignore_toll_ways and "yes" == toll then
return false
end
-- Reversible oneways change direction with low frequency (think twice a day):
-- do not route over these at all at the moment because of time dependence.
-- Note: alternating (high frequency) oneways are handled below with penalty.
local oneway = way:get_value_by_key("oneway")
if oneway and "reversible" == oneway then
return
if "reversible" == oneway then
return false
end
local impassable = way:get_value_by_key("impassable")
if impassable and "yes" == impassable then
return
if "yes" == impassable then
return false
end
local status = way:get_value_by_key("status")
if status and "impassable" == status then
return
if "impassable" == status then
return false
end
end
-- Check if we are allowed to access the way
local access = find_access_tag(way, access_tags_hierarchy)
if access_tag_blacklist[access] then
return
-- set default mode
function set_default_mode(way,result)
result.forward_mode = mode.driving
result.backward_mode = mode.driving
end
-- check accessibility by traversing our acces tag hierarchy
function handle_access(way,result,data)
data.access = find_access_tag(way, access_tags_hierarchy)
if access_tag_blacklist[data.access] then
return false
end
end
-- handling ferries and piers
local route_speed = speed_profile[route]
if (route_speed and route_speed > 0) then
highway = route
local duration = way:get_value_by_key("duration")
if duration and durationIsValid(duration) then
result.duration = max( parseDuration(duration), 1 )
-- handling ferries and piers
function handle_ferries(way,result)
local route = way:get_value_by_key("route")
if route then
local route_speed = speed_profile[route]
if route_speed and route_speed > 0 then
local duration = way:get_value_by_key("duration")
if duration and durationIsValid(duration) then
result.duration = max( parseDuration(duration), 1 )
end
result.forward_mode = mode.ferry
result.backward_mode = mode.ferry
result.forward_speed = route_speed
result.backward_speed = route_speed
end
result.forward_mode = mode.ferry
result.backward_mode = mode.ferry
result.forward_speed = route_speed
result.backward_speed = route_speed
end
end
-- handling movable bridges
local bridge_speed = speed_profile[bridge]
local capacity_car = way:get_value_by_key("capacity:car")
if (bridge_speed and bridge_speed > 0) and (capacity_car ~= 0) then
highway = bridge
local duration = way:get_value_by_key("duration")
if duration and durationIsValid(duration) then
result.duration = max( parseDuration(duration), 1 )
-- handling movable bridges
function handle_movables(way,result)
local bridge = way:get_value_by_key("bridge")
if bridge then
local bridge_speed = speed_profile[bridge]
if bridge_speed and bridge_speed > 0 then
local capacity_car = way:get_value_by_key("capacity:car")
if capacity_car ~= 0 then
local duration = way:get_value_by_key("duration")
if duration and durationIsValid(duration) then
result.duration = max( parseDuration(duration), 1 )
end
result.forward_speed = bridge_speed
result.backward_speed = bridge_speed
end
end
result.forward_speed = bridge_speed
result.backward_speed = bridge_speed
end
-- leave early if this way is not accessible
if "" == highway then
return
end
end
-- handle speed (excluding maxspeed)
function handle_speed(way,result,data)
if result.forward_speed == -1 then
local highway_speed = speed_profile[highway]
local highway_speed = speed_profile[way:get_value_by_key("highway")]
local max_speed = parse_maxspeed( way:get_value_by_key("maxspeed") )
-- Set the avg speed on the way if it is accessible by road class
if highway_speed then
@@ -385,7 +454,7 @@ function way_function (way, result)
end
else
-- Set the avg speed on ways that are marked accessible
if access_tag_whitelist[access] then
if access_tag_whitelist[data.access] then
result.forward_speed = speed_profile["default"]
result.backward_speed = speed_profile["default"]
end
@@ -398,18 +467,28 @@ function way_function (way, result)
end
if -1 == result.forward_speed and -1 == result.backward_speed then
return
return false
end
if handle_side_roads(way,result) == false then return false end
if handle_surface(way,result) == false then return false end
if handle_maxspeed(way,result) == false then return false end
if handle_speed_scaling(way,result) == false then return false end
if handle_alternating_speed(way,result) == false then return false end
end
-- reduce speed on special side roads
-- reduce speed on special side roads
function handle_side_roads(way,result)
local sideway = way:get_value_by_key("side_road")
if "yes" == sideway or
"rotary" == sideway then
result.forward_speed = result.forward_speed * side_road_speed_multiplier
result.backward_speed = result.backward_speed * side_road_speed_multiplier
end
end
-- reduce speed on bad surfaces
-- reduce speed on bad surfaces
function handle_surface(way,result)
local surface = way:get_value_by_key("surface")
local tracktype = way:get_value_by_key("tracktype")
local smoothness = way:get_value_by_key("smoothness")
@@ -426,65 +505,77 @@ function way_function (way, result)
result.forward_speed = math.min(smoothness_speeds[smoothness], result.forward_speed)
result.backward_speed = math.min(smoothness_speeds[smoothness], result.backward_speed)
end
end
-- set the road classification based on guidance globals configuration
set_classification(highway,result,way)
-- handles name, including ref and pronunciation
function handle_names(way,result)
-- parse the remaining tags
local name = way:get_value_by_key("name")
local pronunciation = way:get_value_by_key("name:pronunciation")
local ref = way:get_value_by_key("ref")
local junction = way:get_value_by_key("junction")
-- local barrier = way:get_value_by_key("barrier", "")
-- local cycleway = way:get_value_by_key("cycleway", "")
local service = way:get_value_by_key("service")
-- Set the name that will be used for instructions
local has_ref = ref and "" ~= ref
local has_name = name and "" ~= name
local has_pronunciation = pronunciation and "" ~= pronunciation
if has_name then
if name then
result.name = name
end
if has_ref then
if ref then
result.ref = canonicalizeStringList(ref, ";")
end
if has_pronunciation then
if pronunciation then
result.pronunciation = pronunciation
end
end
local turn_lanes = ""
local turn_lanes_forward = ""
local turn_lanes_backward = ""
-- handle turn lanes
function handle_turn_lanes(way,result)
local turn_lanes = ''
local turn_lanes_forward = ''
local turn_lanes_backward = ''
turn_lanes, turn_lanes_forward, turn_lanes_backward = get_turn_lanes(way)
if turn_lanes and turn_lanes ~= "" then
if turn_lanes and turn_lanes ~= '' then
result.turn_lanes_forward = turn_lanes;
result.turn_lanes_backward = turn_lanes;
else
if turn_lanes_forward and turn_lanes_forward ~= "" then
result.turn_lanes_forward = turn_lanes_forward;
if turn_lanes_forward and turn_lanes_forward ~= '' then
result.turn_lanes_forward = turn_lanes_forward;
end
if turn_lanes_backward and turn_lanes_backward ~= "" then
result.turn_lanes_backward = turn_lanes_backward;
if turn_lanes_backward and turn_lanes_backward ~= '' then
result.turn_lanes_backward = turn_lanes_backward;
end
end
end
-- junctions
function handle_roundabouts(way,result)
local junction = way:get_value_by_key("junction");
if junction and "roundabout" == junction then
if junction == "roundabout" then
result.roundabout = true
end
-- Set access restriction flag if access is allowed under certain restrictions only
if access ~= "" and access_tag_restricted[access] then
-- See Issue 3361: roundabout-shaped not following roundabout rules.
-- This will get us "At Strausberger Platz do Maneuver X" instead of multiple quick turns.
-- In a new API version we can think of having a separate type passing it through to the user.
if junction == "circular" then
result.circular = true
end
end
-- Set access restriction flag if access is allowed under certain restrictions only
function handle_restricted(way,result,data)
if data.access and access_tag_restricted[data.access] then
result.is_access_restricted = true
end
end
if service and service ~= "" then
-- service roads
function handle_service(way,result)
local service = way:get_value_by_key("service")
if service then
-- Set access restriction flag if service is allowed under certain restrictions only
if service_tag_restricted[service] then
result.is_access_restricted = true
@@ -494,11 +585,57 @@ function way_function (way, result)
if service_tag_forbidden[service] then
result.forward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
return
return false
end
end
end
-- scale speeds to get better average driving times
function handle_speed_scaling(way,result)
local width = math.huge
local lanes = math.huge
if result.forward_speed > 0 or result.backward_speed > 0 then
local width_string = way:get_value_by_key("width")
if width_string and tonumber(width_string:match("%d*")) then
width = tonumber(width_string:match("%d*"))
end
local lanes_string = way:get_value_by_key("lanes")
if lanes_string and tonumber(lanes_string:match("%d*")) then
lanes = tonumber(lanes_string:match("%d*"))
end
end
-- Set direction according to tags on way
local is_bidirectional = result.forward_mode ~= mode.inaccessible and
result.backward_mode ~= mode.inaccessible
local service = way:get_value_by_key("service")
if result.forward_speed > 0 then
local scaled_speed = result.forward_speed * speed_reduction
local penalized_speed = math.huge
if service and service_speeds[service] then
penalized_speed = service_speeds[service]
elseif width <= 3 or (lanes <= 1 and is_bidirectional) then
penalized_speed = result.forward_speed / 2
end
result.forward_speed = math.min(penalized_speed, scaled_speed)
end
if result.backward_speed > 0 then
local scaled_speed = result.backward_speed * speed_reduction
local penalized_speed = math.huge
if service and service_speeds[service]then
penalized_speed = service_speeds[service]
elseif width <= 3 or (lanes <= 1 and is_bidirectional) then
penalized_speed = result.backward_speed / 2
end
result.backward_speed = math.min(penalized_speed, scaled_speed)
end
end
-- oneways
function handle_oneway(way,result)
local oneway = way:get_value_by_key("oneway")
if obey_oneway then
if oneway == "-1" then
result.forward_mode = mode.inaccessible
@@ -507,10 +644,11 @@ function way_function (way, result)
local destination = get_destination(way, is_forward)
result.destinations = canonicalizeStringList(destination, ",")
elseif oneway == "yes" or
oneway == "1" or
oneway == "true" or
junction == "roundabout" or
(highway == "motorway" and oneway ~= "no") then
oneway == "1" or
oneway == "true" or
way:get_value_by_key("junction") == "roundabout" or
way:get_value_by_key("junction") == "circular" or
(way:get_value_by_key("highway") == "motorway" and oneway ~= "no") then
result.backward_mode = mode.inaccessible
@@ -519,13 +657,17 @@ function way_function (way, result)
result.destinations = canonicalizeStringList(destination, ",")
end
end
end
-- maxspeed and advisory maxspeed
function handle_maxspeed(way,result)
-- Override speed settings if explicit forward/backward maxspeeds are given
local maxspeed_forward = parse_maxspeed(way:get_value_by_key("maxspeed:forward"))
local maxspeed_backward = parse_maxspeed(way:get_value_by_key("maxspeed:backward"))
if maxspeed_forward and maxspeed_forward > 0 then
if mode.inaccessible ~= result.forward_mode and mode.inaccessible ~= result.backward_mode then
result.backward_speed = result.forward_speed
if mode.inaccessible ~= result.forward_mode and
mode.inaccessible ~= result.backward_mode then
result.backward_speed = result.forward_speed
end
result.forward_speed = maxspeed_forward
end
@@ -555,49 +697,12 @@ function way_function (way, result)
if advisory_backward and advisory_backward > 0 then
result.backward_speed = advisory_backward
end
end
local width = math.huge
local lanes = math.huge
if result.forward_speed > 0 or result.backward_speed > 0 then
local width_string = way:get_value_by_key("width")
if width_string and tonumber(width_string:match("%d*")) then
width = tonumber(width_string:match("%d*"))
end
local lanes_string = way:get_value_by_key("lanes")
if lanes_string and tonumber(lanes_string:match("%d*")) then
lanes = tonumber(lanes_string:match("%d*"))
end
end
local is_bidirectional = result.forward_mode ~= mode.inaccessible and result.backward_mode ~= mode.inaccessible
-- scale speeds to get better avg driving times
if result.forward_speed > 0 then
local scaled_speed = result.forward_speed * speed_reduction
local penalized_speed = math.huge
if service and service ~= "" and service_speeds[service] then
penalized_speed = service_speeds[service]
elseif width <= 3 or (lanes <= 1 and is_bidirectional) then
penalized_speed = result.forward_speed / 2
end
result.forward_speed = math.min(penalized_speed, scaled_speed)
end
if result.backward_speed > 0 then
local scaled_speed = result.backward_speed * speed_reduction
local penalized_speed = math.huge
if service and service ~= "" and service_speeds[service]then
penalized_speed = service_speeds[service]
elseif width <= 3 or (lanes <= 1 and is_bidirectional) then
penalized_speed = result.backward_speed / 2
end
result.backward_speed = math.min(penalized_speed, scaled_speed)
end
-- Handle high frequency reversible oneways (think traffic signal controlled, changing direction every 15 minutes).
-- Scaling speed to take average waiting time into account plus some more for start / stop.
if oneway and "alternating" == oneway then
-- Handle high frequency reversible oneways (think traffic signal controlled, changing direction every 15 minutes).
-- Scaling speed to take average waiting time into account plus some more for start / stop.
function handle_alternating_speed(way,result)
if "alternating" == way:get_value_by_key('oneway') then
local scaling_factor = 0.4
if result.forward_speed ~= math.huge then
result.forward_speed = result.forward_speed * scaling_factor
@@ -606,9 +711,83 @@ function way_function (way, result)
result.backward_speed = result.backward_speed * scaling_factor
end
end
end
-- determine if this way can be used as a start/end point for routing
function handle_startpoint(way,result)
-- only allow this road as start point if it not a ferry
result.is_startpoint = result.forward_mode == mode.driving or result.backward_mode == mode.driving
result.is_startpoint = result.forward_mode == mode.driving or
result.backward_mode == mode.driving
end
-- set the road classification based on guidance globals configuration
function handle_classification(way,result)
set_classification(way:get_value_by_key("highway"),result,way)
end
-- main entry point for processsing a way
function way_function(way, result)
-- intermediate values used during processing
local data = {}
-- to optimize processing, we should try to abort as soon as
-- possible if the way is not routable, to avoid doing
-- unnecessary work. this implies we should check things that
-- commonly forbids access early, and handle complicated edge
-- cases later.
-- perform an quick initial check and abort if way is obviously
-- not routable, e.g. because it does not have any of the key
-- tags indicating routability
if initial_routability_check(way,result,data) == false then return end
-- set the default mode for this profile. if can be changed later
-- in case it turns we're e.g. on a ferry
if set_default_mode(way,result) == false then return end
-- check various tags that could indicate that the way is not
-- routable. this includes things like status=impassable,
-- toll=yes and oneway=reversible
if is_way_blocked(way,result) == false then return end
-- determine access status by checking our hierarchy of
-- access tags, e.g: motorcar, motor_vehicle, vehicle
if handle_access(way,result,data) == false then return end
-- check high occupancy vehicle restrictions
if handle_hov(way,result) == false then return end
-- check whether we're using a special transport mode
if handle_ferries(way,result) == false then return end
if handle_movables(way,result) == false then return end
-- handle service road restrictions
if handle_service(way,result) == false then return end
-- check whether forward/backward directons are routable
if handle_oneway(way,result) == false then return end
-- compute speed taking into account way type, maxspeed tags, etc.
if handle_speed(way,result,data) == false then return end
-- handle turn lanes and road classification, used for guidance
if handle_turn_lanes(way,result) == false then return end
if handle_classification(way,result) == false then return end
-- handle various other flags
if handle_roundabouts(way,result) == false then return end
if handle_startpoint(way,result) == false then return end
if handle_restricted(way,result,data) == false then return end
-- handle roundabout flags
if handle_roundabouts(way,result) == false then return end
-- check if this way can be routed through, but not used as
-- origin or destination
if handle_restricted(way,result,data) == false then return end
-- set name, ref and pronunciation
if handle_names(way,result) == false then return end
end
function turn_function (angle)
+102
View File
@@ -0,0 +1,102 @@
-- Enable calling our lua profile code directly from the lua command line,
-- which makes it easier to debug.
-- We simulate the normal C++ environment by defining the required globals and functions.
-- Usage:
-- > cd profiles
-- > lua5.1 debug.lua
-- for more convenient printing of tables
local pprint = require('lib/pprint')
-- globals that are normally set from C++
-- profiles code modifies this table
properties = {}
-- should match values defined in include/extractor/guidance/road_classification.hpp
road_priority_class = {
motorway = 0,
trunk = 2,
primary = 4,
secondary = 6,
tertiary = 8,
main_residential = 10,
side_residential = 11,
link_road = 14,
bike_path = 16,
foot_path = 18,
connectivity = 31,
}
-- should match values defined in include/extractor/travel_mode.hpp
mode = {
inaccessible = 0,
driving = 1,
cycling = 2,
walking = 3,
ferry = 4,
train = 5,
pushing_bike = 6,
}
-- input tags, normally extracted from OSM data
local way = {
highway = 'motorway',
name = 'Main Street',
--width = '3',
--maxspeed = '30',
--['maxspeed:advisory'] = '25',
--oneway = '-1',
--service = 'alley',
--['oneway:bicycle'] = 'yes',
--junction = 'roundabout',
--['name:pronunciation'] = 'fuerloong',
--route = 'ferry',
--duration = '00:01:00',
--hov = 'designated',
--access = 'no'
--destination = 'Berlin',
["destination:ref"] = 'Nuremberg',
--["destination:ref:forward"] = 'Hamburg;Dresden',
}
-- tag function normally provided via C++
function way:get_value_by_key(k)
return self[k]
end
-- Mock C++ helper functions which are called from LUA.
-- FIXME
-- Debugging LUA code that uses these will not work correctly
-- unless we reimplement themethods in LUA.
function durationIsValid(str)
return true
end
function parseDuration(str)
return 1
end
function canonicalizeStringList(str)
return str
end
-- start state of result table, normally set form C++
local result = {
road_classification = {},
forward_speed = -1,
backward_speed = -1,
}
-- the profile we want to debug
require("car")
-- call the way function
way_function(way,result)
-- and print the output
pprint(way)
print("=>")
pprint(result)
+4 -1
View File
@@ -156,10 +156,13 @@ function way_function (way, result)
result.ref = ref
end
-- roundabouts
-- roundabouts
if "roundabout" == junction then
result.roundabout = true
end
if "circular" == junction then
result.circular = true
end
-- speed
if route_speeds[route] then
+2 -2
View File
@@ -5,11 +5,11 @@ local Access = {}
function Access.find_access_tag(source,access_tags_hierarchy)
for i,v in ipairs(access_tags_hierarchy) do
local tag = source:get_value_by_key(v)
if tag and tag ~= '' then
if tag then
return tag
end
end
return ""
return nil
end
return Access
+21 -46
View File
@@ -1,53 +1,28 @@
local Destination = {}
function Destination.get_directional_tag(way, is_forward, tag)
local v
if is_forward then
v = way:get_value_by_key(tag .. ':forward') or way:get_value_by_key(tag)
else
v = way:get_value_by_key(tag .. ':backward') or way:get_value_by_key(tag)
end
if v then
return v.gsub(v, ';', ', ')
end
end
-- Assemble destination as: "A59: Düsseldorf, Köln"
-- destination:ref ^ ^ destination
function Destination.get_destination(way, is_forward)
local destination = way:get_value_by_key("destination")
local destination_forward = way:get_value_by_key("destination:forward")
local destination_backward = way:get_value_by_key("destination:backward")
local destination_ref = way:get_value_by_key("destination:ref")
local destination_ref_forward = way:get_value_by_key("destination:ref:forward")
local destination_ref_backward = way:get_value_by_key("destination:ref:backward")
-- Assemble destination as: "A59: Düsseldorf, Köln"
-- destination:ref ^ ^ destination
local rv = ""
if destination_ref then
if is_forward == true and destination_ref == "" then
if destination_ref_forward then
destination_ref = destination_ref_forward
end
elseif is_forward == false then
if destination_ref_backward then
destination_ref = destination_ref_backward
end
end
rv = rv .. string.gsub(destination_ref, ";", ", ")
ref = Destination.get_directional_tag(way, is_forward, 'destination:ref')
dest = Destination.get_directional_tag(way, is_forward, 'destination')
if ref and dest then
return ref .. ': ' .. dest
else
return ref or dest or ''
end
if destination then
if is_forward == true and destination == "" then
if destination_forward then
destination = destination_forward
end
elseif is_forward == false then
if destination_backward then
destination = destination_backward
end
end
if destination ~= "" then
if rv ~= "" then
rv = rv .. ": "
end
rv = rv .. string.gsub(destination, ";", ", ")
end
end
return rv
end
return Destination
+8 -8
View File
@@ -61,7 +61,7 @@ function Guidance.set_classification (highway, result, input_way)
end
local lane_count = input_way:get_value_by_key("lanes")
if lane_count and lane_count ~= "" then
if lane_count then
local lc = tonumber(lane_count)
if lc ~= nil then
result.road_classification.num_lanes = lc
@@ -69,14 +69,14 @@ function Guidance.set_classification (highway, result, input_way)
else
local total_count = 0
local forward_count = input_way:get_value_by_key("lanes:forward")
if forward_count and forward_count ~= "" then
if forward_count then
local fc = tonumber(forward_count)
if fc ~= nil then
total_count = fc
end
end
local backward_count = input_way:get_value_by_key("lanes:backward")
if backward_count and backward_count ~= "" then
if backward_count then
local bc = tonumber(backward_count)
if bc ~= nil then
total_count = total_count + bc
@@ -96,19 +96,19 @@ local function get_psv_counts(way)
local fw = 0;
local bw = 0;
if psv and psv ~= "" then
if psv then
fw = tonumber(psv)
if( fw == nil ) then
fw = 0
end
end
if psv_forward and psv_forward ~= "" then
if psv_forward then
fw = tonumber(psv_forward)
if( fw == nil ) then
fw = 0
end
end
if psv_backward and psv_backward ~= "" then
if psv_backward then
bw = tonumber(psv_backward);
if( bw == nil ) then
bw = 0
@@ -119,8 +119,8 @@ end
-- trims lane string with regard to supported lanes
local function process_lanes(turn_lane,vehicle_lane,first_count,second_count)
if turn_lane and turn_lane ~= "" then
if vehicle_lane and vehicle_lane ~= "" then
if turn_lane then
if vehicle_lane then
turn_lane = applyAccessTokens(turn_lane,vehicle_lane)
elseif first_count ~= 0 or second_count ~= 0 then
turn_lane = trimLaneString(turn_lane, first_count, second_count)
+457
View File
@@ -0,0 +1,457 @@
-- Easy way to print data structes
-- From https://github.com/jagt/pprint.lua, file is license as pubic domain
local pprint = { VERSION = '0.1' }
pprint.defaults = {
-- type display trigger, hide not useful datatypes by default
-- custom types are treated as table
show_nil = true,
show_boolean = true,
show_number = true,
show_string = true,
show_table = true,
show_function = false,
show_thread = false,
show_userdata = false,
-- additional display trigger
show_metatable = false, -- show metatable
show_all = false, -- override other show settings and show everything
use_tostring = false, -- use __tostring to print table if available
filter_function = nil, -- called like callback(value[,key, parent]), return truty value to hide
object_cache = 'local', -- cache blob and table to give it a id, 'local' cache per print, 'global' cache
-- per process, falsy value to disable (might cause infinite loop)
-- format settings
indent_size = 2, -- indent for each nested table level
level_width = 80, -- max width per indent level
wrap_string = true, -- wrap string when it's longer than level_width
wrap_array = false, -- wrap every array elements
sort_keys = true, -- sort table keys
}
local TYPES = {
['nil'] = 1, ['boolean'] = 2, ['number'] = 3, ['string'] = 4,
['table'] = 5, ['function'] = 6, ['thread'] = 7, ['userdata'] = 8
}
-- seems this is the only way to escape these, as lua don't know how to map char '\a' to 'a'
local ESCAPE_MAP = {
['\a'] = '\\a', ['\b'] = '\\b', ['\f'] = '\\f', ['\n'] = '\\n', ['\r'] = '\\r',
['\t'] = '\\t', ['\v'] = '\\v', ['\\'] = '\\\\',
}
-- generic utilities
local function escape(s)
s = s:gsub('([%c\\])', ESCAPE_MAP)
local dq = s:find('"')
local sq = s:find("'")
if dq and sq then
return s:gsub('"', '\\"'), '"'
elseif sq then
return s, '"'
else
return s, "'"
end
end
local function is_plain_key(key)
return type(key) == 'string' and key:match('^[%a_][%a%d_]*$')
end
local CACHE_TYPES = {
['table'] = true, ['function'] = true, ['thread'] = true, ['userdata'] = true
}
-- cache would be populated to be like:
-- {
-- function = { `fun1` = 1, _cnt = 1 }, -- object id
-- table = { `table1` = 1, `table2` = 2, _cnt = 2 },
-- visited_tables = { `table1` = 7, `table2` = 8 }, -- visit count
-- }
-- use weakrefs to avoid accidentall adding refcount
local function cache_apperance(obj, cache, option)
if not cache.visited_tables then
cache.visited_tables = setmetatable({}, {__mode = 'k'})
end
local t = type(obj)
-- TODO can't test filter_function here as we don't have the ix and key,
-- might cause different results?
-- respect show_xxx and filter_function to be consistent with print results
if (not TYPES[t] and not option.show_table)
or (TYPES[t] and not option['show_'..t]) then
return
end
if CACHE_TYPES[t] or TYPES[t] == nil then
if not cache[t] then
cache[t] = setmetatable({}, {__mode = 'k'})
cache[t]._cnt = 0
end
if not cache[t][obj] then
cache[t]._cnt = cache[t]._cnt + 1
cache[t][obj] = cache[t]._cnt
end
end
if t == 'table' or TYPES[t] == nil then
if cache.visited_tables[obj] == false then
-- already printed, no need to mark this and its children anymore
return
elseif cache.visited_tables[obj] == nil then
cache.visited_tables[obj] = 1
else
-- visited already, increment and continue
cache.visited_tables[obj] = cache.visited_tables[obj] + 1
return
end
for k, v in pairs(obj) do
cache_apperance(k, cache, option)
cache_apperance(v, cache, option)
end
local mt = getmetatable(obj)
if mt and option.show_metatable then
cache_apperance(mt, cache, option)
end
end
end
-- makes 'foo2' < 'foo100000'. string.sub makes substring anyway, no need to use index based method
local function str_natural_cmp(lhs, rhs)
while #lhs > 0 and #rhs > 0 do
local lmid, lend = lhs:find('%d+')
local rmid, rend = rhs:find('%d+')
if not (lmid and rmid) then return lhs < rhs end
local lsub = lhs:sub(1, lmid-1)
local rsub = rhs:sub(1, rmid-1)
if lsub ~= rsub then
return lsub < rsub
end
local lnum = tonumber(lhs:sub(lmid, lend))
local rnum = tonumber(rhs:sub(rmid, rend))
if lnum ~= rnum then
return lnum < rnum
end
lhs = lhs:sub(lend+1)
rhs = rhs:sub(rend+1)
end
return lhs < rhs
end
local function cmp(lhs, rhs)
local tleft = type(lhs)
local tright = type(rhs)
if tleft == 'number' and tright == 'number' then return lhs < rhs end
if tleft == 'string' and tright == 'string' then return str_natural_cmp(lhs, rhs) end
if tleft == tright then return str_natural_cmp(tostring(lhs), tostring(rhs)) end
-- allow custom types
local oleft = TYPES[tleft] or 9
local oright = TYPES[tright] or 9
return oleft < oright
end
-- setup option with default
local function make_option(option)
if option == nil then
option = {}
end
for k, v in pairs(pprint.defaults) do
if option[k] == nil then
option[k] = v
end
if option.show_all then
for t, _ in pairs(TYPES) do
option['show_'..t] = true
end
option.show_metatable = true
end
end
return option
end
-- override defaults and take effects for all following calls
function pprint.setup(option)
pprint.defaults = make_option(option)
end
-- format lua object into a string
function pprint.pformat(obj, option, printer)
option = make_option(option)
local buf = {}
local function default_printer(s)
table.insert(buf, s)
end
printer = printer or default_printer
local cache
if option.object_cache == 'global' then
-- steal the cache into a local var so it's not visible from _G or anywhere
-- still can't avoid user explicitly referentce pprint._cache but it shouldn't happen anyway
cache = pprint._cache or {}
pprint._cache = nil
elseif option.object_cache == 'local' then
cache = {}
end
local last = '' -- used for look back and remove trailing comma
local status = {
indent = '', -- current indent
len = 0, -- current line length
}
local wrapped_printer = function(s)
printer(last)
last = s
end
local function _indent(d)
status.indent = string.rep(' ', d + #(status.indent))
end
local function _n(d)
wrapped_printer('\n')
wrapped_printer(status.indent)
if d then
_indent(d)
end
status.len = 0
return true -- used to close bracket correctly
end
local function _p(s, nowrap)
status.len = status.len + #s
if not nowrap and status.len > option.level_width then
_n()
wrapped_printer(s)
status.len = #s
else
wrapped_printer(s)
end
end
local formatter = {}
local function format(v)
local f = formatter[type(v)]
f = f or formatter.table -- allow patched type()
if option.filter_function and option.filter_function(v, nil, nil) then
return ''
else
return f(v)
end
end
local function tostring_formatter(v)
return tostring(v)
end
local function number_formatter(n)
return n == math.huge and '[[math.huge]]' or tostring(n)
end
local function nop_formatter(v)
return ''
end
local function make_fixed_formatter(t, has_cache)
if has_cache then
return function (v)
return string.format('[[%s %d]]', t, cache[t][v])
end
else
return function (v)
return '[['..t..']]'
end
end
end
local function string_formatter(s, force_long_quote)
local s, quote = escape(s)
local quote_len = force_long_quote and 4 or 2
if quote_len + #s + status.len > option.level_width then
_n()
-- only wrap string when is longer than level_width
if option.wrap_string and #s + quote_len > option.level_width then
-- keep the quotes together
_p('[[')
while #s + status.len >= option.level_width do
local seg = option.level_width - status.len
_p(string.sub(s, 1, seg), true)
_n()
s = string.sub(s, seg+1)
end
_p(s) -- print the remaining parts
return ']]'
end
end
return force_long_quote and '[['..s..']]' or quote..s..quote
end
local function table_formatter(t)
if option.use_tostring then
local mt = getmetatable(t)
if mt and mt.__tostring then
return string_formatter(tostring(t), true)
end
end
local print_header_ix = nil
local ttype = type(t)
if option.object_cache then
local cache_state = cache.visited_tables[t]
local tix = cache[ttype][t]
-- FIXME should really handle `cache_state == nil`
-- as user might add things through filter_function
if cache_state == false then
-- already printed, just print the the number
return string_formatter(string.format('%s %d', ttype, tix), true)
elseif cache_state > 1 then
-- appeared more than once, print table header with number
print_header_ix = tix
cache.visited_tables[t] = false
else
-- appeared exactly once, print like a normal table
end
end
local tlen = #t
local wrapped = false
_p('{')
_indent(option.indent_size)
_p(string.rep(' ', option.indent_size - 1))
if print_header_ix then
_p(string.format('--[[%s %d]] ', ttype, print_header_ix))
end
for ix = 1,tlen do
local v = t[ix]
if formatter[type(v)] == nop_formatter or
(option.filter_function and option.filter_function(v, ix, t)) then
-- pass
else
if option.wrap_array then
wrapped = _n()
end
_p(format(v)..', ')
end
end
-- hashmap part of the table, in contrast to array part
local function is_hash_key(k)
local numkey = tonumber(k)
if numkey ~= k or numkey > tlen then
return true
end
end
local function print_kv(k, v, t)
-- can't use option.show_x as obj may contain custom type
if formatter[type(v)] == nop_formatter or
formatter[type(k)] == nop_formatter or
(option.filter_function and option.filter_function(v, k, t)) then
return
end
wrapped = _n()
if is_plain_key(k) then
_p(k, true)
else
_p('[')
-- [[]] type string in key is illegal, needs to add spaces inbetween
local k = format(k)
if string.match(k, '%[%[') then
_p(' '..k..' ', true)
else
_p(k, true)
end
_p(']')
end
_p(' = ', true)
_p(format(v), true)
_p(',', true)
end
if option.sort_keys then
local keys = {}
for k, _ in pairs(t) do
if is_hash_key(k) then
table.insert(keys, k)
end
end
table.sort(keys, cmp)
for _, k in ipairs(keys) do
print_kv(k, t[k], t)
end
else
for k, v in pairs(t) do
if is_hash_key(k) then
print_kv(k, v, t)
end
end
end
if option.show_metatable then
local mt = getmetatable(t)
if mt then
print_kv('__metatable', mt, t)
end
end
_indent(-option.indent_size)
-- make { } into {}
last = string.gsub(last, '^ +$', '')
-- peek last to remove trailing comma
last = string.gsub(last, ',%s*$', ' ')
if wrapped then
_n()
end
_p('}')
return ''
end
-- set formatters
formatter['nil'] = option.show_nil and tostring_formatter or nop_formatter
formatter['boolean'] = option.show_boolean and tostring_formatter or nop_formatter
formatter['number'] = option.show_number and number_formatter or nop_formatter -- need to handle math.huge
formatter['function'] = option.show_function and make_fixed_formatter('function', option.object_cache) or nop_formatter
formatter['thread'] = option.show_thread and make_fixed_formatter('thread', option.object_cache) or nop_formatter
formatter['userdata'] = option.show_userdata and make_fixed_formatter('userdata', option.object_cache) or nop_formatter
formatter['string'] = option.show_string and string_formatter or nop_formatter
formatter['table'] = option.show_table and table_formatter or nop_formatter
if option.object_cache then
-- needs to visit the table before start printing
cache_apperance(obj, cache, option)
end
_p(format(obj))
printer(last) -- close the buffered one
-- put cache back if global
if option.object_cache == 'global' then
pprint._cache = cache
end
return table.concat(buf)
end
-- pprint all the arguments
function pprint.pprint( ... )
local args = {...}
-- select will get an accurate count of array len, counting trailing nils
local len = select('#', ...)
for ix = 1,len do
pprint.pformat(args[ix], nil, io.write)
io.write('\n')
end
end
setmetatable(pprint, {
__call = function (_, ...)
pprint.pprint(...)
end
})
return pprint
+10
View File
@@ -0,0 +1,10 @@
-- Sequence of items
-- Ordered, but have to loop through items to check for inclusion.
-- Currently the same as a table.
function Sequence(source)
return source
end
return Sequence
+23
View File
@@ -0,0 +1,23 @@
-- Set of items
-- Fast check for inclusion, but unordered.
--
-- Instead of having to do:
-- whitelist = { 'apple'=true, 'cherries'=true, 'melons'=true }
--
-- you can do:
-- whitelist = Set { 'apple', 'cherries', 'melons' }
--
-- and then use it as:
-- print( whitelist['cherries'] ) => true
function Set(source)
set = {}
if source then
for i,v in ipairs(source) do
set[v] = true
end
end
return set
end
return Set
+97
View File
@@ -0,0 +1,97 @@
-- Enable calling our lua profile code directly from the lua command line,
-- which makes it easier to debug.
-- We simulate the normal C++ environment by defining the required globals and functions.
-- Usage:
-- > cd profiles
-- > lua5.1 debug.lua
-- for more convenient printing of tables
local pprint = require('lib/pprint')
-- globals that are normally set from C++
-- profiles code modifies this table
properties = {}
-- should match values defined in include/extractor/guidance/road_classification.hpp
road_priority_class = {
motorway = 0,
trunk = 2,
primary = 4,
secondary = 6,
tertiary = 8,
main_residential = 10,
side_residential = 11,
link_road = 14,
bike_path = 16,
foot_path = 18,
connectivity = 31,
}
-- should match values defined in include/extractor/travel_mode.hpp
mode = {
inaccessible = 0,
driving = 1,
cycling = 2,
walking = 3,
ferry = 4,
train = 5,
pushing_bike = 6,
}
-- input tags, normally extracted from OSM data
local way = {
highway = 'primary',
name = 'Main Street',
--width = '3',
--maxspeed = '30',
--['maxspeed:advisory'] = '25',
--oneway = '-1',
--service = 'alley',
--['oneway:bicycle'] = 'yes',
--junction = 'roundabout',
--['name:pronunciation'] = 'fuerloong',
--route = 'ferry',
--duration = '00:01:00',
--hov = 'designated',
--access = 'no'
}
-- tag function normally provided via C++
function way:get_value_by_key(k)
return self[k]
end
-- Mock C++ helper functions which are called from LUA.
-- FIXME
-- Debugging LUA code that uses these will not work correctly
-- unless we reimplement themethods in LUA.
function durationIsValid(str)
return true
end
function parseDuration(str)
return 1
end
function canonicalizeStringList(str)
return str
end
-- start state of result table, normally set form C++
local result = {
road_classification = {},
forward_speed = -1,
backward_speed = -1,
}
-- the profile we want to debug
require("car")
-- call the way function
for i=0,10000,1
do
way_function(way,result)
end
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
set -e -u
if [ ! -f docs/http.md ] ; then
echo "This script should be run from the repository root directory"
exit 1
fi
# Check that the required tools are in the PATH somewhere.
# If executed via `npm run build-api-docs`, then node_modules/.bin is in the PATH
# and these tools should be found
babel -V >/dev/null 2>&1 || { echo >&2 "Can't find babel. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
browserify --help >/dev/null 2>&1 || { echo >&2 "Can't find browserify. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
uglifyjs -V >/dev/null 2>&1 || { echo >&2 "Can't find uglifyjs. Add node_modules/.bin to your path, or run via \"npm run\""; exit 1; }
# Clean up previous version
rm -rf build/docs
# Make temp dir to hold docbox template
mkdir -p build/docs/tmp/src
# Copy docbox template scripts into temp dir
cp -r node_modules/docbox/src/* build/docs/tmp/src
cp -r node_modules/docbox/css build/docs/
# Copy our images/templates into the temp docs dir
cp -r docs/images build/docs
cp docs/src/index.html build/docs/tmp
cp docs/src/* build/docs/tmp/src/custom
mkdir -p build/docs/tmp/content
cp docs/*.md build/docs/tmp/content
# Now, run the scripts to generate the actual final product
pushd build/docs/tmp
NODE_ENV=production browserify src/index.js | uglifyjs -c -m > ../bundle.js
babel src --out-dir lib
node lib/render.js ../index.html
popd
# Cleanup
rm -rf build/docs/tmp
+94
View File
@@ -0,0 +1,94 @@
#!/usr/bin/env node
'use strict'
var crypto = require('crypto');
var fs = require('fs');
var idx = process.argv.indexOf('-c');
if (idx > -1) {
var validate_file = process.argv[idx+1];
if (!process.argv[idx+1]) {
console.error('Please pass arg to -c with a path to the data.md5sum file used to validate');
process.exit(1);
}
validate(validate_file);
} else {
// we are generating checksums for all filenames passed
var args = process.argv.slice(2);
if (args.length > 0) {
generate(args);
} else {
console.error('Please pass either a list of files to generate an md5sum for or validate with "-c data.md5sum"');
process.exit(1);
}
}
function md5FileSync (filename) {
var BUFFER_SIZE = 8192;
var fd = fs.openSync(filename, 'r');
var hash = crypto.createHash('md5');
var buffer = new Buffer(BUFFER_SIZE);
try {
var bytesRead;
do {
bytesRead = fs.readSync(fd, buffer, 0, BUFFER_SIZE);
hash.update(buffer.slice(0, bytesRead));
} while (bytesRead === BUFFER_SIZE)
} finally {
fs.closeSync(fd);
}
return hash.digest('hex');
}
function generate(files) {
files.forEach(function(filename) {
var md5_actual = md5FileSync(filename);
console.log(md5_actual,'',filename);
})
}
function validate(validate_file) {
var sums = {};
var lines = fs.readFileSync(validate_file).
toString().
split('\n').
filter(function(line) {
return line !== "";
});
var error = 0;
lines.forEach(function(line) {
var parts = line.split(' ');
var filename = parts[1];
var md5 = parts[0];
sums[filename] = md5;
var md5_actual = md5FileSync(filename);
if (md5_actual !== md5) {
error++;
console.error(filename + ': FAILED')
} else {
console.log(filename + ': OK');
}
})
if (error > 0) {
console.error('ms5sum.js WARNING: 1 computed checksum did NOT match');
console.error('\nExpected:')
lines.forEach(function(line) {
var parts = line.split(' ');
var filename = parts[1];
var md5 = parts[0];
console.log(md5 + ' ' + filename);
})
process.exit(1);
} else {
process.exit(0);
}
}

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