Compare commits

..

294 Commits

Author SHA1 Message Date
Patrick Niklaus 6fadc4d8b8 Enable travis 2017-06-19 16:03:36 +00:00
Patrick Niklaus 00230967af Change OSRM version to 5.8.0 2017-06-19 16:03:15 +00:00
Patrick Niklaus f4bf76c98e Refactor tile tests 2017-06-19 16:00:34 +00:00
Daniel Patterson 1142a9e49b Add layer to debug tiles to expose all OSM nodes in that area. 2017-06-19 16:00:25 +00:00
Patrick Niklaus b168eca6d5 Bump version 2017-06-15 16:10:37 +00:00
Daniel Patterson e3276324b9 Include 'rate' property (reciprocal of weight) on debug tile edges. (#4162)
Include 'rate' property (reciprocal of weight) on debug tile edges and add turn weight data to debug tiles.
2017-06-15 17:50:57 +02:00
Moritz Kobitzsch f80e5db346 add support for visualising turn penalties in MLD Debug tiles (#4157)
- template function for tile functionality with edge finder operator
 - refactors unit tests into single function (reduce code duplication)
 - adds unit tests for core-ch
2017-06-15 13:59:44 +02:00
Daniel Patterson 35550d8c0a Parallelize generation of the edge-expanded-edges. 2017-06-15 09:05:45 +00:00
Daniel J. Hofmann b68d79407e Takes fn by forwarding ref. in for_each_pair, resolves #4148 2017-06-14 15:17:26 +00:00
Patrick Niklaus 27ed69b08f Parallize scripting on osmium::Buffer granularity
Fixes #3447 and reduces parsing time by about 15%.
2017-06-13 21:47:54 +00:00
Daniel Patterson cd8fb82215 Add flag to allow skipping calling node function for nodes with no tags. 2017-06-13 12:23:00 +00:00
Daniel Patterson 5c8e2b6f78 Don't copy the node/way/segment/turn function objects for every call. 12-13% speedup for lua processing right there. 2017-06-13 12:23:00 +00:00
Stepan Kuzmin 9d30817294 add tests for the gaps and tidy map matching flags #4145 2017-06-12 11:32:06 +00:00
Stepan Kuzmin 5ee3c4de9f Expose Map Matching gaps and tidy parameters in Node.js bindings #4021 2017-06-12 11:32:06 +00:00
Michael Krasnyk afbcb3d38c Don't filter out MLD tests 2017-06-10 11:05:57 +00:00
Daniel J. Hofmann de1d5f199f Uses correct coefficients for local optimality in CH alternatives
The alpha constant is for the local optimality T-Test threshold.

Before we used epsilon for the T-Test threshold, but the epsilon
constant is meant to be used for the stretch test(s) only.

This changeset fixes the local optimality T-Test and uses the
epsilon constant for the two stretch tests:
- We test the stretch for the total route against epsilon and
- We test the detour against the epsilon now, too

We can discuss if the second stretch test should actually use
epsilon, too, or a adapted value of it - but definitly not alpha.
2017-06-09 13:20:41 +02:00
Michael Krasnyk 9158f69ea0 Failing test for alternative path 2017-06-09 13:20:41 +02:00
Daniel J. Hofmann 2cfd9c8d01 Adds npm5 lockfile 2017-06-08 21:58:09 +00:00
Daniel Patterson 5026741652 Make initialization fail with a specific exception if the dataset isn't compatible with the algorithm being used, rather than crashing when a query occurs. 2017-06-08 18:31:51 +00:00
Daniel Patterson 3d77714c36 Make most command-line tools return useful error codes on well-known exceptions. 2017-06-08 15:03:24 +00:00
Michael Krasnyk 03e83ec6a0 Fix invalid roundabout instructions for different driving modes, #4129 2017-06-08 15:01:27 +00:00
Michael Krasnyk 9315dc1c73 Test for a roundabout with footway exits, #4129 2017-06-08 15:01:27 +00:00
Patrick Niklaus b8bb12b2e2 Merge pull request #4134 from gojuno/polyline_input
Polyline6 support for the http REST API
2017-06-08 12:05:49 +00:00
Lev Dragunov bd1532847c Changelog entry 2017-06-07 21:46:19 +03:00
Lev Dragunov 3602b58517 Review fixes 2017-06-07 21:43:49 +03:00
Lev Dragunov d7035291ea clang-format 2017-06-07 15:39:08 +03:00
Lev Dragunov 6b0bcb5171 Docs and tests 2017-06-07 15:24:00 +03:00
Lev Dragunov 6b8f3c7fef Polyline6 support in the REST input 2017-06-06 19:51:00 +03:00
Patrick Niklaus 0d12d2fd28 Merge pull request #4094 from Project-OSRM/refactor/rapidash
Replace timezone shapefile parsing with geojson parsing
2017-06-02 20:01:04 +00:00
Patrick Niklaus 10460fc2fb Fix PR comments 2017-06-02 18:46:21 +00:00
Patrick Niklaus 6c7f0edf50 Don't use manual extract commands in weight tests 2017-06-02 18:12:13 +00:00
Patrick Niklaus 51bf9c4ff2 Small fixes for osrm-runner 2017-06-02 18:12:13 +00:00
Patrick Niklaus 0266c9d969 Renumber nodes after running osrm-partition
The new numbering uses the partition information
to sort border nodes first to compactify storages
that need access indexed by border node ID.

We also get an optimized cache performance for free
sincr we can also recursively sort the nodes by cell ID.

This implements issue #3779.
2017-06-02 18:12:13 +00:00
Michael Krasnyk 879de346ea Add timezone names customization in tests 2017-06-02 17:35:18 +02:00
Michael Krasnyk 50d9c4b34a Add local time support for windows 2017-06-02 17:35:18 +02:00
Patrick Niklaus a195d7dfd3 Remove compiler errors and use 32bit for segment_index 2017-06-02 12:15:06 +00:00
Daniel Patterson 1c3cb897c1 Refactor RTree so that .fileIndex only contains EdgeDataT, and all r-tree structure is in the .ramIndex file.
Also tunes the BRANCHING_FACTOR a bit to speed up access with this new layout.
2017-06-02 12:15:06 +00:00
karenzshea 0e39320a77 do not run conditional cuke tests by default 2017-06-02 11:15:34 +02:00
karenzshea 1b162c1962 remove rapidjson gtest dep 2017-06-02 10:26:39 +02:00
karenzshea f497201322 add check that restrictions are off when not found in timezone polygons 2017-06-02 10:00:07 +02:00
karenzshea 65746edd2d deps and lint 2017-06-02 10:00:07 +02:00
karenzshea 91e1ac83d9 add london geojson fixture 2017-06-02 10:00:07 +02:00
karenzshea 63ea75612b by default restrictions are off if timezone is not found 2017-06-02 10:00:07 +02:00
Michael Krasnyk f9a650792a Fix updating conditional turn restrictions 2017-06-02 10:00:07 +02:00
karenzshea 564a29141e add testing geojson files 2017-06-02 10:00:07 +02:00
karenzshea c937d20e48 unit tests for geojson validation 2017-06-02 10:00:07 +02:00
karenzshea ca353eb7db refactor timezoner a bit for unit tests, add initial unit tests 2017-06-02 10:00:07 +02:00
karenzshea f268163ea0 remove shapefile dependency from build 2017-06-02 10:00:07 +02:00
karenzshea 6f41e3faf1 fixes to get compiling 2017-06-02 10:00:07 +02:00
karenzshea aed2c0124a rapidjson steppin in 2017-06-02 10:00:07 +02:00
Michael Krasnyk f5564c9275 Merge commit '632ce270fa23d00e969877e983da6bc7cbaf1458' as 'third_party/rapidjson' 2017-06-02 09:35:53 +02:00
Michael Krasnyk 632ce270fa Squashed 'third_party/rapidjson/' content from commit f54b0e47a
git-subtree-dir: third_party/rapidjson
git-subtree-split: f54b0e47a08782a6131cc3d60f94d038fa6e0a51
2017-06-02 09:35:53 +02:00
karenzshea 93dac6b246 vendoring rapidjson, header only library 2017-06-02 09:35:30 +02:00
Moritz Kobitzsch a92674022a make all u-turns continue 2017-06-01 12:39:10 +02:00
Moritz Kobitzsch ceaf065d0e don't collapse highway ramps into uturns (#4074) 2017-06-01 12:39:10 +02:00
Michael Krasnyk a58139dfb5 Terminate earlier if mason fails to install clang++ on travis 2017-06-01 10:26:11 +00:00
Moritz Kobitzsch 9bd2b0deaa fix invalid turn angle in forks 2017-06-01 11:43:18 +02:00
Michael Krasnyk d262c4dfaa [skip ci] Add comments about order of post-processing calls 2017-06-01 11:13:31 +02:00
Michael Krasnyk dd009322de Remove roundabout skip as no leavesRoundabout steps after postProcess 2017-06-01 11:13:31 +02:00
Michael Krasnyk 858ec2e655 Fix steps collapsing after non-closed roundabouts, #4100 2017-06-01 11:13:31 +02:00
Michael Krasnyk 5d4ab4100a Test for collapsing sliproads after crossing a roundabout, #4100 2017-06-01 11:13:31 +02:00
FILLAU Jean-Maxime 43ddc63d67 Adds documentations on 'approaches' parameter.
Adds changelog
Adds doc/http.md doc
Adds doc/nodejs/api.md doc

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-31 15:02:55 +00:00
Daniel J. Hofmann b5d1565dec Let's Travis check that for yarn lockfile and package.json sync
See https://yarnpkg.com/lang/en/docs/cli/check/
2017-05-31 14:40:31 +02:00
Daniel J. Hofmann 6658bb7d51 Runs yarn upgrade to sync yarn lockfile 2017-05-31 14:40:31 +02:00
Daniel J. Hofmann eb2db4994f Updates NAN for Node.js bindings 2017-05-31 14:40:31 +02:00
Daniel J. Hofmann d88e5ddf20 Uses node-cmake's CMake module directly, resolves #3912
No need for vendoring.
2017-05-31 14:40:31 +02:00
Daniel J. Hofmann f3558260b6 Splits turn penalty tests into bicycle and testbot domain, resolves #4067 2017-05-31 10:47:43 +02:00
Daniel J. Hofmann 0317bbb35d Splits via tests into car and testbot domain, resolves #4061 2017-05-30 16:38:51 +02:00
Daniel J. Hofmann a4a6ed7e38 Puts approach test into car domain 2017-05-30 16:37:05 +02:00
FILLAU Jean-Maxime 15a1e10487 Add nodejs binding test
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 98ad9d8b61 Refactoring enum Approach in enum class.
Suppress "engine::"

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime c573cdb0ae Use formating script.
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 82a149eb87 Propagating approach parameter to every phantom nodes search function.
Propagating approach parameter for plugins :
 - tabler
 - nearest
 - trip

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 089c98a107 Adding support for left left hand driving.
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 17a73e3979 Add NodeJS API for Approaches param.
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime f65299d665 Rename side API
Side -> Approach
 - DEFAULT -> CURB
 - BOTH -> UNRESTRICTED
 - remove OPPOSITE param

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime f782dfbfd9 Add uturn test case in cucumber for sides param.
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime ec7934ea33 Change qi::lit for qi::symbols for the sides parameter parser.
Refactor code :
 - Suppress StartSide Enum
 - Change Side Structure for Enum

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 2de17f3fd0 Adding url unit test for "sides" parameters
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime ba2bf4f78e Adding cucumber file test "side_param_feature" for the side parameter.
- test on normal segment
 - test on oneway segment

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 8a54e6a0ec Adding "sides" params for the sides option tests into java script
Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
FILLAU Jean-Maxime 8e70c87e64 New "sides" setting in base parameters for phantom nodes.
- Adding sides parameter into base parameters, it can take the values SIDE, OPPOSITE or DEFAULT.
 - Adding url parser for "sides" parameter, url values are "s" for SIDE, "o" for OPPOSITE and "d" for DEFAULT, example : "sides=s;s".
 - Checking parameters, if "sides" parameter is used, the number of parameter is the same as number of location.
 - Create a phantom to start at side driving or Opposite side driving.

Signed-off-by: FILLAU Jean-Maxime <jean-maxime.fillau@mapotempo.com>
2017-05-30 10:19:41 +00:00
Patrick Niklaus 579a1ed42e Don't copy the object on WriteOne 2017-05-29 15:09:36 +00:00
Patrick Niklaus a544935e7d Fix unit-test 2017-05-29 15:09:36 +00:00
Daniel Patterson 7eab227ab1 Use FileWriter for better error handling when writing name data. 2017-05-29 15:09:36 +00:00
Daniel Patterson 382a5cebab Use FileWriter for writing LeafNode data to improve error handling. 2017-05-29 15:09:36 +00:00
Johan Uhle 6d2353c302 Allow docker image with assertions (#4016) 2017-05-29 12:08:44 +02:00
Lev Dragunov 45ee096260 Ignore split breakage fix. 2017-05-26 10:55:03 +00:00
Daniel Patterson c21a476b00 Overridden virtual function should be marked as override final. 2017-05-26 09:15:34 +00:00
Daniel Patterson 25c870dc57 Unused padding doesn't need to be named, removing name silences compiler warnings. 2017-05-26 09:15:34 +00:00
Daniel Patterson 4605c35101 Mark NodeJS headers as system includes to suppress compiler warnings. 2017-05-26 09:15:34 +00:00
Daniel Patterson 8655c61ec2 Remove variable name for unused parameters to silence compiler warnings. 2017-05-26 09:15:34 +00:00
Michael Krasnyk 314cf3f31a Add a comment line about counting 2017-05-23 18:27:47 +00:00
Michael Krasnyk 1d26deb0be Allow counting of service exits on service roundabouts, see #4075 2017-05-23 18:27:47 +00:00
Michael Krasnyk ac35757616 [skip ci] Adjust CHANGELOG and the test description 2017-05-23 14:35:23 +02:00
Michael Krasnyk 47f2f17987 Change order of guidance post-processing, fix #4030 2017-05-23 14:35:23 +02:00
Michael Krasnyk a63b43c259 Place reverse entering_via_edge in the front of intersection_view 2017-05-22 09:33:59 +00:00
Michael Krasnyk 14582fea5f Added example for roundabout overlapping 2017-05-22 09:33:59 +00:00
Daniel J. Hofmann 862ec14e06 Asserts Valid Iterators in Roundabout Exit Invalidation, see #4024 2017-05-22 09:33:59 +00:00
Daniel Patterson 570d81c6dd Bypass boost::numeric_cast checks for coordinate values that have already been validated (#4059)
(i.e. stuff that's stored in our datafiles).  Keep those checks for user-supplied values
(i.e. coordinates coming from files during preprocessing, or coordinates supplied by users
 during requests)
2017-05-19 10:52:44 -07:00
Michael Krasnyk 4964d0dcbd Adjust expectation and remove non-valid assertions 2017-05-19 09:47:47 +00:00
Patrick Niklaus 5c00fc9769 Disable weight update factor test, see issue #4065 2017-05-19 08:25:03 +00:00
Patrick Niklaus 3599d1db8e Switch code to use packed vector for segment weights/durations 2017-05-19 08:25:03 +00:00
Michael Krasnyk 5c61f00ffa Add testbot profile to zero-speed-updates.feature 2017-05-19 09:00:23 +02:00
Daniel Patterson aef3ff3e7b Use correct node-loading code in rtree benchmark. (#4064) 2017-05-18 13:29:50 -07:00
Daniel J. Hofmann a971c2ef37 Applies max turn weight for turns onto restricted weights: no need for custom penalty 2017-05-18 16:33:50 +00:00
Daniel J. Hofmann c757f70b97 Prevents possible overflow in applying a turn penalty onto restricted roads 2017-05-18 16:33:50 +00:00
Daniel J. Hofmann 403db7cc84 Lets MakeResponse(Route) explicitly call MakeResponse(ManyRoutes) in Route API
https://github.com/Project-OSRM/osrm-backend/pull/4035#discussion_r116890340
2017-05-18 10:54:32 +02:00
Michael Krasnyk 7a4c5a64fa Simplify angleBetween to avoid cancellation losses 2017-05-17 15:52:11 +00:00
Michael Krasnyk c535e74a65 Added test to check bearing::angleBetween precision 2017-05-17 15:52:11 +00:00
Michael Krasnyk e605917083 Changed some assert to OSRM_ASSERT 2017-05-17 15:52:11 +00:00
Michael Krasnyk 14db5f8d1f Fix OSRM_ASSERT_MSG compilation fail in Release mode 2017-05-17 15:52:11 +00:00
Michael Krasnyk 3546abc30e Added ChangeLog entry 2017-05-17 15:21:51 +00:00
Michael Krasnyk e4b58c1258 Reverted connection of forward and backward nodes in one SCC 2017-05-17 15:21:51 +00:00
Michael Krasnyk 5e2e1d4c96 Renamed EdgeBasedNode to EdgeBasedNodeSegment 2017-05-17 15:21:51 +00:00
Michael Krasnyk 1a7cd785f2 Rename .nodes -> .nbg_nodes and .nodes_data -> .ebg_nodes 2017-05-17 15:21:51 +00:00
Michael Krasnyk 65de940882 Change EdgeBasedNodeDataExternalContainer to EdgeBasedNodeDataContainer 2017-05-17 15:21:51 +00:00
Michael Krasnyk 26702920b4 Move ComponentID to EdgeBasedNodeDataContainer 2017-05-17 15:21:51 +00:00
Michael Krasnyk 373087d74f Initialize unused bits in PhantomNode 2017-05-17 15:21:51 +00:00
Michael Krasnyk ca6b1b39b7 Remove data duplicates in .node file 2017-05-17 15:21:51 +00:00
Michael Krasnyk 8934167e76 Merge part of .nodes fields into .nodes_data 2017-05-17 15:21:51 +00:00
Daniel J. Hofmann 9972b5f1f9 Removes unused PUBLISH_NODE_BINDINGS var from .travis.yml 2017-05-16 16:23:24 +00:00
Patrick Niklaus d8877abf26 Fix weight value for alley 2017-05-16 16:19:17 +00:00
Patrick Niklaus bce3b68281 Add regression test 2017-05-16 16:19:17 +00:00
Patrick Niklaus 7d42e18479 Fix bicycle turn penalties 2017-05-16 16:19:17 +00:00
Mateusz Loskot 4294295242 Mark way_function properties as mandatory
Format values and function names as code (refines #4040)
2017-05-16 15:17:57 +00:00
Frederik Ramm 16f492026a remove penalty_table from car.lua
remove penalty_table as it is apparently not used anywhere.
2017-05-16 10:40:21 +00:00
Mateusz Loskot 7d58f0ec53 Document default values of global properties set in profile 2017-05-16 10:39:51 +00:00
Patrick Niklaus 6bd724fe24 Rewrite packed vector to also allow random access
This fixes issues #3952. The new approach pre-computes masks for fast
access. Since elements can potentially span multiple words we need masks
and offsets for each upper and lower word.

Due to a bug in the C++14 standart the mask computation is not
recognized as constexpr, but would work on C++17.
2017-05-16 10:25:29 +00:00
Patrick Niklaus 26a208529e [skip ci] Fix alternatives_count documentation 2017-05-15 17:02:41 +00:00
Patrick Niklaus 3fbdb19956 Bump cucumber timeout of gcc-6 with coverage 2017-05-15 12:23:07 +00:00
Patrick Niklaus ea9d5eca0f Update yarn.lock 2017-05-15 12:23:07 +00:00
Patrick Niklaus 0f66278532 Disbale doc builds again 2017-05-15 12:23:07 +00:00
Patrick Niklaus b9206ef017 Upgrade docbox 2017-05-15 12:23:07 +00:00
Patrick Niklaus 9d8f1d9dbf Try documentation 4.0.0 JS RC1 2017-05-15 12:23:07 +00:00
Daniel J. Hofmann e064a9334b Lifts restriction to only provide zero or one alternative routes 2017-05-12 13:54:22 +02:00
Daniel J. Hofmann e12c7756d9 Weight-ifies alternatives related code-paths 2017-05-12 13:54:22 +02:00
Moritz Kobitzsch f8002480c2 fix continue_straight interaction with bearing specification 2017-05-12 13:38:04 +02:00
Karen Shea 799a677e7a Conditional turn restriction support (#3841)
* optionally include condition and via node coords in InputRestrictionContainer

* only write conditionals to disk, custom serialization for restrictions

* conditional turn lookup, reuse timezone validation from
extract-conditionals

* adapt updater to use coordinates/osm ids, remove internal to external map

* add utc time now parameter to contraction

* only compile timezone code where libshp is found, adapt test running

* slight refactor, more tests

* catch invalid via nodes in restriction parsing, set default cucumber
origin to guinée

* add another run to test mld routed paths

* cosmetic review changes

* Simplify Timezoner for windows build

* Split declaration and parsing parts for opening hours

* adjust conditional tests to run without shapefiles

* always include parse conditionals option

* Adjust travis timeout

* Added dummy TZ shapefile with test timezone polygons

* [skip ci] update changelog
2017-05-11 12:13:52 +02:00
Michael Krasnyk 12f47708cd Adjust method and function names 2017-05-11 09:13:42 +00:00
Michael Krasnyk 9358aa1128 Disable nodes with invalid segments 2017-05-11 09:13:42 +00:00
Michael Krasnyk a44b63fbb9 Add response codes of trip and routability queries 2017-05-11 09:13:42 +00:00
Mateusz Łoskot e2b7e8a4da Refactor osrm-extract and osrm-contract to use osrm lib interface
Simplifies implementation of the tools slightly.
Ensures osrm::extract and osrm::contract keep working.

Follows up PR #3787
2017-05-10 21:35:42 +00:00
Michael Krasnyk a5bfcd876f Add response code to test result values 2017-05-09 16:58:23 +00:00
Patrick Niklaus 2f02384d22 Disbale boost::interprocess condition variables on Linux to fix issue #3911 2017-05-08 09:15:01 +00:00
Michael Krasnyk 3de8613843 Added test with an empty CSV file 2017-05-05 22:15:05 +00:00
Michael Krasnyk ccb8a07dc7 Hide qi namespace alias 2017-05-05 22:15:05 +00:00
Michael Krasnyk 6484fed190 Remove generate-edge-lookup argument in feature tests 2017-05-05 22:15:05 +00:00
Michael Krasnyk 6b103c6d0b Add zero file size check 2017-05-05 22:15:05 +00:00
Michael Krasnyk 669ac058b8 Print diagnostic information to avoid boost cryptic errors 2017-05-05 22:15:05 +00:00
Michael Krasnyk e92967167f Use mapped_file_source for CSV files 2017-05-05 22:15:05 +00:00
Patrick Niklaus f3de2c9b94 For the cyclability profile add alley penalties 2017-05-05 17:06:50 +00:00
Patrick Niklaus 21cd1a44e8 Add failing test case for alleys 2017-05-05 17:06:50 +00:00
Johan Uhle 6ca46795aa Fix gitsha output in dockerfile (#4014) 2017-05-05 15:55:48 +02:00
Patrick Niklaus 35d7b7ceaf Regenerate docs 2017-05-05 08:51:36 +00:00
Patrick Niklaus faa2094488 Fix docs for radius 2017-05-05 08:51:36 +00:00
Patrick Niklaus e6d776699f Fix overloaded parameter docs 2017-05-05 08:51:36 +00:00
Patrick Niklaus 200e90ad43 Disable TOC 2017-05-05 08:51:36 +00:00
Michael Krasnyk c66f67ac07 Updated assertions to catch negative duration values for weights > 0
but still clamping negative duration values at 0 without checking weights
2017-05-04 21:03:45 +00:00
Michael Krasnyk 334a7b50cd Use rectified linear unit to prevent negative duration values 2017-05-04 21:03:45 +00:00
Michael Krasnyk a9d3e61884 Fix minor review comments 2017-05-03 21:59:38 +00:00
Michael Krasnyk 88082c48cf Remove GetEdgeBasedNodeID from TurnDataContainer 2017-05-03 21:59:38 +00:00
Michael Krasnyk 40d0297885 Added unpacked_nodes vector to annotatePath interface 2017-05-03 21:59:38 +00:00
Michael Krasnyk be1acae20c Use edge_id as index in ebg_node_data_container 2017-05-03 21:59:38 +00:00
Michael Krasnyk f1e4349c82 Move geometry ids, name_ids and travel_modes to EdgeBasedNodeData 2017-05-03 21:59:38 +00:00
Michael Krasnyk 1f701341db Move reserve call before pushing weights 2017-05-03 21:59:38 +00:00
Patrick Niklaus 2a24468267 Regenerate API docs 2017-05-03 15:23:03 +00:00
Patrick Niklaus f531a956f5 Update nodejs docs to document the constructor better 2017-05-03 15:23:03 +00:00
Patrick Niklaus 1aea10010b Run the docs in CI again 2017-05-02 16:57:23 +00:00
Patrick Niklaus 2cf6010665 Split travis jobs 2017-05-02 16:57:23 +00:00
Michael Krasnyk 2402d60429 Adjusted to PR comments 2017-05-02 16:55:03 +00:00
Michael Krasnyk 19494984eb Fix incorrect exit turn invalidation 2017-05-02 16:55:03 +00:00
Michael Krasnyk 07c7cb3c6c Rename BinaryHeap to QueryHeap 2017-05-02 15:54:25 +00:00
Michael Krasnyk 358aebec4d Decrease memory footprint of HeapHandle from 32 to 24 bytes 2017-05-02 15:54:25 +00:00
Michael Krasnyk 05826150f6 Use boost::heap::d_ary_heap 2017-05-02 15:54:25 +00:00
Michael Krasnyk 5827358a1e node.js script to run random osrm queries 2017-05-02 15:54:25 +00:00
Daniel J. Hofmann 9334cc463d Fixes Table not checking for valid phantom nodes
We failed to check if we could actually find phantom nodes for all
coordinates in the table plugin, leading to corrupt internal state.

```
curl 'http://localhost:5000/table/v1/car/7.4151,43.7305;7.4222,43.7368?radiuses=0;'
```

```
[assert][140505627227904] /tmp/osrm-backend/include/engine/routing_algorithms/routing_base.hpp:68
in: void osrm::engine::routing_algorithms::insertNodesInHeap(osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>::ManyToManyQueryHeap&, const osrm::engine::PhantomNode&) [with bool DIRECTION = false; osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>::ManyToManyQueryHeap = osrm::util::BinaryHeap<unsigned int, unsigned int, int, osrm::engine::ManyToManyHeapData, osrm::util::UnorderedMapStorage<unsigned int, int> >]: phantom_node.IsValid()
terminate called without an active exception
```
2017-05-02 13:41:33 +02:00
Daniel J. Hofmann 5532ee627f Fixes util.format calls in Cucumber support code 2017-05-02 12:52:10 +02:00
Freenerd 2021c30805 Save gitsha for later use in docker container 2017-05-02 09:36:09 +00:00
Patrick Niklaus 0e39aa9488 Address PR comments 2017-04-24 16:04:41 +00:00
Patrick Niklaus 8ec0745883 Add benchmark 2017-04-24 16:04:41 +00:00
Patrick Niklaus c446b017ef Switch from macro based StrongTypedef to template version 2017-04-24 16:04:41 +00:00
Patrick Niklaus a68435d856 Move clip functions to lambda 2017-04-20 14:58:26 +00:00
Patrick Niklaus 814324146b signed -> unsigned 2017-04-20 14:58:26 +00:00
Patrick Niklaus 11d8b2ba5a Add clipping for 20 bits to SegmentWeight/SegmentDuration 2017-04-20 14:58:26 +00:00
Patrick Niklaus d6c6a262d8 Use 16bit for SegmentWeight and SegmentDuration 2017-04-20 14:58:26 +00:00
Patrick Niklaus 5c4f96e4bc Fix checking columns if route is not specified 2017-04-20 13:52:13 +00:00
Patrick Niklaus 9974b8b1da Apply traffic light penalty also for non-turns 2017-04-20 13:52:13 +00:00
Michael Krasnyk c81baae1b9 Fix incorrect weight fallback for distance-based weights 2017-04-19 08:28:38 +02:00
Patrick Niklaus e96545be2e Disable is_integral check because it fails for strong-type-def 2017-04-18 17:24:46 +00:00
Patrick Niklaus 609801ae99 Fix PR comments 2017-04-18 17:24:46 +00:00
Patrick Niklaus a66918a303 Make PackedVector generic 2017-04-18 17:24:46 +00:00
Pepijn Schoen e85c4f87e9 Skip fingerprinting .turn_penalties_index, to be done in a separate iteration because of Appveyor issues. 2017-04-18 12:01:06 +00:00
Pepijn Schoen 8ff5a22799 clang-format 2017-04-18 12:01:06 +00:00
Pepijn Schoen 4929d1297e Address PR comments 2017-04-18 12:01:06 +00:00
Pepijn Schoen b830a8f942 Replace Count32 with Count64 2017-04-18 12:01:06 +00:00
Pepijn Schoen 0c388a5264 Fingerprint .turn_penalties_index 2017-04-18 12:01:06 +00:00
Pepijn Schoen e4eb18cf4e Fingerprint .properties 2017-04-18 12:01:06 +00:00
Pepijn Schoen 5b4f432cba Fingerprint .tld 2017-04-18 12:01:06 +00:00
Pepijn Schoen 15f7257645 Fingerprint .turn_duration_penalties and .turn_weight_penalties 2017-04-18 12:01:06 +00:00
Pepijn Schoen 12c11f1d48 Fingerprint .names 2017-04-18 12:01:06 +00:00
Pepijn Schoen a196d5ced3 Fingerprint .timestamp, normalize use of Size / GetSize and make that function Fingerprint-aware 2017-04-18 12:01:06 +00:00
Pepijn Schoen 802af08179 Fingerprint .core 2017-04-18 12:01:06 +00:00
Pepijn Schoen 85ec50552d fingerprint .ramIndex / tree nodes 2017-04-18 12:01:06 +00:00
Pepijn Schoen 8da96f8d94 fingerprint .tld 2017-04-18 12:01:06 +00:00
Pepijn Schoen 5b9d858f57 Fingerprint .edges 2017-04-18 12:01:06 +00:00
Pepijn Schoen 023242ec03 Fingerprint geometries 2017-04-18 12:01:06 +00:00
Pepijn Schoen 683e53e950 Fingerprint .osrm.datasource_names 2017-04-18 12:01:06 +00:00
Pepijn Schoen df0ee955e8 Fingerprint and move .levels 2017-04-18 12:01:06 +00:00
Daniel Patterson 771834793f Only log components in Debug mode, it's very wordy and not really useful (#3948)
for Release builds.

Log component counts at the end of the SCC run.
2017-04-17 16:49:26 -07:00
Michael Krasnyk 3915c1286b Don't remove the last original coordinate during tiding 2017-04-13 21:27:00 +00:00
Patrick Niklaus b422b636d3 Remove boost::make_unique to fix travis node builds 2017-04-13 21:19:09 +00:00
Patrick Niklaus 5bbc675c6b Bump osrm version to 5.8 2017-04-13 21:19:09 +00:00
Patrick Niklaus addf4d90e9 Use .gitignore default instead of .npmignore 2017-04-13 21:19:09 +00:00
Patrick Niklaus 721e5e7947 Restructure travis build 2017-04-13 21:19:09 +00:00
Michael Krasnyk dea3144c4d Use total angle for turn instruction if entry step has large distance 2017-04-12 23:22:44 +00:00
Patrick Niklaus 1080d25fcf Install node version as well 2017-04-12 20:27:32 +00:00
Patrick Niklaus afb553a31e Only use three jobs for node builds 2017-04-12 20:27:32 +00:00
Patrick Niklaus e2c231234d Use nvm instead of travis node_js key
This fixes issues on container builds that would always use
node 6 even when 4 was specified.
2017-04-12 20:27:32 +00:00
Patrick Niklaus 103f7117ed Update changelog 2017-04-12 14:59:26 +00:00
Michael Krasnyk 59b70c4d11 Make CoreCH SearchEngineData inherited from CH one
this allows to keep a single Algorithm template parameter in internal
interfaces as

template <typename Algorithm>
search(SearchEngineData<Algorithm> &,
       const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &, ...)
2017-04-12 10:54:09 +00:00
Michael Krasnyk f96bae40ac Remove unused {forward,reverse}_heap_2 in MLD engine data 2017-04-12 10:54:09 +00:00
Michael Krasnyk ba974c73bf Remove CoreCH heaps 2017-04-12 10:54:09 +00:00
Michael Krasnyk e498ad3ee7 Make explicit fallback to CH heaps in CoreCH algorithms 2017-04-12 10:54:09 +00:00
Michael Krasnyk 1de031ed06 Remove {forward,reverse}_core_heap arguments from search interface 2017-04-12 10:54:09 +00:00
Patrick Niklaus d6ac924b94 Use Date.now() 2017-04-11 22:33:38 +00:00
Patrick Niklaus ee24473cbb Always print node version 2017-04-11 22:33:38 +00:00
Patrick Niklaus c19a3cec1c Fix build syntax 2017-04-11 22:33:38 +00:00
Patrick Niklaus f3694be1a0 Override install and after_sucess 2017-04-11 22:33:38 +00:00
Patrick Niklaus 306d86ce58 Add missing semi-colon 2017-04-11 22:33:38 +00:00
Patrick Niklaus 2c001b63a5 Port timer script to JS 2017-04-11 22:33:38 +00:00
Patrick Niklaus e162dda836 Don't use bc 2017-04-11 22:33:38 +00:00
Patrick Niklaus 10c532bd4c Revert "Skip cucumber tests for publish builds"
This reverts commit 3f8160c156.
2017-04-11 22:33:38 +00:00
Patrick Niklaus c8a7bc1d6a Revert "Don't build unit tests for publishing job"
This reverts commit eb0bd378ae.
2017-04-11 22:33:38 +00:00
Patrick Niklaus 9ca3c69b49 Don't build unit tests for publishing job 2017-04-11 22:33:38 +00:00
Patrick Niklaus d1cf8c1fd5 Skip cucumber tests for publish builds 2017-04-11 22:33:38 +00:00
Patrick Niklaus 018742f50f Constrain the number of jobs on container builds 2017-04-11 22:33:38 +00:00
Patrick Niklaus b82d21f856 Install yarn when not there 2017-04-11 22:33:38 +00:00
Patrick Niklaus cfaadf198f Attempt sudo:false build matrix for node 2017-04-11 22:33:38 +00:00
Michael Krasnyk 6698b5e07e Use fallbacks counter to print a single warning message 2017-04-11 14:55:56 +00:00
Michael Krasnyk 37794a5e8a Change traffic CSV field value from weight to rate
and make the value required.

If the weight name is 'duration' than the rate value
can be computed as speed / 3.6

Issue: https://github.com/Project-OSRM/osrm-backend/issues/3823
2017-04-11 14:55:56 +00:00
Patrick Niklaus a88fef2937 Implement distance pruning for MLD as well 2017-04-10 17:25:55 +00:00
Patrick Niklaus da474a16a9 Fix formating 2017-04-10 17:25:02 +00:00
Patrick Niklaus 59bbfeb67f Buffer turn data on disk to save memory 2017-04-10 17:25:02 +00:00
Patrick Niklaus 4e9e2ed5bd Emit a notification when turning on a ferry and don't merge step 2017-04-07 15:29:53 +00:00
Moritz Kobitzsch e0593c7ca2 add failing test for 3762 2017-04-07 15:29:53 +00:00
Daniel J. Hofmann 1f69df0d89 We need bash for the install script 2017-04-07 14:48:57 +02:00
Patrick Niklaus 05706879a0 Less is more: Don't force any specific build configuration 2017-04-07 14:48:57 +02:00
Patrick Niklaus 7e49b36198 Add script to fall back to source build 2017-04-07 14:48:57 +02:00
Patrick Niklaus 56bcb491d3 Bump package version to latest.6 2017-04-07 10:08:36 +00:00
Patrick Niklaus f4e2bd848d Fixed breaking publishing due to node-cmake upgrade 2017-04-07 08:54:52 +00:00
Daniel J. Hofmann 0cf96314a3 Documents frontend quick start in Readme 2017-04-07 06:56:01 +00:00
Patrick Niklaus 91e24cab9e Bump package version to latest.5 2017-04-06 20:54:24 +00:00
Patrick Niklaus 288155ead0 Fix formating 2017-04-06 15:42:38 +00:00
Patrick Niklaus 85454857d3 Use default move function 2017-04-06 15:42:38 +00:00
Patrick Niklaus fe50f6590a Fix formating 2017-04-06 15:42:38 +00:00
Patrick Niklaus 2da5da3f16 Don't leak ownership in partition/files 2017-04-06 15:42:38 +00:00
Patrick Niklaus 446c865415 Dont leak ownership in extractor::files 2017-04-06 15:42:38 +00:00
Patrick Niklaus 0072bf0c59 Move to forward declare header 2017-04-06 15:42:38 +00:00
Patrick Niklaus 4ec7ca29f1 Fix formating 2017-04-06 15:42:38 +00:00
Patrick Niklaus d94017dfae No shared_memory_wrapper, (De)SerializeVector 2017-04-06 15:42:38 +00:00
Patrick Niklaus dce0ce0e17 Fix readGraph to not use UseSharedMemory 2017-04-06 15:42:38 +00:00
Patrick Niklaus d61102e255 Fix compilation of rtree benchmark 2017-04-06 15:42:38 +00:00
Patrick Niklaus 7f6e0c478b Split QueryNode into coordinates and osm id 2017-04-06 15:42:38 +00:00
Patrick Niklaus 786a3d8919 Read multi level graph to view 2017-04-06 15:42:38 +00:00
Patrick Niklaus ef3fcdc6e6 Refactor graph writing code in contractor 2017-04-06 15:42:38 +00:00
Patrick Niklaus 90c194fc81 Refactor turn description into own file 2017-04-06 15:42:38 +00:00
Patrick Niklaus 5ed686a17b Add generic graph serialization 2017-04-06 15:42:38 +00:00
Patrick Niklaus 4e3009260c Load data directly into CellStorageView 2017-04-06 15:42:38 +00:00
Patrick Niklaus c87ce2dede Load data directly into MLPView 2017-04-06 15:42:38 +00:00
Patrick Niklaus 99a87b4c83 Change serialisation of .geometries file. 2017-04-06 15:42:38 +00:00
Patrick Niklaus 3f5fc1e897 Read segment data directly into shm 2017-04-06 15:42:38 +00:00
Patrick Niklaus 97d1de1beb Pull turn data up into server 2017-04-06 15:42:38 +00:00
Patrick Niklaus d7e1c9c09c Refactor turn data into own class 2017-04-06 15:42:38 +00:00
Patrick Niklaus 865111bca9 Split partition serialization logic 2017-04-06 15:42:38 +00:00
Patrick Niklaus 08d62cd5e3 Separate serialization and files in extractor 2017-04-06 15:42:38 +00:00
Daniel J. Hofmann 603e2ee7de Adapts bindings to node-cmake v2, resolves #3879 2017-04-06 15:26:54 +02:00
Michael Krasnyk 98948989d0 implement MLD map matching 2017-04-06 11:17:23 +00:00
Michael Krasnyk 1aa8cc3b65 make getPathDistance algorithm-independent 2017-04-06 11:17:23 +00:00
Michael Krasnyk c487d1307e enable map matching in MLD 2017-04-06 11:17:23 +00:00
Michael Krasnyk 604f4957f7 correctly fail on unimplemented map matching feature 2017-04-06 11:17:23 +00:00
Michael Krasnyk 7726576bb7 use ADL and explicit instantiation for map matching 2017-04-06 11:17:23 +00:00
Michael Krasnyk cf17a3a4c3 PR review adjustments 2017-04-06 10:36:40 +02:00
Michael Krasnyk 0972ec9115 remove CH-related part of loops forcing 2017-04-06 10:36:40 +02:00
Michael Krasnyk f660ae30dc use explicit instantiation of shortestPathSearch 2017-04-06 10:36:40 +02:00
Michael Krasnyk 2766c24b42 prefer smaller legs for equal weights in shortest path plugin 2017-04-06 10:36:40 +02:00
Michael Krasnyk cab83555e1 add loops forcing to MLD search 2017-04-06 10:36:40 +02:00
Michael Krasnyk 48a098a9c7 implement MLD shortest path plugin 2017-04-06 10:36:40 +02:00
Michael Krasnyk a1fa1c610c enable "via" MLD tests 2017-04-06 10:36:40 +02:00
Michael Krasnyk 905ca69301 add Algorithm parameter to SearchEngineData 2017-04-06 10:36:40 +02:00
Michael Krasnyk d66cc125aa make first heaps algorithm-aware 2017-04-06 10:36:40 +02:00
Michael Krasnyk 3fc0fc65f9 don't disable algorithms explicitly 2017-04-06 10:36:40 +02:00
Michael Krasnyk 8c64b01d67 itroduce ADL via algorithm specific ch, corech and mld namespaces 2017-04-06 10:36:40 +02:00
Michael Krasnyk 2566f64c34 fix unused variable warning 2017-04-06 10:36:40 +02:00
619 changed files with 74556 additions and 8712 deletions
+2
View File
@@ -7,6 +7,8 @@
#############################
osrm-deps
.ycm_extra_conf.py
# Compiled source #
###################
*.com
-10
View File
@@ -1,10 +0,0 @@
*
!README.md
!CHANGELOG.md
!CONTRIBUTING.MD
!LICENCE.TXT
!package.json
!example
!lib/*.js
!profiles/*
!profiles/lib/*
+163 -39
View File
@@ -7,8 +7,9 @@ git:
sudo: required
dist: trusty
nodejs:
node_js:
- "4"
- "6"
notifications:
email: false
@@ -16,6 +17,7 @@ notifications:
branches:
only:
- master
- "5.8"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@@ -36,6 +38,8 @@ env:
- CCACHE_VERSION=3.3.1
- CMAKE_VERSION=3.7.2
- MASON="$(pwd)/scripts/mason.sh"
- ENABLE_NODE_BINDINGS=On
- NODE="4"
matrix:
fast_finish: true
@@ -45,12 +49,42 @@ matrix:
# Debug Builds
- os: linux
compiler: "gcc-6-debug"
compiler: "format-taginfo-docs"
env: NODE=6
sudo: false
before_install:
install:
- source $NVM_DIR/nvm.sh
- nvm install $NODE
- nvm use $NODE
- npm --version
- npm install --ignore-scripts
- npm link --ignore-scripts
script:
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
- ${MASON} install clang-format 3.8.1
- PATH=$(${MASON} prefix clang-format 3.8.1)/bin:${PATH} ./scripts/format.sh && ./scripts/error_on_dirty.sh
# See issue 4043
#- npm run docs && ./scripts/error_on_dirty.sh
after_success:
- os: linux
compiler: "gcc-6-debug-cov"
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']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_COVERAGE=ON ENABLE_SANITIZER=ON
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
after_success:
- bash <(curl -s https://codecov.io/bash)
- os: linux
compiler: "gcc-6-debug-asan"
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']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
- os: linux
compiler: "clang-4.0-debug"
@@ -61,12 +95,12 @@ matrix:
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
compiler: "mason-linux-debug-santize"
compiler: "mason-linux-debug-asan"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON ENABLE_NODE_BINDINGS=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
# Release Builds
- os: linux
@@ -75,7 +109,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
- os: linux
compiler: "gcc-6-release"
@@ -104,6 +138,8 @@ matrix:
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 ENABLE_LTO=ON
after_success:
- ./scripts/travis/publish.sh
# Disabled because of CI slowness
#- os: linux
@@ -132,31 +168,131 @@ matrix:
#- packages: ['clang-4.0', '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-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Node build jobs. These skip running the tests.
- os: linux
sudo: false
compiler: "node-4-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-4-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-6-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-6-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
before_install:
- source $NVM_DIR/nvm.sh
- nvm install $NODE
- nvm use $NODE
- node --version
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
export JOBS=$((`nproc` + 1))
fi
- |
if [ -n "${RUN_CLANG_FORMAT}" ]; then
${MASON} install clang-format 3.8.1 && PATH=$(${MASON} prefix clang-format 3.8.1)/bin:${PATH} ./scripts/format.sh
if [[ -z $JOBS ]]; then
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
export JOBS=$((`nproc` + 1))
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
export JOBS=$((`sysctl -n hw.ncpu` + 1))
fi
fi
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
export JOBS=$((`sysctl -n hw.ncpu` + 1))
sudo mdutil -i off /
fi
- |
if [[ ! -f $(which yarn) ]]; then
npm install -g yarn
fi
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
- echo "Using ${JOBS} jobs"
- yarn install --ignore-scripts
- yarn check --ignore-scripts --integrity
# Bootstrap cmake to be able to run mason
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}.tar.gz"
- CMAKE_DIR="mason_packages/${TRAVIS_OS_NAME}-x86_64/cmake/${CMAKE_VERSION}"
- mkdir -p ${CMAKE_DIR}
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${CMAKE_DIR} || exit 1
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${CMAKE_DIR} || travis_terminate 1
- export PATH=${CMAKE_DIR}/bin:${PATH}
- ${MASON} install tbb 2017_20161128 && export LD_LIBRARY_PATH=$(${MASON} prefix tbb 2017_20161128)/lib/:${LD_LIBRARY_PATH}
- ${MASON} install ccache ${CCACHE_VERSION} && export PATH=$(${MASON} prefix ccache ${CCACHE_VERSION})/bin:${PATH}
@@ -164,24 +300,22 @@ before_install:
if [[ ! -z ${CLANG_VERSION} ]]; then
export CCOMPILER='clang'
export CXXCOMPILER='clang++'
${MASON} install clang++ ${CLANG_VERSION} && export PATH=$(${MASON} prefix clang++ ${CLANG_VERSION})/bin:${PATH}
${MASON} install clang++ ${CLANG_VERSION} && export PATH=$(${MASON} prefix clang++ ${CLANG_VERSION})/bin:${PATH} || travis_terminate 1
# 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
${MASON} install binutils 2.27 && export PATH=$(${MASON} prefix binutils 2.27)/bin:${PATH}
${MASON} install binutils 2.27 && export PATH=$(${MASON} prefix binutils 2.27)/bin:${PATH} || travis_terminate 1
fi
fi
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
- export OSRM_INSTALL_DIR="$(pwd)/install-osrm"
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- mkdir ${OSRM_BUILD_DIR}
install:
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
./scripts/check_taginfo.py taginfo.json profiles/car.lua
fi
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
@@ -191,7 +325,8 @@ install:
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
-DBUILD_TOOLS=ON \
-DENABLE_CCACHE=ON
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- echo "travis_fold:start:MAKE"
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
@@ -201,15 +336,14 @@ install:
- sudo make install
- |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
sudo ldconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${OSRM_INSTALL_DIR}/lib
fi
- popd
- mkdir example/build && pushd example/build
- export PKG_CONFIG_PATH=${OSRM_INSTALL_DIR}/lib/pkgconfig
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
- make --jobs=${JOBS}
- popd
# building docs only works with npm3+ not with yarn or npm2
#- yarn run docs
script:
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
@@ -224,19 +358,9 @@ script:
- ./unit_tests/server-tests
- ./unit_tests/partition-tests
- |
if [ -n "${ENABLE_NODE_BINDINGS}" ] && [ -z "${ENABLE_SANITIZER}" ]; then
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
npm run nodejs-tests
fi
- |
- popd
- yarn test
after_success:
- |
if [ -n "${ENABLE_COVERAGE}" ]; then
bash <(curl -s https://codecov.io/bash)
fi
- |
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
./scripts/travis/publish.sh
fi
+45 -1
View File
@@ -1,17 +1,61 @@
- Track preprocessing flag in the map matching plugin.
# 5.8.0
- Changes from 5.7
- API:
- polyline6 support in request string
- new parameter `approaches` for `route`, `table`, `trip` and `nearest` requests. This parameter keep waypoints on the curb side.
'approaches' accepts both 'curb' and 'unrestricted' values.
Note : the curb side depend on the `ProfileProperties::left_hand_driving`, it's a global property set once by the profile. If you are working with a planet dataset, the api will be wrong in some countries, and right in others.
- NodeJs Bindings
- new parameter `approaches` for `route`, `table`, `trip` and `nearest` requests.
- Tools
- `osrm-partition` now ensures it is called before `osrm-contract` and removes inconsitent .hsgr files automatically.
- Features
- Added conditional restriction support with `parse-conditional-restrictions=true|false` to osrm-extract. This option saves conditional turn restrictions to the .restrictions file for parsing by contract later. Added `parse-conditionals-from-now=utc time stamp` and `--time-zone-file=/path/to/file` to osrm-contract
- Command-line tools (osrm-extract, osrm-contract, osrm-routed, etc) now return error codes and legible error messages for common problem scenarios, rather than ugly C++ crashes
- Speed up pre-processing by only running the Lua `node_function` for nodes that have tags. Cuts OSM file parsing time in half.
- osrm-extract now performs generation of edge-expanded-edges using all available CPUs, which should make osrm-extract significantly faster on multi-CPU machines
- Files
- .osrm.nodes file was renamed to .nbg_nodes and .ebg_nodes was added
- Guidance
- #4075 Changed counting of exits on service roundabouts
- Debug Tiles
- added support for visualising turn penalties to the MLD plugin
- added support for showing the rate (reciprocal of weight) on each edge when used
- added support for turn weights in addition to turn durations in debug tiles
- Bugfixes
- Fixed a copy/paste issue assigning wrong directions in similar turns (left over right)
- #4074: fixed a bug that would announce entering highway ramps as u-turns
- #4122: osrm-routed/libosrm should throw exception when a dataset incompatible with the requested algorithm is loaded
# 5.7.1
- Bugfixes
- #4030 Roundabout edge-case crashes post-processing
# 5.7.0
- Changes from 5.6
- Algorithm:
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
- Allows for fast metric updates in below a minute on continental sized networks (osrm-customize)
- Plugins supported: `match` and `route`
- Quickstart: `osrm-extract data.osm.pbf`, `osrm-partition data.osrm`, `osrm-customize data.osrm`, `osrm-routed --algorithm=MLD data.osrm`
- NodeJs Bindings
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
- `OSRM` object has new option `algorihtm="CH","CoreCH","MLD"`
- Internals
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
- Files
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
- `osrm-extract` creates new file `.osrm.cnbg` and `.cnbg_to_ebg`
- `osrm-partition` creates new file `.osrm.partition` and `.osrm.cells`
- `osrm-customize` creates new file `.osrm.mldgr`
- Profiles
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
- Map Matching:
- new option `gaps=split|ignore` to enable/disbale track splitting
- new option `tidy=true|false` to simplify traces automatically
# 5.6.3
- Changes from 5.6.0
+15 -11
View File
@@ -54,7 +54,7 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 7)
set(OSRM_VERSION_MINOR 8)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
@@ -126,6 +126,7 @@ file(GLOB UpdaterGlob src/updater/*.cpp)
file(GLOB StorageGlob src/storage/*.cpp)
file(GLOB ServerGlob src/server/*.cpp src/server/**/*.cpp)
file(GLOB EngineGlob src/engine/*.cpp src/engine/**/*.cpp)
file(GLOB ErrorcodesGlob src/osrm/errorcodes.cpp)
add_library(UTIL OBJECT ${UtilGlob})
add_library(EXTRACTOR OBJECT ${ExtractorGlob})
@@ -447,10 +448,6 @@ if(ENABLE_MASON)
add_dependency_includes(${MASON_PACKAGE_tbb_INCLUDE_DIRS})
set(TBB_LIBRARIES ${MASON_PACKAGE_tbb_LDFLAGS})
mason_use(libshp2 VERSION ${MASON_LIBSHP_VERSION})
set(LIBSHAPEFILE_INCLUDE_DIR ${MASON_PACKAGE_libshp2_INCLUDE_DIRS})
set(LIBSHAPEFILE_LIBRARY ${MASON_PACKAGE_libshp2_LDFLAGS})
if(NOT MASON_PACKAGE_tbb_LIBRARY_DIRS)
message(FATAL_ERROR "MASON_PACKAGE_tbb_LIBRARY_DIRS is empty, rpath will not work")
endif()
@@ -477,6 +474,8 @@ if(ENABLE_MASON)
# expat and bzip2 are used from mason rather than the system
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include)
else()
find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
@@ -546,6 +545,9 @@ else()
find_package(Osmium REQUIRED COMPONENTS io)
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
endif()
# prefix compilation with ccache by default if available and on clang or gcc
@@ -637,7 +639,8 @@ set(UPDATER_LIBRARIES
${CMAKE_THREAD_LIBS_INIT}
${TBB_LIBRARIES}
${MAYBE_RT_LIBRARY}
${MAYBE_COVERAGE_LIBRARIES})
${MAYBE_COVERAGE_LIBRARIES}
${ZLIB_LIBRARY})
set(CONTRACTOR_LIBRARIES
${BOOST_BASE_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
@@ -665,6 +668,7 @@ set(UTIL_LIBRARIES
${STXXL_LIBRARY}
${TBB_LIBRARIES}
${MAYBE_COVERAGE_LIBRARIES})
# Libraries
target_link_libraries(osrm ${ENGINE_LIBRARIES})
target_link_libraries(osrm_update ${UPDATER_LIBRARIES})
@@ -676,7 +680,7 @@ target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
# BUILD_COMPONENTS
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:UTIL>)
target_link_libraries(osrm-components ${TBB_LIBRARIES} ${BOOST_BASE_LIBRARIES})
target_link_libraries(osrm-components ${TBB_LIBRARIES} ${BOOST_BASE_LIBRARIES} ${UTIL_LIBRARIES})
install(TARGETS osrm-components DESTINATION bin)
if(BUILD_TOOLS)
@@ -686,12 +690,12 @@ if(BUILD_TOOLS)
install(TARGETS osrm-io-benchmark DESTINATION bin)
find_package(Shapefile) # package libshp-dev
find_package(Shapefile)
if(SHAPEFILE_FOUND AND (Boost_VERSION VERSION_GREATER 106000 OR ENABLE_MASON))
add_executable(osrm-extract-conditionals src/tools/extract-conditionals.cpp $<TARGET_OBJECTS:UTIL>)
target_include_directories(osrm-extract-conditionals PRIVATE ${LIBSHAPEFILE_INCLUDE_DIR})
target_link_libraries(osrm-extract-conditionals ${OSMIUM_LIBRARIES} ${BOOST_BASE_LIBRARIES} ${Boost_PROGRAM_OPTIONS_LIBRARY}
${LIBSHAPEFILE_LIBRARY} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARY} ${EXPAT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
${UTIL_LIBRARIES} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARY} ${EXPAT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
install(TARGETS osrm-extract-conditionals DESTINATION bin)
endif()
endif()
@@ -713,8 +717,8 @@ set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
file(GLOB VariantGlob third_party/variant/include/mapbox/*.hpp)
file(GLOB LibraryGlob include/osrm/*.hpp)
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/phantom_node.hpp)
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp include/util/exception.hpp)
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/approach.hpp include/engine/phantom_node.hpp)
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/alias.hpp include/util/exception.hpp)
set(ExtractorHeader include/extractor/extractor.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
set(PartitionerHeader include/partition/partitioner.hpp include/partition/partition_config.hpp)
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
+29 -12
View File
@@ -37,30 +37,47 @@ Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
## Quick Start
The easiest and quickest way to setup your own routing engine backend is to use Docker images we provide.
The easiest and quickest way to setup your own routing engine is to use Docker images we provide.
### Using Docker
We base [our Docker images](https://hub.docker.com/r/osrm/osrm-backend/) on Alpine Linux and make sure they are as lightweight as possible.
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
```
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
```
Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
Make requests against the HTTP server
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
Optionally start a user-friendly frontend on port 9966, and open it up in your browser
docker run -p 9966:9966 osrm/osrm-frontend
xdg-open 'http://127.0.0.1:9966'
In case Docker complains about not being able to connect to the Docker daemon make sure you are in the `docker` group.
```
sudo usermod -aG docker $USER
```
sudo usermod -aG docker $USER
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
We support the following images on Docker Cloud:
Name | Description
-----|------
`latest` | `master` compiled with release flag
`latest-assertions` | `master` compiled with with release flag, assertions enabled and debug symbols
`latest-debug` | `master` compiled with debug flag
`<tag>` | specific tag compiled with release flag
`<tag>-debug` | specific tag compiled with debug flag
### Building from Source
-587
View File
@@ -1,587 +0,0 @@
# Copyright (c) 2015, Colin Taylor
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# FindNodeJS.cmake CMake module vendored from the node-cmake project (v1.2).
# This script uses CMake 3.1+ features
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0)
message(FATAL_ERROR "FindNodeJS.cmake uses CMake 3.1+ features")
endif()
# Force a build type to be set (ignored on config based generators)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
endif()
# Capture module information
set(NodeJS_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
get_filename_component(NodeJS_MODULE_NAME ${NodeJS_MODULE_PATH} NAME)
# Allow users to specify the installed location of the Node.js package
set(NodeJS_ROOT_DIR "" CACHE PATH
"The root directory of the node.js installed package")
# Allow users to specify that downloaded sources should be used
option(NodeJS_DOWNLOAD "Download the required source files" Off)
# Allow users to force downloading of node packages
option(NodeJS_FORCE_DOWNLOAD "Download the source files every time" Off)
# Allow users to force archive extraction
option(NodeJS_FORCE_EXTRACT "Extract the archive every time" Off)
# Make libc++ the default when compiling with clang
option(NodeJS_USE_CLANG_STDLIB "Use libc++ when compiling with clang" On)
if(APPLE)
set(NodeJS_USE_CLANG_STDLIB On CACHE BOOL "" FORCE)
endif()
if(WIN32)
# Allow users to specify that the executable should be downloaded
option(NodeJS_DOWNLOAD_EXECUTABLE
"Download matching executable if available" Off
)
endif()
# Try to find the node.js executable
# The node executable under linux may not be the correct program
find_program(NodeJS_EXECUTABLE
NAMES node
PATHS ${NodeJS_ROOT_DIR}
PATH_SUFFIXES nodejs node
)
set(NodeJS_VALIDATE_EXECUTABLE 1)
if(NodeJS_EXECUTABLE)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} --version
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} -p "process.platform"
OUTPUT_VARIABLE NodeJS_INSTALLED_PLATFORM
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} -p "process.arch"
OUTPUT_VARIABLE NodeJS_INSTALLED_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
# If node isn't the node.js binary, try the nodejs binary
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
find_program(NodeJS_EXECUTABLE
NAMES nodejs
PATHS ${NodeJS_ROOT_DIR}
PATH_SUFFIXES nodejs node
)
set(NodeJS_VALIDATE_EXECUTABLE 1)
if(NodeJS_EXECUTABLE)
execute_process(
COMMAND ${NodeJS_EXECUTABLE} --version
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
message(WARNING "Node.js executable could not be found. \
Set NodeJS_ROOT_DIR to the installed location of the executable or \
install Node.js to its default location.")
endif()
endif()
# Determine if a variant is set in the components
list(APPEND NodeJS_OTHER_COMPONENTS
X64 IA32 ARM WIN32 LINUX DARWIN
)
set(NodeJS_COMPONENTS_CONTAINS_VARIANT False)
foreach(NodeJS_COMPONENT ${NodeJS_FIND_COMPONENTS})
list(FIND NodeJS_OTHER_COMPONENTS ${NodeJS_COMPONENT} NodeJS_OTHER_INDEX)
if(NodeJS_OTHER_INDEX EQUAL -1)
set(NodeJS_COMPONENTS_CONTAINS_VARIANT True)
break()
endif()
endforeach()
# Get the targeted version of Node.js (or one of its derivatives)
if(NOT NodeJS_VERSION)
if(NodeJS_FIND_VERSION)
set(NodeJS_VERSION ${NodeJS_FIND_VERSION})
elseif(NodeJS_INSTALLED_VERSION AND NOT NodeJS_COMPONENTS_CONTAINS_VARIANT)
string(SUBSTRING ${NodeJS_INSTALLED_VERSION} 1 -1 NodeJS_VERSION)
else()
message(FATAL_ERROR "Node.js version is not set. Set the VERSION \
property of the find_package command to the required version of the \
Node.js sources")
endif()
endif()
# Determine the target platform for the compiled module
# Uses several mechanisms in order:
#
# 1. CMake cache (allows overriding on the command line)
# 2. Node architecture when binary is available
# 3. CMake architecture
#
set(NodeJS_PLATFORM "" CACHE STRING "Target node.js platform for module")
if(NOT NodeJS_PLATFORM)
if(NodeJS_EXECUTABLE)
set(NodeJS_PLATFORM ${NodeJS_INSTALLED_PLATFORM})
elseif(WIN32)
set(NodeJS_PLATFORM "win32")
elseif(UNIX)
if(APPLE)
set(NodeJS_PLATFORM "darwin")
else()
set(NodeJS_PLATFORM "linux")
endif()
else()
message(FATAL_ERROR "Node.js platform is not set. Add the platform \
to the find_package components section or set NodeJS_PLATFORM in the \
cache.")
endif()
endif()
# Convenience variables for the platform type
if(NodeJS_PLATFORM STREQUAL "win32")
set(NodeJS_PLATFORM_WIN32 True)
set(NodeJS_PLATFORM_LINUX False)
set(NodeJS_PLATFORM_DARWIN False)
elseif(NodeJS_PLATFORM STREQUAL "linux")
set(NodeJS_PLATFORM_WIN32 False)
set(NodeJS_PLATFORM_LINUX True)
set(NodeJS_PLATFORM_DARWIN False)
elseif(NodeJS_PLATFORM STREQUAL "darwin")
set(NodeJS_PLATFORM_WIN32 False)
set(NodeJS_PLATFORM_LINUX False)
set(NodeJS_PLATFORM_DARWIN True)
endif()
# Determine the target architecture for the compiled module
# Uses several mechanisms in order:
#
# 1. CMake cache (allows overriding on the command line)
# 2. Node architecture when binary is available
# 3. Compiler architecture under MSVC
#
set(NodeJS_ARCH "" CACHE STRING "Target node.js architecture for module")
if(NOT NodeJS_ARCH)
if(NodeJS_EXECUTABLE)
set(NodeJS_ARCH ${NodeJS_INSTALLED_ARCH})
elseif(MSVC)
if(CMAKE_CL_64)
set(NodeJS_ARCH "x64")
else()
set(NodeJS_ARCH "ia32")
endif()
else()
message(FATAL_ERROR "Node.js architecture is not set. Add the \
architecture to the find_package components section or set NodeJS_ARCH \
in the cache.")
endif()
endif()
# Convenience variables for the architecture
if(NodeJS_ARCH STREQUAL "x64")
set(NodeJS_ARCH_X64 True)
set(NodeJS_ARCH_IA32 False)
set(NodeJS_ARCH_ARM False)
elseif(NodeJS_ARCH STREQUAL "ia32")
set(NodeJS_ARCH_X64 False)
set(NodeJS_ARCH_IA32 True)
set(NodeJS_ARCH_ARM False)
elseif(NodeJS_ARCH STREQUAL "arm")
set(NodeJS_ARCH_X64 False)
set(NodeJS_ARCH_IA32 False)
set(NodeJS_ARCH_ARM True)
endif()
# Include helper functions
include(util/NodeJSUtil)
# Default variant name
# Used by the installed header comparison below
set(NodeJS_DEFAULT_VARIANT_NAME "node.js")
# Variables for Node.js artifacts across variants
# Specify all of these variables for each new variant
set(NodeJS_VARIANT_NAME "") # The printable name of the variant
set(NodeJS_VARIANT_BASE "") # A file name safe version of the variant
set(NodeJS_URL "") # The URL for the artifacts
set(NodeJS_SOURCE_PATH "") # The URL path of the source archive
set(NodeJS_CHECKSUM_PATH "") # The URL path of the checksum file
set(NodeJS_CHECKSUM_TYPE "") # The checksum type (algorithm)
set(NodeJS_WIN32_LIBRARY_PATH "") # The URL path of the windows library
set(NodeJS_WIN32_BINARY_PATH "") # The URL path of the windows executable
set(NodeJS_WIN32_LIBRARY_NAME "") # The name of the windows library
set(NodeJS_WIN32_BINARY_NAME "") # The name of the windows executable
set(NodeJS_DEFAULT_INCLUDE True) # Enable default include behavior
set(NodeJS_DEFAULT_LIBS True) # Include the default libraries
set(NodeJS_HAS_WIN32_PREFIX True) # Does the variant use library prefixes
set(NodeJS_HAS_WIN32_BINARY True) # Does the variant have win32 executables
set(NodeJS_HAS_OPENSSL True) # Does the variant include openssl headers
set(NodeJS_HEADER_VERSION 0.12.7) # Version after header-only archives start
set(NodeJS_SHA256_VERSION 0.7.0) # Version after sha256 checksums start
set(NodeJS_PREFIX_VERSION 0.12.7) # Version after windows prefixing starts
set(NodeJS_CXX11R_VERSION 0.12.7) # Version after c++11 is required
set(NodeJS_SOURCE_INCLUDE True) # Use the include paths from a source archive
set(NodeJS_HEADER_INCLUDE False) # Use the include paths from a header archive
set(NodeJS_INCLUDE_PATHS "") # Set of header dirs inside the source archive
set(NodeJS_LIBRARIES "") # The set of libraries to link with addon
set(NodeJS_WIN32_DELAYLOAD "") # Set of executables to delayload on windows
# NodeJS variants
# Selects download target based on configured component
# Include NodeJS last to provide default configurations when omitted
file(
GLOB NodeJS_SUPPORTED_VARIANTS
RELATIVE ${CMAKE_CURRENT_LIST_DIR}/variants
${CMAKE_CURRENT_LIST_DIR}/variants/*
)
foreach(NodeJS_SUPPORTED_VARIANT ${NodeJS_SUPPORTED_VARIANTS})
get_filename_component(NodeJS_SUPPORTED_VARIANT_NAME
${NodeJS_SUPPORTED_VARIANT} NAME_WE
)
if(NOT NodeJS_SUPPORTED_VARIANT_NAME STREQUAL "NodeJS")
include(variants/${NodeJS_SUPPORTED_VARIANT_NAME})
endif()
endforeach()
include(variants/NodeJS)
# Populate version variables, including version components
set(NodeJS_VERSION_STRING "v${NodeJS_VERSION}")
# Populate the remaining version variables
string(REPLACE "." ";" NodeJS_VERSION_PARTS ${NodeJS_VERSION})
list(GET NodeJS_VERSION_PARTS 0 NodeJS_VERSION_MAJOR)
list(GET NodeJS_VERSION_PARTS 1 NodeJS_VERSION_MINOR)
list(GET NodeJS_VERSION_PARTS 2 NodeJS_VERSION_PATCH)
# If the version we're looking for is the version that is installed,
# try finding the required headers. Don't do this under windows (where
# headers are not part of the installed content), when the user has
# specified that headers should be downloaded or when using a variant other
# than the default
if((NOT NodeJS_PLATFORM_WIN32) AND (NOT NodeJS_DOWNLOAD) AND
NodeJS_VARIANT_NAME STREQUAL NodeJS_DEFAULT_VARIANT_NAME AND
NodeJS_INSTALLED_VERSION STREQUAL NodeJS_VERSION_STRING AND
NodeJS_INSTALLED_PLATFORM STREQUAL NodeJS_PLATFORM AND
NodeJS_INSTALLED_ARCH STREQUAL NodeJS_ARCH)
# node.h is really generic and too easy for cmake to find the wrong
# file, so use the directory as a guard, and then just tack it on to
# the actual path
#
# Specifically ran into this under OSX, where python contains a node.h
# that gets found instead
find_path(NodeJS_INCLUDE_PARENT node/node.h)
set(NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_PARENT}/node)
# Under all systems that support this, there are no libraries required
# for linking (symbols are resolved via the main executable at runtime)
set(NodeJS_LIBRARIES "")
# Otherwise, headers and required libraries must be downloaded to the project
# to supplement what is installed
else()
# Create a folder for downloaded artifacts
set(NodeJS_DOWNLOAD_PATH
${CMAKE_CURRENT_BINARY_DIR}/${NodeJS_VARIANT_BASE}
)
set(NodeJS_DOWNLOAD_PATH ${NodeJS_DOWNLOAD_PATH}-${NodeJS_VERSION_STRING})
file(MAKE_DIRECTORY ${NodeJS_DOWNLOAD_PATH})
# Download the checksum file for validating all other downloads
# Conveniently, if this doesn't download correctly, the setup fails
# due to checksum failures
set(NodeJS_CHECKSUM_FILE ${NodeJS_DOWNLOAD_PATH}/CHECKSUM)
nodejs_download(
${NodeJS_URL}/${NodeJS_CHECKSUM_PATH}
${NodeJS_CHECKSUM_FILE}
${NodeJS_FORCE_DOWNLOAD}
)
file(READ ${NodeJS_CHECKSUM_FILE} NodeJS_CHECKSUM_DATA)
# Download and extract the main source archive
set(NodeJS_SOURCE_FILE ${NodeJS_DOWNLOAD_PATH}/headers.tar.gz)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_SOURCE_PATH} NodeJS_SOURCE_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_SOURCE_PATH}
${NodeJS_SOURCE_FILE}
${NodeJS_SOURCE_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
set(NodeJS_HEADER_PATH ${NodeJS_DOWNLOAD_PATH}/src)
nodejs_extract(
${NodeJS_SOURCE_FILE}
${NodeJS_HEADER_PATH}
${NodeJS_FORCE_EXTRACT}
)
# Populate include directories from the extracted source archive
foreach(NodeJS_HEADER_BASE ${NodeJS_INCLUDE_PATHS})
set(NodeJS_INCLUDE_DIR ${NodeJS_HEADER_PATH}/${NodeJS_HEADER_BASE})
if(NOT EXISTS ${NodeJS_INCLUDE_DIR})
message(FATAL_ERROR "Include does not exist: ${NodeJS_INCLUDE_DIR}")
endif()
list(APPEND NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_DIR})
endforeach()
# Download required library files when targeting windows
if(NodeJS_PLATFORM_WIN32)
# Download the windows library
set(NodeJS_WIN32_LIBRARY_FILE
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
)
set(NodeJS_WIN32_LIBRARY_FILE
${NodeJS_WIN32_LIBRARY_FILE}/${NodeJS_WIN32_LIBRARY_NAME}
)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_LIBRARY_PATH}
NodeJS_WIN32_LIBRARY_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_WIN32_LIBRARY_PATH}
${NodeJS_WIN32_LIBRARY_FILE}
${NodeJS_WIN32_LIBRARY_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
list(APPEND NodeJS_LIBRARIES ${NodeJS_WIN32_LIBRARY_FILE})
# If provided, download the windows executable
if(NodeJS_WIN32_BINARY_PATH AND
NodeJS_DOWNLOAD_EXECUTABLE)
set(NodeJS_WIN32_BINARY_FILE
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
)
set(NodeJS_WIN32_BINARY_FILE
${NodeJS_WIN32_BINARY_FILE}/${NodeJS_WIN32_BINARY_NAME}
)
nodejs_checksum(
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_BINARY_PATH}
NodeJS_WIN32_BINARY_CHECKSUM
)
nodejs_download(
${NodeJS_URL}/${NodeJS_WIN32_BINARY_PATH}
${NodeJS_WIN32_BINARY_FILE}
${NodeJS_WIN32_BINARY_CHECKSUM}
${NodeJS_CHECKSUM_TYPE}
${NodeJS_FORCE_DOWNLOAD}
)
endif()
endif()
endif()
# Support windows delay loading
if(NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_LINK_FLAGS /IGNORE:4199)
set(NodeJS_WIN32_DELAYLOAD_CONDITION "")
foreach(NodeJS_WIN32_DELAYLOAD_BINARY ${NodeJS_WIN32_DELAYLOAD})
list(APPEND NodeJS_LINK_FLAGS
/DELAYLOAD:${NodeJS_WIN32_DELAYLOAD_BINARY}
)
list(APPEND NodeJS_WIN32_DELAYLOAD_CONDITION
"_stricmp(info->szDll, \"${NodeJS_WIN32_DELAYLOAD_BINARY}\") != 0"
)
endforeach()
string(REPLACE ";" " &&\n "
NodeJS_WIN32_DELAYLOAD_CONDITION
"${NodeJS_WIN32_DELAYLOAD_CONDITION}"
)
configure_file(
${NodeJS_MODULE_PATH}/src/win_delay_load_hook.c
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c @ONLY
)
list(APPEND NodeJS_ADDITIONAL_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c
)
endif()
# Allow undefined symbols on OSX
if(NodeJS_PLATFORM_DARWIN)
list(APPEND NodeJS_LINK_FLAGS "-undefined dynamic_lookup")
endif()
# Use libc++ when clang is the compiler by default
if(NodeJS_USE_CLANG_STDLIB AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*")
list(APPEND NodeJS_COMPILE_OPTIONS -stdlib=libc++)
endif()
# Require c++11 support after a specific point, but only if the user hasn't
# specified an override
if(NOT NodeJS_CXX_STANDARD)
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION)
set(NodeJS_CXX_STANDARD 11)
else()
set(NodeJS_CXX_STANDARD 98)
endif()
endif()
# Set required definitions
list(APPEND NodeJS_DEFINITIONS BUILDING_NODE_EXTENSION)
if(NodeJS_PLATFORM_DARWIN)
list(APPEND NodeJS_DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
endif()
if(NOT NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_DEFINITIONS
_LARGEFILE_SOURCE
_FILE_OFFSET_BITS=64
)
endif()
function(add_nodejs_module NAME)
# Build a shared library for the module
add_library(${NAME} SHARED ${ARGN} ${NodeJS_ADDITIONAL_SOURCES})
# Include required headers
# Find and include Nan as well (always available as its a
# dependency of this module)
nodejs_find_module_fallback(nan ${CMAKE_CURRENT_SOURCE_DIR} NAN_PATH)
target_include_directories(${NAME}
PUBLIC ${NodeJS_INCLUDE_DIRS}
PUBLIC ${NAN_PATH}
)
# Set module properties
# This ensures proper naming of the module library across all platforms
get_target_property(COMPILE_OPTIONS ${NAME} COMPILE_OPTIONS)
if(NOT COMPILE_OPTIONS)
set(COMPILE_OPTIONS "")
endif()
set(COMPILE_OPTIONS ${COMPILE_OPTIONS} ${NodeJS_COMPILE_OPTIONS})
get_target_property(LINK_FLAGS ${NAME} LINK_FLAGS)
if(NOT LINK_FLAGS)
set(LINK_FLAGS "")
endif()
foreach(NodeJS_LINK_FLAG ${NodeJS_LINK_FLAGS})
set(LINK_FLAGS "${LINK_FLAGS} ${NodeJS_LINK_FLAG}")
endforeach()
set_target_properties(${NAME} PROPERTIES
PREFIX ""
SUFFIX ".node"
MACOSX_RPATH ON
POSITION_INDEPENDENT_CODE TRUE
COMPILE_OPTIONS "${COMPILE_OPTIONS}"
LINK_FLAGS "${LINK_FLAGS}"
CXX_STANDARD_REQUIRED TRUE
CXX_STANDARD ${NodeJS_CXX_STANDARD}
)
# Output the module in a per build type directory
# This makes builds consistent with visual studio and other generators
# that build by configuration
if(NOT CMAKE_CONFIGURATION_TYPES)
set_property(TARGET ${NAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BUILD_TYPE}
)
endif()
# Set any required complier flags
# Mostly used under windows
target_compile_definitions(${NAME} PRIVATE ${NodeJS_DEFINITIONS})
# Link against required NodeJS libraries
target_link_libraries(${NAME} ${NodeJS_LIBRARIES})
endfunction()
# Write out the configuration for node scripts
configure_file(
${NodeJS_MODULE_PATH}/build.json.in
${CMAKE_CURRENT_BINARY_DIR}/build.json @ONLY
)
# Make sure we haven't violated the version-to-standard mapping
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION AND
NodeJS_CXX_STANDARD EQUAL 98)
message(FATAL_ERROR "${NodeJS_VARIANT_NAME} ${NodeJS_VERSION} \
requires C++11 or newer to build")
endif()
# This is a find_package file, handle the standard invocation
include(FindPackageHandleStandardArgs)
set(NodeJS_TARGET "${NodeJS_VARIANT_NAME} ${NodeJS_PLATFORM}/${NodeJS_ARCH}")
find_package_handle_standard_args(NodeJS
FOUND_VAR NodeJS_FOUND
REQUIRED_VARS NodeJS_TARGET NodeJS_INCLUDE_DIRS
VERSION_VAR NodeJS_VERSION
)
# Mark variables that users shouldn't modify
mark_as_advanced(
NodeJS_VALIDATE_EXECUTABLE
NodeJS_OTHER_COMPONENTS
NodeJS_COMPONENTS_CONTAINS_VARIANT
NodeJS_COMPONENT
NodeJS_OTHER_INDEX
NodeJS_VERSION_STRING
NodeJS_VERSION_MAJOR
NodeJS_VERSION_MINOR
NodeJS_VERSION_PATCH
NodeJS_VERSION_TWEAK
NodeJS_PLATFORM
NodeJS_PLATFORM_WIN32
NodeJS_PLATFORM_LINUX
NodeJS_PLATFORM_DARWIN
NodeJS_ARCH
NodeJS_ARCH_X64
NodeJS_ARCH_IA32
NodeJS_ARCH_ARM
NodeJS_DEFAULT_VARIANT_NAME
NodeJS_VARIANT_BASE
NodeJS_VARIANT_NAME
NodeJS_URL
NodeJS_SOURCE_PATH
NodeJS_CHECKSUM_PATH
NodeJS_CHECKSUM_TYPE
NodeJS_WIN32_LIBRARY_PATH
NodeJS_WIN32_BINARY_PATH
NodeJS_WIN32_LIBRARY_NAME
NodeJS_WIN32_BINARY_NAME
NodeJS_DEFAULT_INCLUDE
NodeJS_DEFAULT_LIBS
NodeJS_HAS_WIN32_BINARY
NodeJS_HEADER_VERSION
NodeJS_SHA256_VERISON
NodeJS_PREFIX_VERSION
NodeJS_SOURCE_INCLUDE
NodeJS_HEADER_INCLUDE
NodeJS_INCLUDE_PATHS
NodeJS_WIN32_DELAYLOAD
NodeJS_DOWNLOAD_PATH
NodeJS_CHECKSUM_FILE
NodeJS_CHECKSUM_DATA
NodeJS_SOURCE_FILE
NodeJS_SOURCE_CHECKSUM
NodeJS_HEADER_PATH
NodeJS_HEADER_BASE
NodeJS_INCLUDE_DIR
NodeJS_WIN32_LIBRARY_FILE
NodeJS_WIN32_LIBRARY_CHECKSUM
NodeJS_WIN32_BINARY_FILE
NodeJS_WIN32_BINARY_CHECKSUM
NodeJS_NAN_PATH
NodeJS_LINK_FLAGS
NodeJS_COMPILE_OPTIONS
NodeJS_ADDITIONAL_SOURCES
NodeJS_WIN32_DELAYLOAD_CONDITION
NodeJS_WIN32_DELAYLOAD_BINARY
NodeJS_TARGET
)
-10
View File
@@ -1,10 +0,0 @@
{
"build_type": "@CMAKE_BUILD_TYPE@",
"generator": "@CMAKE_GENERATOR@",
"toolset": "@CMAKE_GENERATOR_TOOLSET@",
"platform": "@CMAKE_GENERATOR_PLATFORM@",
"variant": "@NodeJS_VARIANT_BASE@",
"version": "@NodeJS_VERSION@",
"download": "@NodeJS_DOWNLOAD@",
"standard": "@NodeJS_CXX_STANDARD@"
}
-28
View File
@@ -1,28 +0,0 @@
set(GITHUB_API_TOKEN $ENV{GITHUB_API_TOKEN})
set(GITHUB_AUTH "")
if(GITHUB_API_TOKEN)
set(GITHUB_AUTH "?access_token=${GITHUB_API_TOKEN}")
endif()
set(GITHUB_API_URL "https://api.github.com")
function(github_get_rate_limit VAR)
set(RATE_LIMIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/GITHUBRATE)
set(RATE_LIMIT_URL ${GITHUB_API_URL}/rate_limit${GITHUB_AUTH})
nodejs_download(
${RATE_LIMIT_URL}
${RATE_LIMIT_FILE}
ON
)
file(READ ${RATE_LIMIT_FILE} RATE_LIMIT_DATA)
string(REGEX MATCH "\"remaining\": ([0-9]+),"
RATE_LIMIT_MATCH ${RATE_LIMIT_DATA})
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()
mark_as_advanced(
GITHUB_AUTH
GITHUB_API_TOKEN
GITHUB_API_URL
)
-166
View File
@@ -1,166 +0,0 @@
function(nodejs_check_file FILE)
set(MESSAGE "File ${FILE} does not exist or is empty")
if(ARGC GREATER 1)
set(MESSAGE ${ARGV1})
endif()
# Make sure the file has contents
file(READ ${FILE} FILE_CONTENT LIMIT 1 HEX)
if(NOT FILE_CONTENT)
file(REMOVE ${FILE})
message(FATAL_ERROR ${MESSAGE})
endif()
endfunction()
function(nodejs_download URL FILE)
# Function optionally takes a checksum and a checksum type, and
# a force value
# Either can be specified without the other, but checksum must come first
if(ARGC GREATER 2)
set(CHECKSUM ${ARGV2})
if(CHECKSUM STREQUAL "On" OR CHECKSUM STREQUAL "ON" OR
CHECKSUM STREQUAL "True" OR CHECKSUM STREQUAL "TRUE" OR
CHECKSUM STREQUAL "Off" OR CHECKSUM STREQUAL "OFF" OR
CHECKSUM STREQUAL "False" OR CHECKSUM STREQUAL "FALSE")
set(FORCE ${CHECKSUM})
unset(CHECKSUM)
elseif(ARGC GREATER 3)
set(TYPE ${ARGV3})
else()
message(FATAL_ERROR "Checksum type must be specified")
endif()
elseif(ARGC GREATER 4)
set(CHECKSUM ${ARGV2})
set(TYPE ${ARGV3})
set(FORCE ${ARGV4})
endif()
# If the file exists, no need to download it again unless its being forced
if(NOT FORCE AND EXISTS ${FILE})
return()
endif()
# Download the file
message(STATUS "Downloading: ${URL}")
file(DOWNLOAD
${URL}
${FILE}
SHOW_PROGRESS
)
# Make sure the file has contents
nodejs_check_file(${FILE} "Unable to download ${URL}")
# If a checksum is provided, validate the downloaded file
if(CHECKSUM)
message(STATUS "Validating: ${FILE}")
file(${TYPE} ${FILE} DOWNLOAD_CHECKSUM)
message(STATUS "Checksum: ${CHECKSUM}")
message(STATUS "Download: ${DOWNLOAD_CHECKSUM}")
if(NOT CHECKSUM STREQUAL DOWNLOAD_CHECKSUM)
file(REMOVE ${FILE})
message(FATAL_ERROR "Validation failure: ${FILE}")
endif()
endif()
endfunction()
function(nodejs_checksum DATA FILE VAR)
string(REGEX MATCH "([A-Fa-f0-9]+)[\t ]+${FILE}" CHECKSUM_MATCH ${DATA})
if(CMAKE_MATCH_1)
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
else()
message(FATAL_ERROR "Unable to extract file checksum")
endif()
endfunction()
function(nodejs_extract FILE DIR)
# Function optionally takes a force value
if(ARGC GREATER 2)
set(FORCE ${ARGV2})
endif()
# If the archvie has been extracted, no need to extract again unless it
# is being forced
if(NOT FORCE AND EXISTS ${DIR})
return()
endif()
# Make a temporary directory for extracting the output
set(EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/extract)
if(EXISTS ${EXTRACT_DIR})
file(REMOVE_RECURSE ${EXTRACT_DIR})
endif()
file(MAKE_DIRECTORY ${EXTRACT_DIR})
# Extract the archive
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xfz ${FILE}
WORKING_DIRECTORY ${EXTRACT_DIR}
)
# If only one element is extracted, the archive contained a nested
# folder; use the inner folder as the extracted folder
file(GLOB EXTRACT_CHILDREN ${EXTRACT_DIR}/*)
list(LENGTH EXTRACT_CHILDREN NUM_CHILDREN)
set(TARGET_DIR ${EXTRACT_DIR})
if(NUM_CHILDREN EQUAL 1)
list(GET EXTRACT_CHILDREN 0 TARGET_DIR)
endif()
# Move the folder to the target path
if(EXISTS ${DIR})
file(REMOVE_RECURSE ${DIR})
endif()
file(RENAME ${TARGET_DIR} ${DIR})
# Make sure to clean up the extraction folder when the inner folder
# is used
file(REMOVE_RECURSE ${EXTRACT_DIR})
endfunction()
function(nodejs_find_module NAME BASE PATH)
# Find a node module using the same search path that require uses
# without needing a node binary
set(ROOT ${BASE})
set(DRIVE "^[A-Za-z]?:?/$")
# Walk up the directory tree until at the root
while(NOT ROOT MATCHES ${DRIVE} AND NOT
EXISTS ${ROOT}/node_modules/${NAME})
get_filename_component(ROOT ${ROOT} DIRECTORY)
endwhile()
# Operate like the CMake find_* functions, returning NOTFOUND if the
# module can't be found
if(ROOT MATCHES ${DRIVE})
set(${PATH} ${NAME}-NOTFOUND PARENT_SCOPE)
else()
set(${PATH} ${ROOT}/node_modules/${NAME} PARENT_SCOPE)
endif()
endfunction()
macro(nodejs_find_module_fallback NAME BASE PATH)
# Look in the provided path first
# If the module isn't found, try searching from the module
nodejs_find_module(${NAME} ${BASE} ${PATH})
if(NOT ${PATH})
nodejs_find_module(${NAME} ${NodeJS_MODULE_PATH} ${PATH})
endif()
endmacro()
function(nodejs_get_version URL VAR)
set(NWJS_LATEST_RELEASE_URL
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
set(VERSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/VERSION)
nodejs_download(
${URL}
${VERSION_FILE}
ON
)
nodejs_check_file(${VERSION_FILE})
file(READ ${VERSION_FILE} VERSION_DATA)
string(REGEX MATCH "v([0-9]+\.[0-9]+\.[0-9]+)"
VERSION_MATCH ${VERSION_DATA}
)
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
endfunction()
-81
View File
@@ -1,81 +0,0 @@
set(ELECTRON_VARIANT_BASE "electron")
set(ELECTRON_WIN32_BINARY_NAME "${ELECTRON_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${ELECTRON_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_ELECTRON OR
NodeJS_VARIANT STREQUAL ${ELECTRON_VARIANT_BASE})
if(NodeJS_VERSION STREQUAL "latest")
include(util/Github)
github_get_rate_limit(GITHUB_RATE_LIMIT)
# Handle determining the latest release
# Very complicated, due to electron not following the "latest"
# convention of other variants
set(ELECTRON_LATEST_RELEASE_FILE ${CMAKE_CURRENT_BINARY_DIR}/ELECTRON)
set(ELECTRON_LATEST_RELEASE_URL
${GITHUB_API_URL}/repos/atom/electron/releases/latest${GITHUB_AUTH}
)
if(GITHUB_RATE_LIMIT GREATER 0)
nodejs_download(
${ELECTRON_LATEST_RELEASE_URL}
${ELECTRON_LATEST_RELEASE_FILE}
ON
)
endif()
nodejs_check_file(
${ELECTRON_LATEST_RELEASE_FILE}
"Releases file could not be downloaded, likely \
because github rate limit was exceeded. Wait until the limit \
passes or set GITHUB_API_TOKEN in your environment to a valid \
github developer token."
)
file(READ ${ELECTRON_LATEST_RELEASE_FILE} ELECTRON_LATEST_RELEASE_DATA)
string(REGEX MATCH "\"tag_name\"\: \"v([0-9]+\.[0-9]+\.[0-9]+)\""
ELECTRON_LATEST_RELEASE_MATCH ${ELECTRON_LATEST_RELEASE_DATA})
set(NodeJS_VERSION ${CMAKE_MATCH_1})
endif()
set(NodeJS_VARIANT_NAME "Electron.js")
# SHASUMS of any kind is inaccessible prior to 0.16.0
if(NodeJS_VERSION VERSION_LESS 0.16.0)
message(FATAL_ERROR "Electron is only supported for versions >= 0.16.0")
endif()
# Electron switched to IOJS after 0.25.0
# Probably needs to be bounded on the upper side if/when they switch
# back to node mainline due to iojs-node merge
set(NodeJS_VARIANT_BASE "node")
if(NodeJS_VERSION VERSION_GREATER 0.25.0)
set(NodeJS_VARIANT_BASE "iojs")
endif()
# Url is hard to get, because it will immediately resolve to a CDN
# Extracted from the electron website
set(NodeJS_URL
"https://atom.io/download/atom-shell/v${NodeJS_VERSION}"
)
# Headers become available for IOJS base ONLY!
# Variant base switch above handles this
set(NodeJS_HEADER_VERSION 0.30.1)
# Header only archive uses source style paths
set(NodeJS_DEFAULT_INCLUDE False)
# Hard to determine, but versions seem to start at 16, and SHA256 is
# available
set(NodeJS_SHA256_VERSION 0.15.9)
# C++11 and Prefixing start after the IOJS switch
# Will carry forward after node mainline so no need for upper bound (whew)
set(NodeJS_PREFIX_VERSION 0.25.0)
set(NodeJS_CXX11R_VERSION 0.25.0)
# The executable is not provided on the CDN
# In theory, I could support a BINARY_URL to get this from github
set(NodeJS_HAS_WIN32_BINARY False)
# OpenSSL isn't included in the headers
set(NodeJS_HAS_OPENSSL False)
endif()
-25
View File
@@ -1,25 +0,0 @@
set(IOJS_URL_BASE "https://iojs.org/dist")
set(IOJS_VARIANT_BASE "iojs")
set(IOJS_WIN32_BINARY_NAME "${IOJS_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${IOJS_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_IOJS OR NodeJS_VARIANT STREQUAL ${IOJS_VARIANT_BASE})
if(NodeJS_VERSION STREQUAL "latest")
set(IOJS_LATEST_RELEASE_URL
"${IOJS_URL_BASE}/latest/SHASUMS256.txt")
nodejs_get_version(${IOJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
set(NodeJS_VARIANT_NAME "io.js")
set(NodeJS_VARIANT_BASE ${IOJS_VARIANT_BASE})
set(NodeJS_URL "${IOJS_URL_BASE}/v${NodeJS_VERSION}")
set(NodeJS_HEADER_VERSION 2.3.1)
set(NodeJS_WIN32_BINARY_NAME "${IOJS_WIN32_BINARY_NAME}")
endif()
mark_as_advanced(
IOJS_URL_BASE
IOJS_VARIANT_BASE
IOJS_WIN32_BINARY_NAME
IOJS_LATEST_RELEASE_URL
)
-30
View File
@@ -1,30 +0,0 @@
set(NWJS_URL_BASE "http://dl.nwjs.io")
set(NWJS_VARIANT_BASE "nw")
set(NWJS_WIN32_BINARY_NAME "${NWJS_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${NWJS_WIN32_BINARY_NAME})
if(NodeJS_FIND_REQUIRED_NWJS OR NodeJS_VARIANT STREQUAL ${NWJS_VARIANT_BASE})
set(NodeJS_CHECKSUM_PATH "MD5SUMS")
set(NodeJS_CHECKSUM_TYPE "MD5")
if(NodeJS_VERSION STREQUAL "latest")
set(NWJS_LATEST_RELEASE_URL
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
nodejs_get_version(${NWJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
set(NodeJS_VARIANT_NAME "nw.js")
set(NodeJS_VARIANT_BASE ${NWJS_VARIANT_BASE})
set(NodeJS_URL "${NWJS_URL_BASE}/v${NodeJS_VERSION}")
set(NodeJS_SOURCE_PATH "nw-headers-v${NodeJS_VERSION}.tar.gz")
set(NodeJS_DEFAULT_INCLUDE False)
set(NodeJS_HAS_WIN32_PREFIX False)
set(NodeJS_HAS_WIN32_BINARY False)
endif()
mark_as_advanced(
NWJS_URL_BASE
NWJS_VARIANT_BASE
NWJS_WIN32_BINARY_NAME
NWJS_LATEST_RELEASE_URL
)
-131
View File
@@ -1,131 +0,0 @@
set(NodeJS_URL_BASE http://nodejs.org/dist)
set(NodeJS_DEFAULT_VARIANT_BASE "node")
set(NodeJS_DEFAULT_WIN32_BINARY_NAME "${NodeJS_DEFAULT_VARIANT_BASE}.exe")
list(APPEND NodeJS_WIN32_DELAYLOAD ${NodeJS_DEFAULT_WIN32_BINARY_NAME})
if(NodeJS_VERSION STREQUAL "latest")
set(NodeJS_LATEST_RELEASE_URL
"${NodeJS_URL_BASE}/latest/SHASUMS256.txt")
nodejs_get_version(${NodeJS_LATEST_RELEASE_URL} NodeJS_VERSION)
endif()
if(NOT NodeJS_VARIANT_NAME)
set(NodeJS_VARIANT_NAME ${NodeJS_DEFAULT_VARIANT_NAME})
endif()
if(NOT NodeJS_VARIANT_BASE)
set(NodeJS_VARIANT_BASE ${NodeJS_DEFAULT_VARIANT_BASE})
endif()
if(NOT NodeJS_URL)
set(NodeJS_URL "${NodeJS_URL_BASE}/v${NodeJS_VERSION}")
endif()
if(NOT NodeJS_SOURCE_PATH)
set(NodeJS_SOURCE_PATH "${NodeJS_VARIANT_BASE}-v${NodeJS_VERSION}")
# Use the headers archive when its available
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}-headers")
endif()
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}.tar.gz")
endif()
if(NodeJS_DEFAULT_INCLUDE AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
set(NodeJS_SOURCE_INCLUDE False)
set(NodeJS_HEADER_INCLUDE True)
endif()
if(NodeJS_SOURCE_INCLUDE)
list(APPEND NodeJS_INCLUDE_PATHS
src
deps/uv/include
deps/v8/include
deps/zlib
)
# OpenSSL is an optional header
if(NodeJS_HAS_OPENSSL)
list(APPEND NodeJS_INCLUDE_PATHS
deps/openssl/openssl/include
)
endif()
endif()
if(NodeJS_HEADER_INCLUDE)
set(NodeJS_INCLUDE_PATHS include/node)
endif()
if(NOT NodeJS_CHECKSUM_TYPE)
# Use SHA256 when available
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_SHA256_VERSION})
set(NodeJS_CHECKSUM_TYPE "SHA256")
else()
set(NodeJS_CHECKSUM_TYPE "SHA1")
endif()
endif()
if(NOT NodeJS_CHECKSUM_PATH)
set(NodeJS_CHECKSUM_PATH "SHASUMS")
if(NodeJS_CHECKSUM_TYPE STREQUAL "SHA256")
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}256")
endif()
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}.txt")
endif()
# Library and binary are based on variant base
if(NOT NodeJS_WIN32_LIBRARY_NAME)
set(NodeJS_WIN32_LIBRARY_NAME ${NodeJS_VARIANT_BASE}.lib)
endif()
if(NOT NodeJS_WIN32_BINARY_NAME)
set(NodeJS_WIN32_BINARY_NAME ${NodeJS_VARIANT_BASE}.exe)
endif()
if(NOT NodeJS_WIN32_LIBRARY_PATH)
# The library location is prefixed after a specific version
if(NodeJS_HAS_WIN32_PREFIX AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
set(NodeJS_WIN32_LIBRARY_PATH "win-")
if(NodeJS_ARCH_IA32)
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x86/")
endif()
endif()
# 64-bit versions are prefixed
if(NodeJS_ARCH_X64)
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x64/")
endif()
set(NodeJS_WIN32_LIBRARY_PATH
"${NodeJS_WIN32_LIBRARY_PATH}${NodeJS_WIN32_LIBRARY_NAME}"
)
endif()
if(NodeJS_HAS_WIN32_BINARY AND NOT NodeJS_WIN32_BINARY_PATH)
# The executable location is prefixed after a specific version
if(NodeJS_HAS_WIN32_PREFIX AND
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
set(NodeJS_WIN32_BINARY_PATH "win-")
if(NodeJS_ARCH_IA32)
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x86/")
endif()
endif()
# 64-bit versions are prefixed
if(NodeJS_ARCH_X64)
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x64/")
endif()
set(NodeJS_WIN32_BINARY_PATH
"${NodeJS_WIN32_BINARY_PATH}${NodeJS_WIN32_BINARY_NAME}"
)
endif()
# Specify windows libraries
# XXX: This may need to be version/variant specific in the future
if(NodeJS_DEFAULT_LIBS AND NodeJS_PLATFORM_WIN32)
list(APPEND NodeJS_LIBRARIES
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
odbc32.lib DelayImp.lib
)
endif()
mark_as_advanced(
NodeJS_URL_BASE
NodeJS_DEFAULT_VARIANT_BASE
NodeJS_DEFAULT_WIN32_BINARY_NAME
NodeJS_LATEST_RELEASE_URL
)
+1 -1
View File
@@ -3,5 +3,5 @@ module.exports = {
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
all: '--strict --require features/support --require features/step_definitions',
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@match --tags ~@alternative --tags ~@matrix --tags ~@trip --tags ~@via --require features/support --require features/step_definitions -f progress'
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@matrix --tags ~@trip --require features/support --require features/step_definitions -f progress'
}
+18 -11
View File
@@ -1,15 +1,9 @@
FROM alpine:3.5
ARG DOCKER_TAG
RUN mkdir /src
COPY . /src
RUN mkdir /opt
WORKDIR /opt
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
case ${DOCKER_TAG} in *"-debug"*) BUILD_TYPE="Debug";; *) BUILD_TYPE="Release";; esac && \
\
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk upgrade && \
@@ -23,13 +17,26 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Release .. && \
make -j${NPROC} && \
make install && \
\
make install
ARG DOCKER_TAG
RUN mkdir /src
COPY . /src
WORKDIR /src
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "Building OSRM ${DOCKER_TAG}" && \
cd /src && \
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
echo "Building OSRM gitsha $(cat /opt/OSRM_GITSHA)" && \
mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_LTO=On .. && \
BUILD_TYPE="Release" && \
ENABLE_ASSERTIONS="Off" && \
BUILD_TOOLS="Off" && \
case ${DOCKER_TAG} in *"-debug"*) BUILD_TYPE="Debug";; esac && \
case ${DOCKER_TAG} in *"-assertions"*) BUILD_TYPE="RelWithDebInfo" && ENABLE_ASSERTIONS="On" && BUILD_TOOLS="On";; esac && \
echo "Building ${BUILD_TYPE} with ENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} BUILD_TOOLS=${BUILD_TOOLS}" && \
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS} -DBUILD_TOOLS=${BUILD_TOOLS} -DENABLE_LTO=On && \
make -j${NPROC} install && \
cd ../profiles && \
cp -r * /opt && \
+8 -3
View File
@@ -15,7 +15,7 @@ GET /{service}/{version}/{profile}/{coordinates}[.{format}]?option=value&option=
| `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})`. |
| `coordinates`| String of format `{longitude},{latitude};{longitude},{latitude}[;{longitude},{latitude} ...]` or `polyline({polyline}) or polyline6({polyline6})`. |
| `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).
@@ -30,6 +30,7 @@ To pass parameters to each location some options support an array like encoding:
|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. |
|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. |
|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. |
|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curb side. |
Where the elements follow the following format:
@@ -38,6 +39,7 @@ Where the elements follow the following format:
|bearing |`{value},{range}` `integer 0 .. 360,integer 0 .. 180` |
|radius |`double >= 0` or `unlimited` (default) |
|hint |Base64 `string` |
|approach |`curb` or `unrestricted` (default) |
```
{option}={element};{element}[;{element} ... ]
@@ -300,7 +302,7 @@ The area to search is chosen such that the correct candidate should be considere
Each `Waypoint` object has the following additional properties:
- `matchings_index`: Index to the `Route` object in `matchings` the sub-trace was matched to.
- `waypoint_index`: Index of the waypoint inside the matched route.
- `alternatives_count`: number of alternative routes leading to the destination from this trace point. 0 means there are no other routes reaching destination. Greater values mean that there are different routes available and different route can be selected if you provide more coordinates.
- `alternatives_count`: Number of probable alternative matchings for this trace point. A value of zero indicate that this point was matched unambiguously. Split the trace at these points for incremental map matching.
- `matchings`: An array of `Route` objects that assemble the trace. Each `Route` object has the following additional properties:
- `confidence`: Confidence of the matching. `float` value between 0 and 1. 1 is very confident that the matching is correct.
@@ -417,8 +419,10 @@ Vector tiles contain two layers:
| `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 |
| `duration` | `float` | how long this segment takes to traverse, in seconds. This value is to calculate the total route ETA. |
| `weight ` | `integer` | how long this segment takes to traverse, in units (may differ from `duration` when artificial biasing is applied in the Lua profiles). ACTUAL ROUTING USES THIS VALUE. |
| `name` | `string` | the name of the road this segment belongs to |
| `rate` | `float` | the value of `length/weight` - analagous to `speed`, but using the `weight` value rather than `duration`, rounded to the nearest integer |
`turns` layer:
@@ -427,6 +431,7 @@ Vector tiles contain two layers:
| `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"). |
| `weight` | `float` | the weight we think it takes to make that turn. May be negative, depending on how the data model is constructed (some turns get a "bonus"). ACTUAL ROUTING USES THIS VALUE |
## Result objects
+132 -127
View File
@@ -1,66 +1,60 @@
# OSRM
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
The `OSRM` method is the main constructor for creating an OSRM instance. An OSRM instance requires a `.osrm` network,
which is prepared by the OSRM Backend C++ library.
## OSRM
The `OSRM` method is the main constructor for creating an OSRM instance.
An OSRM instance requires a `.osrm` dataset, which is prepared by the OSRM toolchain.
You can create such a `.osrm` file by running the OSRM binaries we ship in `node_modules/osrm/lib/binding/` and default
profiles (e.g. for setting speeds and determining road types to route on) in `node_modules/osrm/profiles/`:
node_modules/osrm/lib/binding/osrm-extract data.osm.pbf -p node_modules/osrm/profiles/car.lua
node_modules/osrm/lib/binding/osrm-contract data.osrm
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation or further details.
Consult the [osrm-backend](https://github.com/Project-OSRM/osrm-backend) documentation for further details.
Once you have a complete `network.osrm` file, you can calculate networks in javascript with this library using the
methods below. To create an OSRM instance with your network you need to construct an instance like this:
Once you have a complete `network.osrm` file, you can calculate routes in javascript with this object.
```javascript
var osrm = new OSRM('network.osrm');
```
#### Methods
**Parameters**
| Service | Description |
| -------------------------- | --------------------------------------------------------- |
| [`osrm.route`](#route) | shortest path between given coordinates |
| [`osrm.nearest`](#nearest) | returns the nearest street segment for a given coordinate |
| [`osrm.table`](#table) | computes distance tables for given coordinates |
| [`osrm.match`](#match) | matches given coordinates to the road network |
| [`osrm.trip`](#trip) | Compute the shortest trip between given coordinates |
| [`osrm.tile`](#tile) | Return vector tiles containing debugging info |
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Options for creating an OSRM object or string to the `.osrm` file. (optional, default `{shared_memory:true}`)
- `options.algorithm` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
Make sure you prepared the dataset with the correct toolchain.
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
#### General Options
Each OSRM method (except for `OSRM.tile()`) has set of general options as well as unique options, outlined below.
| Option | Values | Description | Format |
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| coordinates | `array` of `coordinate` elements: `[{coordinate}, ...]` | The coordinates this request will use. | `array` with `[{lon},{lat}]` values, in decimal degrees |
| bearings | `array` of `bearing` elements: `[{bearing}, ...]` | Limits the search to segments with given bearing in degrees towards true north in clockwise direction. | `null` or `array` with `[{value},{range}]` `integer 0 .. 360,integer 0 .. 180` |
| radiuses | `array` of `radius` elements: `[{radius}, ...]` | Limits the search to given radius in meters. | `null` or `double >= 0` or `unlimited` (default) |
| hints | `array` of `hint` elements: `[{hint}, ...]` | Hint to derive position in street network. | Base64 `string` |
| generate\_hints | `true` (default) or `false` | Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. | `Boolean` |
## route
### route
Returns the fastest route between two or more coordinates while visiting the waypoints in order.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the route query.
- `options.alternatives` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Search for alternative routes and return as well. _Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route leg. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** 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. `null`/`true`/`false`
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes and return as well.
_Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`)
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** 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.
`null`/`true`/`false`
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM("berlin-latest.osrm");
osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, function(err, result) {
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
if(err) throw err;
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
@@ -69,7 +63,7 @@ osrm.route({coordinates: [[13.438640,52.519930], [13.415852, 52.513191]]}, funct
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** An array of [Waypoint](#waypoint) objects representing all waypoints in order AND an array of [`Route`](#route) objects ordered by descending recommendation rank.
## nearest
### nearest
Snaps a coordinate to the street network and returns the nearest n matches.
@@ -78,8 +72,14 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the nearest query.
- `options.number` **\[[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)]** Number of nearest segments that should be returned.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -98,19 +98,27 @@ osrm.nearest(options, function(err, response) {
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints`.
**`waypoints`**: array of [`Ẁaypoint`](#waypoint) objects sorted by distance to the input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied
input coordinate.
Each object has an additional `distance` property, which is the distance in meters to the supplied input coordinate.
## table
### table
Computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
tables.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the table query.
- `options.sources` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.sources` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to
use
location with given index as source. Default is to use all.
- `options.destinations` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
#coordinates`) to use location with given index as destination. Default is to use all.
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -132,24 +140,25 @@ osrm.table(options, function(err, response) {
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `durations`, `sources`, and `destinations`.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]`
gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds.
**`durations`**: array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from the i-th waypoint to the j-th waypoint.
Values are given in seconds.
**`sources`**: array of [`Ẁaypoint`](#waypoint) objects describing all sources in order.
**`destinations`**: array of [`Ẁaypoint`](#waypoint) objects describing all destinations in order.
## tile
### tile
This generates [Mapbox Vector Tiles](https://mapbox.com/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,
so are in sync with actual routing results, and let you examine which roads are actually
routable,
and what weights they have applied.
**Parameters**
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](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/>.
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](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/).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -164,7 +173,7 @@ osrm.tile([0, 0, 0], function(err, response) {
Returns **[Buffer](https://nodejs.org/api/buffer.html)** contains a Protocol Buffer encoded vector tile.
## match
### 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
@@ -175,15 +184,18 @@ if they can not be matched successfully.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the match query.
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified`
according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>]** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **\[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)]** Standard deviation of GPS precision used for map matching.
If applicable use GPS accuracy (`double >= 0`, default `5m`).
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
- `options.gaps` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore`. (optional, default `split`)
- `options.tidy` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Allows the input track modification to obtain better matching quality for noisy tracks. (optional, default `false`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -203,69 +215,55 @@ osrm.match(options, function(err, response) {
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `tracepoints` and `matchings`.
**`tracepoints`** Array of [`Ẁaypoint`](#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. Each
`Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
the waypoint inside the matched route.
**`matchings`** is an array of [`Route`](#route) objects that
assemble the trace. Each `Route` object has an additional `confidence` property, which is the confidence of
the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
If the trace point was ommited by map matching because it is an outlier, the entry will be null.
Each `Waypoint` object includes two additional properties, 1) `matchings_index`: Index to the
[`Route`](#route) object in matchings the sub-trace was matched to, 2) `waypoint_index`: Index of
the waypoint inside the matched route.
**`matchings`** is an array of [`Route`](#route) objects that assemble the trace. Each `Route` object has an additional `confidence` property,
which is the confidence of the matching. float value between `0` and `1`. `1` is very confident that the matching is correct.
## trip
### trip
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm). The returned path does not have to be the fastest path, as TSP is NP-hard it is only an approximation. Note that all input coordinates have to be connected for the trip service to work.
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.roundtrip` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route is a roundtrip. (optional, default `true`)
- `options.source` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route starts at `any` coordinate. Can also be `first`. (optional, default `any`)
- `options.destination` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Return route ends at `any` coordinate. Can also be `last`. (optional, default `any`)
- `options.steps` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** Return route steps for each route. (optional, default `false`)
- `options.annotations` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)] or \[[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>]** Return annotations for each route leg for duration, nodes, distance, weight, datasources and/or speed. Annotations can be `false` or `true` (no/full annotations) or an array of strings with `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed`. (optional, default `false`)
- `options.geometries` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Returned route geometry format (influences overview
and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Fixing Start and End Points**
It is possible to explicitly set the start or end coordinate of the trip. When source is set to `first`, the first coordinate is used as start coordinate of the trip in the output. When destination is set to `last`, the last coordinate will be used as destination of the trip in the returned output. If you specify `any`, any of the coordinates can be used as the first or last coordinate in the output.
However, if `source=any&destination=any` the returned round-trip will still start at the first input coordinate by default.
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
(farthest-insertion algorithm) for 10 or _ more waypoints and uses brute force for less than 10
waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is
only an approximation.
Note that all input coordinates have to be connected for the trip service to work.
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
Right now, the following combinations are possible:
| roundtrip | source | destination | supported |
| :-- | :-- | :-- | :-- |
| true | first | last | **yes** |
| true | first | any | **yes** |
| true | any | last | **yes** |
| true | any | any | **yes** |
| false | first | last | **yes** |
| false | first | any | no |
| false | any | last | no |
| false | any | any | no |
| :-------- | :----- | :---------- | :-------- |
| true | first | last | **yes** |
| true | first | any | **yes** |
| true | any | last | **yes** |
| true | any | any | **yes** |
| false | first | last | **yes** |
| false | first | any | no |
| false | any | last | no |
| false | any | any | no |
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
}
osrm.trip(options, function(err, response) {
if (err) throw err;
console.log(response.waypoints); // array of Waypoint objects
console.log(response.trips); // array of Route objects
});
```
Non Roundtrip Request
```javascript
var osrm = new OSRM('network.osrm');
var options = {
@@ -285,49 +283,56 @@ osrm.trip(options, function(err, response) {
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** containing `waypoints` and `trips`.
**`waypoints`**: an array of [`Ẁaypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties, 1) `trips_index`: index to trips of the
sub-trip the point was matched to, and 2) `waypoint_index`: index of the point in the trip.
**`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
Each Waypoint object has the following additional properties,
1) `trips_index`: index to trips of the sub-trip the point was matched to, and
2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
# Responses
## Responses
Responses
## Route
### Route
Represents a route through (potentially multiple) waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#route)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#route)
## RouteLeg
### RouteLeg
Represents a route between two waypoints.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routeleg)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#routeleg)
## RouteStep
### RouteStep
A step consists of a maneuver such as a turn or merge, followed by a distance of travel along a single way to the subsequent step.
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.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
## StepManeuver
### StepManeuver
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmanuever)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
## Waypoint
### Waypoint
Object used to describe waypoint on a route.
**Parameters**
- `exteral` **documentation** in [`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
+23 -23
View File
@@ -29,40 +29,40 @@ The following global properties can be set in your profile:
Attribute | Type | Notes
------------------------------|----------|----------------------------------------------------------------------------
weight_name | String | Name used in output for the routing weight property (default 'duration')
weight_precision | Unsigned | Decimal precision of edge weights (default 1)
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance)
use_turn_restrictions | Boolean | Are turn instructions followed?
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed?
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
use_turn_restrictions | Boolean | Are turn instructions followed? (default `false`)
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that segment_function will be called for all segments
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `segment_function` will be called for all segments (default `false`)
## way_function
Given an OpenStreetMap way, the way_function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
Given an OpenStreetMap way, the `way_function` will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
All other calculations stem from that, including the returned timings in driving directions, but also, less directly, it feeds into the actual routing decisions the engine will take (a way with a slow traversal speed, may be less favoured than a way with fast traversal speed, but it depends how long it is, and... what it connects to in the rest of the network graph)
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the way_function. Instead a way_function will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `way_function`. Instead a `way_function` will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
The following attributes can be set on the result in way_function:
The following attributes can be set on the result in `way_function`:
Attribute | Type | Notes
----------------------------------------|----------|--------------------------------------------------------------------------
forward_speed | Float | Speed on this way in km/h
forward_speed | Float | Speed on this way in km/h. Mandatory.
backward_speed | Float | " "
forward_rate | Float | Routing weight, expressed as meters/*weight* (e.g. for a fastest-route weighting, you would want this to be meters/second, so set it to forward_speed/3.6)
backward_rate | Float | " "
forward_mode | Enum | Mode of travel (e.g. car, ferry). Defined in include/extractor/travel_mode.hpp
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
backward_mode | Enum | " "
duration | Float | Alternative setter for duration of the whole way in both directions
weight | Float | Alternative setter for weight of the whole way in both directions
turn_lanes_forward | String | Directions for individual lanes (normalised OSM turn:lanes value)
turn_lanes_forward | String | Directions for individual lanes (normalised OSM `turn:lanes` value)
turn_lanes_backward | String | " "
forward_restricted | Boolean | Is this a restricted access road? (e.g. private, or deliveries only; used to enable high turn penalty, so that way is only chosen for start/end of route)
backward_restricted | Boolean | " "
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if false, prevents snapping the start point to this way)
is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if `false`, prevents snapping the start point to this way)
roundabout | Boolean | Is this part of a roundabout?
circular | Boolean | Is this part of a non-roundabout circular junction?
name | String | Name of the way
@@ -70,7 +70,7 @@ ref | String | Road number
pronunciation | String | Name pronunciation
road_classification.motorway_class | Boolean | Guidance: way is a motorway
road_classification.link_class | Boolean | Guidance: way is a slip/link road
road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in include/extractor/guidance/road_classification.hpp
road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in `include/extractor/guidance/road_classification.hpp`
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
@@ -87,16 +87,16 @@ Forks can be emitted between roads of similar priority category only. Obvious ch
## node_function
The following attributes can be set on the result in node_function:
The following attributes can be set on the result in `node_function`:
Attribute | Type | Notes
----------------|---------|-------------------------------------------------------
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in turn_function)?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `turn_function`)?
## segment_function
The following attributes can be read and set on the result in segment_function:
The following attributes can be read and set on the result in `segment_function`:
Attribute | Read/write? | Type | Notes
-------------------|-------------|---------|------------------------------------------------------
@@ -110,15 +110,15 @@ duration | Read/write | Float | Duration for this segment
## turn_function
The following attributes can be read and set on the result in turn_function:
The following attributes can be read and set on the result in `turn_function`:
Attribute | Read/write? | Type | Notes
-------------------|-------------|---------|------------------------------------------------------
direction_modifier | Read | Enum | Geometry of turn. Defined in include/extractor/guidance/turn_instruction.hpp
turn_type | Read | Enum | Priority of turn. Defined in include/extractor/guidance/turn_instruction.hpp
direction_modifier | Read | Enum | Geometry of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
turn_type | Read | Enum | Priority of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in way_function)
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in way_function)
angle | Read | Float | Angle of turn in degrees (0-360: 0=u-turn, 180=straight on)
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `way_function`)
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in `way_function`)
angle | Read | Float | Angle of turn in degrees (`0-360`: `0`=u-turn, `180`=straight on)
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
+35
View File
@@ -0,0 +1,35 @@
@routing @bicycle @alley
Feature: Bicycle - Route around alleys
Background:
Given the profile file
"""
require 'bicycle'
properties.weight_name = 'cyclability'
"""
Scenario: Bicycle - Avoid taking alleys
Given the query options
| annotations | nodes |
Given the node map
"""
a-----b-----c
| : |
d.....e.....f
"""
And the ways
| nodes | highway | service |
| abc | residential | |
| def | service | alley |
| ad | residential | |
| be | service | alley |
| cf | residential | |
When I route I should get
| from | to | a:nodes | weight | # |
| a | f | 1:2:3:6 | 200.4 | Avoids d,e,f |
| a | e | 1:2:5 | 176.4 | Take the alley b,e if neccessary |
| d | f | 4:1:2:3:6 | 252.6 | Avoids the alley d,e,f |
+29 -22
View File
@@ -2,35 +2,42 @@
Feature: Turn Penalties
Background:
Given the profile "turnbot"
Given the profile "bicycle"
Given a grid size of 200 meters
Scenario: Bike - turns should incur a delay that depend on the angle
Scenario: Bicycle - Turn penalties on cyclability
Given the profile file
"""
require 'bicycle'
properties.weight_name = 'cyclability'
"""
Given the node map
"""
c d e
b j f
a s g
a--b-----c
|
|
d
e--------f-----------g
/
/
/
h
"""
And the ways
| nodes |
| sj |
| ja |
| jb |
| jc |
| jd |
| je |
| jf |
| jg |
| nodes | highway |
| abc | residential |
| bd | residential |
| efg | residential |
| fh | residential |
When I route I should get
| from | to | route | time | distance |
| s | a | sj,ja,ja | 63s +-1 | 483m +-1 |
| s | b | sj,jb,jb | 50s +-1 | 400m +-1 |
| s | c | sj,jc,jc | 54s +-1 | 483m +-1 |
| s | d | sj,jd,jd | 40s +-1 | 400m +-1 |
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
| from | to | distance | weight | # |
| a | c | 900m +- 1 | 216 | Going straight has no penalties |
| a | d | 900m +- 1 | 220.2 | Turning right had penalties |
| e | g | 2100m +- 4| 503.9 | Going straght has no penalties |
| e | h | 2100m +- 4| 515.1 | Turn sharp right has even higher penalties|
+192
View File
@@ -0,0 +1,192 @@
@routing @approach
Feature: Approach parameter
Background:
Given the profile "car"
And a grid size of 10 meters
Scenario: Start End same approach, option unrestricted for Start and End
Given the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End same approach, option unrestricted for Start and curb for End
Given the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
Scenario: Start End opposite approach, option unrestricted for Start and End
Given the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End opposite approach, option unrestricted for Start and curb for End
Given the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
###############
# Oneway Test #
###############
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and End
Given the node map
"""
s e
a------b------c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and curb for End
Given the node map
"""
s e
a------b------c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and End
Given the node map
"""
s
a------b------c
e
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and curb for End
Given the node map
"""
s
a------b------c
e
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
##############
# UTurn Test #
##############
Scenario: UTurn test, router can't found a route because uturn unauthorized on the segment selected
Given the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bc | bc | c | no_u_turn |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | |
Scenario: UTurn test, router can found a route because he can use the roundabout
Given the node map
"""
h
s e / \
a------b------c g
\ /
f
"""
And the ways
| nodes | junction |
| ab | |
| bc | |
| cfghc | roundabout |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bc | bc | c | no_u_turn |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
@@ -0,0 +1,741 @@
@routing @car @restrictions
Feature: Car - Turn restrictions
# Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction
# Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes.
Background: Use car routing
Given the profile "car"
Given a grid size of 200 meters
Given the origin -9.2972,10.3811
# coordinate in Guinée, a country that observes GMT year round
@no_turning @conditionals
Scenario: Car - ignores unrecognized restriction
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | only_right_turn @ (has_pygmies > 10 p) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Restriction would be on, but the restriction was badly tagged
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p |
\ |
j
| \
s m
"""
And the ways
| nodes |
| nj |
| js |
| pjm |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | nj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
| restriction | js | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) |
When I route I should get
| from | to | route |
| n | m | nj,pjm,pjm |
| s | m | js,pjm,pjm |
@no_turning @conditionals
Scenario: Car - ignores except restriction
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | no |
| jp | no |
And the relations
| type | way:from | way:to | node:via | restriction:conditional | except |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar |
| restriction | jp | nj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus |
When I route I should get
| from | to | route | # |
| e | s | ej,js,js | |
| e | n | ej,nj,nj | restriction does not apply to cars |
| e | p | ej,jp,jp | |
| p | s | jp,nj,nj,js,js | restriction excepting busses still applies to cars |
@no_turning @conditionals
Scenario: Car - only_right_turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
When I route I should get
| from | to | route |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,nj,nj,jp,jp |
@no_turning @conditionals
Scenario: Car - No right turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
When I route I should get
| from | to | route | # |
| e | s | ej,js,js | normal turn |
| e | n | ej,js,js,nj,nj | avoids right turn |
| e | p | ej,jp,jp | normal maneuver |
@only_turning @conditionals
Scenario: Car - only_left_turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,js,js,jp,jp |
@no_turning @conditionals
Scenario: Car - No left turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
When I route I should get
| from | to | route |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is off
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is on
Given the extract extra arguments "--parse-conditional-restrictions"
# 10am utc, wed
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction with multiple time windows
Given the extract extra arguments "--parse-conditional-restrictions"
# 5pm Wed 02 May, 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the node map
"""
n
p |
\ |
j
| \
s m
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| jp | yes |
| mj | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp |
@no_turning @conditionals
Scenario: Car - only_right_turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) |
When I route I should get
| from | to | route |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,nj,nj,jp,jp |
@no_turning @conditionals
Scenario: Car - No right turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) |
When I route I should get
| from | to | route | # |
| e | s | ej,js,js | normal turn |
| e | n | ej,js,js,nj,nj | avoids right turn |
| e | p | ej,jp,jp | normal maneuver |
@only_turning @conditionals
Scenario: Car - only_left_turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,js,js,jp,jp |
@no_turning @conditionals
Scenario: Car - No left turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) |
When I route I should get
| from | to | route |
| e | s | ej,nj,nj,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is off
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction is on
Given the extract extra arguments "--parse-conditional-restrictions"
# 10am utc, wed
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600"
Given the node map
"""
n
p j e
s
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| ej | yes |
| jp | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) |
When I route I should get
| from | to | route |
| e | s | ej,js,js |
| e | n | ej,js,js,nj,nj |
| e | p | ej,jp,jp |
@no_turning @conditionals
Scenario: Car - Conditional restriction with multiple time windows
Given the extract extra arguments "--parse-conditional-restrictions"
# 5pm Wed 02 May, 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the node map
"""
n
p |
\ |
j
| \
s m
"""
And the ways
| nodes | oneway |
| nj | no |
| js | no |
| jp | yes |
| mj | yes |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp |
# https://www.openstreetmap.org/#map=18/38.91099/-77.00888
@no_turning @conditionals
Scenario: Car - DC North capitol situation, two on one off
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 9pm Wed 02 May, 2017 UTC, 5pm EDT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493845200"
# """
# a h
# d
# b g
# e
# c f
# """
Given the node locations
| node | lat | lon |
| a | 38.9113 | -77.0091 |
| b | 38.9108 | -77.0091 |
| c | 38.9104 | -77.0091 |
| d | 38.9110 | -77.0096 |
| e | 38.9106 | -77.0086 |
| f | 38.9105 | -77.0090 |
| g | 38.9108 | -77.0090 |
| h | 38.9113 | -77.0090 |
And the ways
| nodes | oneway | name |
| ab | yes | cap south |
| bc | yes | cap south |
| fg | yes | cap north |
| gh | yes | cap north |
| db | no | florida nw |
| bg | no | florida |
| ge | no | florida ne |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ab | bg | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
| restriction | fg | bg | g | no_left_turn @ (Mo-Fr 06:00-10:00) |
| restriction | bg | bc | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
When I route I should get
| from | to | route | turns |
| a | e | cap south,florida nw,florida nw,florida ne | depart,turn right,continue uturn,arrive |
| f | d | cap north,florida,florida nw | depart,turn left,arrive |
| e | c | florida ne,florida nw,cap south,cap south | depart,continue uturn,turn right,arrive |
@no_turning @conditionals
Scenario: Car - DC North capitol situation, one on two off
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 10:30am utc, wed, 6:30am est
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493807400"
# """
# a h
# d
# b g
# e
# c f
# """
Given the node locations
| node | lat | lon |
| a | 38.9113 | -77.0091 |
| b | 38.9108 | -77.0091 |
| c | 38.9104 | -77.0091 |
| d | 38.9110 | -77.0096 |
| e | 38.9106 | -77.0086 |
| f | 38.9105 | -77.0090 |
| g | 38.9108 | -77.0090 |
| h | 38.9113 | -77.0090 |
And the ways
| nodes | oneway | name |
| ab | yes | cap south |
| bc | yes | cap south |
| fg | yes | cap north |
| gh | yes | cap north |
| db | no | florida nw |
| bg | no | florida |
| ge | no | florida ne |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ab | bg | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
| restriction | fg | bg | g | no_left_turn @ (Mo-Fr 06:00-10:00) |
| restriction | bg | bc | b | no_left_turn @ (Mo-Fr 07:00-09:30,16:00-18:30) |
When I route I should get
| from | to | route | turns |
| a | e | cap south,florida,florida ne | depart,turn left,arrive |
| f | d | cap north,florida ne,florida ne,florida nw | depart,turn sharp right,continue uturn,arrive |
| e | c | florida ne,cap south,cap south | depart,turn left,arrive |
@only_turning @conditionals
Scenario: Car - Restriction is always off when point not found in timezone files
# same test as the following one, but given a different time zone file
Given the extract extra arguments "--parse-conditional-restrictions"
# 9am UTC, 10am BST
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493802000"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/dc.geojson --parse-conditionals-from-now=1493802000"
# """
# a
# e
# b
# d
# c
# """
Given the node locations
| node | lat | lon |
| a | 51.5250 | -0.1166 |
| b | 51.5243 | -0.1159 |
| c | 51.5238 | -0.1152 |
| d | 51.5241 | -0.1167 |
| e | 51.5247 | -0.1153 |
And the ways
| nodes | name |
| ab | albic |
| bc | albic |
| db | dobe |
| be | dobe |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ab | be | b | only_left_turn @ (Mo-Fr 07:00-11:00) |
When I route I should get
| from | to | route | turns |
| a | c | albic,albic | depart,arrive |
| a | e | albic,dobe,dobe | depart,turn left,arrive |
@only_turning @conditionals
Scenario: Car - Somewhere in london, the UK, GMT timezone
Given the extract extra arguments "--parse-conditional-restrictions"
# 9am UTC, 10am BST
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
# """
# a
# e
# b
# d
# c
# """
Given the node locations
| node | lat | lon |
| a | 51.5250 | -0.1166 |
| b | 51.5243 | -0.1159 |
| c | 51.5238 | -0.1152 |
| d | 51.5241 | -0.1167 |
| e | 51.5247 | -0.1153 |
And the ways
| nodes | name |
| ab | albic |
| bc | albic |
| db | dobe |
| be | dobe |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ab | be | b | only_left_turn @ (Mo-Fr 07:00-11:00) |
When I route I should get
| from | to | route | turns |
| a | c | albic,dobe,dobe,albic,albic | depart,turn left,continue uturn,turn left,arrive |
| a | e | albic,dobe,dobe | depart,turn left,arrive |
@only_turning @conditionals
Scenario: Car - Somewhere in London, the UK, GMT timezone
Given the extract extra arguments "--parse-conditional-restrictions=1"
# 9am UTC, 10am BST
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/london.geojson --parse-conditionals-from-now=1493802000"
# """
# a
# e
# b
# d
# c
# """
Given the node locations
| node | lat | lon |
| a | 51.5250 | -0.1166 |
| b | 51.5243 | -0.1159 |
| c | 51.5238 | -0.1152 |
| d | 51.5241 | -0.1167 |
| e | 51.5247 | -0.1153 |
And the ways
| nodes | name |
| ab | albic |
| bc | albic |
| db | dobe |
| be | dobe |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | ab | be | b | only_left_turn @ (Mo-Fr 07:00-11:00) |
When I route I should get
| from | to | route | turns |
| a | c | albic,dobe,dobe,albic,albic | depart,turn left,continue uturn,turn left,arrive |
| a | e | albic,dobe,dobe | depart,turn left,arrive |
+2 -2
View File
@@ -60,8 +60,8 @@ Feature: Basic Routing
| bc | | 101 |
When I route I should get
| waypoints | route | summary |
| a,c | road, | road, 101 |
| waypoints | route | summary |
| a,c | road,, | road, 101 |
Scenario: Only Refs
Given the node map
@@ -0,0 +1,39 @@
@routing @car @traffic_light
Feature: Car - Handle traffic lights
Background:
Given the profile "car"
Scenario: Car - Encounters a traffic light
Given the node map
"""
a-1-b-2-c
d-3-e-4-f
g-h-i k-l-m
| |
j n
"""
And the ways
| nodes | highway |
| abc | primary |
| def | primary |
| ghi | primary |
| klm | primary |
| hj | primary |
| ln | primary |
And the nodes
| node | highway |
| e | traffic_signals |
| l | traffic_signals |
When I route I should get
| from | to | time | # |
| 1 | 2 | 11.1s | no turn with no traffic light |
| 3 | 4 | 13.1s | no turn with traffic light |
| g | j | 18.7s | turn with no traffic light |
| k | n | 20.7s | turn with traffic light |
@@ -48,7 +48,6 @@ Feature: Traffic - turn penalties
| mn | primary |
| mp | primary |
And the profile "car"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting not based on turn penalty file
When I route I should get
+33
View File
@@ -0,0 +1,33 @@
@routing @via
Feature: Via points
Background:
Given the profile "car"
# See issue #1896
Scenario: Via point at a dead end with barrier
Given the profile "car"
Given the node map
"""
a b c
1
d
f e
"""
And the nodes
| node | barrier |
| d | bollard |
And the ways
| nodes |
| abc |
| bd |
| afed |
When I route I should get
| waypoints | route |
| a,1,c | abc,bd,bd,bd,bd,abc,abc |
| c,1,a | abc,bd,bd,bd,bd,abc,abc |
+25 -1
View File
@@ -51,7 +51,6 @@ Feature: Car - weights
| cd | primary | yes |
| be | service | yes |
| ec | service | yes |
And the extract extra arguments "--generate-edge-lookup"
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
@@ -62,3 +61,28 @@ Feature: Car - weights
| from | to | route | speed | weight |
| a | d | ab,bc,cd,cd | 65 km/h | 44.4 |
| a | e | ab,be,be | 14 km/h | 112 |
Scenario: Distance weights
Given the profile file "car" extended with
"""
api_version = 1
properties.weight_name = 'distance'
"""
Given the node map
"""
a---b---c
|
d
"""
And the ways
| nodes |
| abc |
| bd |
When I route I should get
| waypoints | bearings | route | distance | weights | times |
| a,b | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
| b,c | 90 90 | abc,abc | 200m | 200,0 | 11.1s,0s |
| a,d | 90 180 | abc,bd,bd | 399.9m | 200,200,0 | 13.2s,11.1s,0s |
+36
View File
@@ -1019,3 +1019,39 @@ Feature: Collapse
| a,g | road,cross,cross | depart,fork left,arrive | a,b,g |
| a,e | road,road,road | depart,fork slight right,arrive | a,b,e |
| a,f | road,road,cross,cross | depart,fork slight right,turn right,arrive | a,b,d,f |
# http://www.openstreetmap.org/way/92415447 #3933
Scenario: Use total angle for turn instruction if entry step has large distance
# """
# kf-_ a
# | - b
# | c
# |d
# e
# |
# i
# """
And the node locations
| node | lat | lon | #id |
| a | -33.9644254 | 151.1378673 | 33226063 |
| b | -33.9644373 | 151.1377172 | 1072787030 |
| c | -33.9644791 | 151.1374452 | 4222903609 |
| d | -33.9645661 | 151.1372654 | 4222903610 |
| e | -33.9646986 | 151.1371539 | 4222903611 |
| f | -33.964386 | 151.1372133 | 1072786875 |
| i | -33.9661796 | 151.1368491 | 2781176918 |
| k | -33.9643781 | 151.1371422 | 1684173853 |
And the ways
| nodes | highway | name | oneway | #id |
| ab | trunk | President Avenue | yes | 92415447 |
| bcde | trunk | President Avenue | yes | 422534457 |
| bf | trunk | President Avenue | yes | 447779786 |
| fk | trunk | President Avenue | yes | 179293012 |
| fei | trunk | Princes Highway | yes | 130099670 |
When I route I should get
| waypoints | route | turns | locations |
| a,i | President Avenue,Princes Highway,Princes Highway | depart,turn left,arrive | a,b,i |
@@ -37,3 +37,37 @@ Feature: Basic Roundabout
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
# https://www.openstreetmap.org/way/223225602
Scenario: Enter and Exit with changing mode
Given the node map
"""
a
b
h g c d
e
f
"""
And the ways
| nodes | junction | highway |
| ab | | residential |
| cd | | residential |
| ef | | footway |
| gh | | footway |
| bgecb | roundabout | residential |
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,ef | depart,roundabout turn left exit-1,notification right,arrive |
| a,h | ab,bgecb,gh,gh | depart,roundabout turn right exit-1,notification right,arrive |
| d,f | cd,ef,ef,ef | depart,roundabout turn sharp left exit-2,notification right,arrive |
| d,h | cd,gh,gh,gh | depart,roundabout turn left exit-2,notification right,arrive |
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
| f,h | ef,gh,gh,gh | depart,roundabout turn sharp left exit-3,notification right,arrive |
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout turn left exit-2,arrive |
| h,d | gh,cd,cd | depart,roundabout turn straight exit-1,arrive |
| h,f | gh,bgecb,ef,ef | depart,roundabout turn right exit-1,notification right,arrive |
+165
View File
@@ -222,6 +222,43 @@ Feature: Basic Roundabout
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
Scenario: Mixed Entry and Exit - clockwise order
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 |
| behkb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-3,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
Scenario: Mixed Entry and Exit - segregated roads, different names
Given the node map
"""
@@ -681,3 +718,131 @@ Feature: Basic Roundabout
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
| u,s | ug,ds,ds | depart,roundabout-exit-4,arrive |
| u,t | ug,ft,ft | depart,roundabout-exit-5,arrive |
@3762
Scenario: Only Enter
Given the node map
"""
a
b
i c e ~ ~ ~ f - h
j d
k g
"""
And the ways
| nodes | junction | route |
| ab | | |
| ef | | ferry |
| fh | | |
| dg | | |
| ic | | |
| jk | | |
| bcjdeb | roundabout | |
When I route I should get
| waypoints | route | turns |
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
Scenario: Drive through roundabout
Given the node map
"""
a
b e d f
c
g h
"""
And the ways
| nodes | junction | oneway |
| abcda | roundabout | yes |
| edf | | |
| gch | | yes |
When I route I should get
| waypoints | bearings | route | turns |
| e,f | 90 90 | edf,edf,edf | depart,roundabout-exit-1,arrive |
| e,h | 90 135 | edf,gch,gch | depart,roundabout-exit-2,arrive |
| g,f | 45 90 | gch,edf,edf | depart,roundabout-exit-2,arrive |
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |
Scenario: CCW and CW roundabouts with overlaps
Given the node map
"""
a d g h
b c j i
f e k l
"""
And the ways
| nodes | highway | junction |
| abcda | tertiary | roundabout |
| ed | tertiary | |
| af | tertiary | |
| ghijg | tertiary | roundabout |
| kg | tertiary | |
| hl | tertiary | |
When I route I should get
| from | to | route | turns | distance |
| e | f | ed,af,af | depart,roundabout-exit-1,arrive | 80.1m |
| f | e | af,ed,ed | depart,roundabout-exit-1,arrive | 120.1m |
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |
@4030 @4075
Scenario: Service roundabout with service exits
Given the node map
"""
g a d f
h b1c e
"""
And the ways
| nodes | highway | junction |
| abcda | service | roundabout |
| ce | service | |
| df | service | |
| ag | tertiary | |
| bh | service | |
When I route I should get
| from | to | route | turns |
| 1 | e | abcda,ce,ce | depart,roundabout-exit-1,arrive |
| 1 | f | abcda,df,df | depart,roundabout-exit-2,arrive |
| 1 | g | abcda,ag,ag | depart,roundabout-exit-3,arrive |
| 1 | h | abcda,bh,bh | depart,roundabout-exit-4,arrive |
Scenario: Collapsing a sliproad step after roundabouts
Given the node map
"""
a r j
eb1ds ufghl
`i
c t
m v k
"""
And the ways
| nodes | highway | junction | oneway | # |
| abcda | tertiary | roundabout | | circle |
| ebds | tertiary | | | road |
| cm | tertiary | | | |
| ds | tertiary | | | road |
| rstur | tertiary | roundabout | | circle2 |
| ufghl | tertiary | | | road |
| tv | tertiary | | | |
| gi | tertiary | | yes | sliproad |
| jhik | tertiary | | | crossroad |
When I route I should get
| from | to | route | turns | distance |
| e | k | ebds,ebds,ds,ufghl,jhik,jhik | depart,rotary-exit-1,rotary-exit-1,rstur-exit-2,turn right,arrive | 189.1m |
| 1 | k | ebds,ds,ufghl,jhik,jhik | depart,rotary-exit-1,rstur-exit-2,turn right,arrive | 159.1m |
+2 -2
View File
@@ -134,7 +134,7 @@ Feature: Turn Lane Guidance
| 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 |
| 1 | a | 90,2 270,2 | in,in,in | depart,continue 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
@@ -629,7 +629,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,left,left | depart,turn left,arrive | ,left:true left:true left:true straight:false straight:false, |
| a,e | road,road,road | depart,turn uturn,arrive | ,left:true left:false left:false straight:false straight:false, |
| a,e | road,road,road | depart,continue uturn,arrive | ,left:true left:false left:false straight:false straight:false, |
| a,g | road,straight,straight | depart,new name straight,arrive | ,left:false left:false left:false straight:true straight:true, |
@todo @roundabout
+59
View File
@@ -1260,3 +1260,62 @@ Feature: Simple Turns
| waypoints | route | turns |
| a,d | Goethe,Fried,Fried | depart,continue left,arrive |
| a,g | Goethe,Fried,Fried | depart,turn right,arrive |
# Conflicting roads (https://www.openstreetmap.org/export#map=19/37.57805/-77.46049)
Scenario: Turning at forklike structure
Given the node map
"""
c d
- - - b - - - a
-
e
"""
And the ways
| nodes | name | oneway | highway |
| abc | foo | no | residential |
| bd | bar | yes | residential |
| eb | some | yes | tertiary_link |
When I route I should get
| waypoints | route | turns |
| a,d | foo,bar,bar | depart,turn slight right,arrive |
Scenario: UTurn onto ramp
Given the node map
"""
a - - - b - c
.|
_________________ de
h-g-----------------------f
"""
And the ways
| nodes | name | ref | oneway | highway |
| abc | Road | | yes | primary |
| ce | other | | yes | primary |
| cdg | | | yes | motorway_link |
| fgh | | C 42 | yes | motorway |
When I route I should get
| waypoints | route | ref | turns |
| a,h | Road,,, | ,,C 42,C 42 | depart,on ramp right,merge slight left,arrive |
Scenario: UTurn onto ramp (same ref)
Given the node map
"""
a - - - b - c
.|
_________________ de
h-g-----------------------f
"""
And the ways
| nodes | name | ref | oneway | highway |
| abc | Road | C 42 | yes | primary |
| ce | other | | yes | primary |
| cdg | | | yes | motorway_link |
| fgh | | C 42 | yes | motorway |
When I route I should get
| waypoints | route | ref | turns |
| a,h | Road,,, | C 42,,C 42,C 42 | depart,on ramp right,merge slight left,arrive |
@@ -1,4 +1,5 @@
@contract @options @edge-weight-updates-over-factor
# Broken see issue #4065
@contract @options @edge-weight-updates-over-factor @todo
Feature: osrm-contract command line option: edge-weight-updates-over-factor
Background: Log edge weight updates over given factor
@@ -20,11 +21,30 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
And the data has been saved to disk
Scenario: Logging weight with updates over factor of 2, long segment
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
When I run "osrm-extract --profile {profile_file} {osm_file}"
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
Then stderr should not contain "Speed values were used to update 2 segment(s)"
And stderr should contain "Segment: 1,2"
And stderr should contain "Segment: 1,3"
And I route I should get
| from | to | route | speed |
| a | b | ab,ab | 100 km/h |
| a | c | ac,ac | 100 km/h |
Scenario: Logging using weigts as durations for non-duration profile
Given the profile file "testbot" extended with
"""
properties.weight_name = 'steps'
function way_function(way, result)
result.forward_mode = mode.driving
result.backward_mode = mode.driving
result.weight = 1
result.duration = 1
end
"""
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file}"
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"
+1 -1
View File
@@ -14,5 +14,5 @@ Feature: osrm-routed command line options: invalid options
Scenario: osrm-routed - Missing file
When I try to run "osrm-routed over-the-rainbow.osrm"
Then stderr should contain "over-the-rainbow.osrm"
And stderr should contain "not found"
And stderr should contain "Required files are missing"
And it should exit with an error
+3 -11
View File
@@ -32,9 +32,7 @@ Feature: Raster - weights
Scenario: Weighting not based on raster sources
Given the profile "testbot"
When I run "osrm-extract {osm_file} -p {profile_file}"
And I run "osrm-contract {processed_file}"
And I route I should get
When I route I should get
| from | to | route | speed |
| a | b | ab,ab | 36 km/h |
| a | c | ab,bc,bc | 36 km/h |
@@ -44,10 +42,7 @@ Feature: Raster - weights
Scenario: Weighting based on raster sources
Given the profile "rasterbot"
When I run "osrm-extract {osm_file} -p {profile_file}"
Then stdout should contain "evaluating segment"
And I run "osrm-contract {processed_file}"
And I route I should get
When I route I should get
| from | to | route | speed |
| a | b | ab,ab | 8 km/h |
| b | a | ab,ab | 22 km/h |
@@ -63,10 +58,7 @@ Feature: Raster - weights
Scenario: Weighting based on raster sources
Given the profile "rasterbotinterp"
When I run "osrm-extract {osm_file} -p {profile_file}"
Then stdout should contain "evaluating segment"
And I run "osrm-contract {processed_file}"
And I route I should get
When I route I should get
| from | to | route | speed |
| a | b | ab,ab | 8 km/h |
| a | c | ad,dc,dc | 15 km/h |
+7 -7
View File
@@ -38,7 +38,7 @@ module.exports = function () {
callback();
});
this.Given(/^the origin ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)$/, (lat, lon, callback) => {
this.Given(/^the origin ([-+]?[0-9]*\.?[0-9]+),([-+]?[0-9]*\.?[0-9]+)$/, (lon, lat, callback) => {
this.setOrigin([parseFloat(lon), parseFloat(lat)]);
callback();
});
@@ -67,7 +67,7 @@ module.exports = function () {
if (this.nameNodeHash[name]) throw new Error(util.format('*** duplicate node %s', name));
this.addOSMNode(name, lonLat[0], lonLat[1], null);
} else if (name.match(/[0-9]/) ) {
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s'), name);
if (this.locationHash[name]) throw new Error(util.format('*** duplicate node %s', name));
this.addLocation(name, lonLat[0], lonLat[1], null);
}
cb();
@@ -89,7 +89,7 @@ module.exports = function () {
let addNodeLocations = (row, cb) => {
let name = row.node;
if (this.findNodeByName(name)) throw new Error(util.format('*** duplicate node %s'), name);
if (this.findNodeByName(name)) throw new Error(util.format('*** duplicate node %s', name));
if (name.match(/[a-z]/)) {
let id = row.id && parseInt(row.id);
@@ -194,19 +194,19 @@ module.exports = function () {
isColonSeparated = key.match(/^(.*):(.*)/);
if (isNode) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => {
if (nodeName.length !== 1) throw new Error(util.format('*** invalid relation node member "%s"'), nodeName);
if (nodeName.length !== 1) throw new Error(util.format('*** invalid relation node member "%s"', nodeName));
let node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown relation node member "%s"'), nodeName);
if (!node) throw new Error(util.format('*** unknown relation node member "%s"', nodeName));
relation.addMember('node', node.id, isNode[1]);
});
} else if (isWay) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((wayName) => {
let way = this.findWayByName(wayName);
if (!way) throw new Error(util.format('*** unknown relation way member "%s"'), wayName);
if (!way) throw new Error(util.format('*** unknown relation way member "%s"', wayName));
relation.addMember('way', way.id, isWay[1]);
});
} else if (isColonSeparated && isColonSeparated[1] !== 'restriction') {
throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"'), isColonSeparated[1], isColonSeparated[2]);
throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"', isColonSeparated[1], isColonSeparated[2]));
} else {
relation.addTag(key, row[key]);
}
+6 -4
View File
@@ -16,10 +16,13 @@ module.exports = function () {
var headers = new Set(table.raw()[0]);
got.code = 'unknown';
if (res.body.length) {
json = JSON.parse(res.body);
got.code = json.code;
}
if (headers.has('status')) {
got.status = json.status.toString();
}
@@ -33,7 +36,7 @@ module.exports = function () {
got['#'] = row['#'];
}
var subMatchings = [],
var subMatchings = [''],
turns = '',
route = '',
duration = '',
@@ -175,8 +178,7 @@ module.exports = function () {
if (headers.has('matchings')) {
if (subMatchings.length != row.matchings.split(',').length) {
ok = false;
cb(new Error('*** table matchings and api response are not the same'));
return cb(new Error('*** table matchings and api response are not the same'));
}
row.matchings.split(',').forEach((sub, si) => {
@@ -226,7 +228,7 @@ module.exports = function () {
for (var i=0; i<row.trace.length; i++) {
var n = row.trace[i],
node = this.findNodeByName(n);
if (!node) throw new Error(util.format('*** unknown waypoint node "%s"'), n);
if (!node) throw new Error(util.format('*** unknown waypoint node "%s"', n));
trace.push(node);
}
if (row.timestamps) {
+2 -2
View File
@@ -6,10 +6,10 @@ module.exports = function () {
if (e) return callback(e);
var testRow = (row, ri, cb) => {
var inNode = this.findNodeByName(row.in);
if (!inNode) throw new Error(util.format('*** unknown in-node "%s"'), row.in);
if (!inNode) throw new Error(util.format('*** unknown in-node "%s"', row.in));
var outNode = this.findNodeByName(row.out);
if (!outNode) throw new Error(util.format('*** unknown out-node "%s"'), row.out);
if (!outNode) throw new Error(util.format('*** unknown out-node "%s"', row.out));
this.requestNearest(inNode, this.queryParams, (err, response) => {
if (err) return cb(err);
+2 -1
View File
@@ -121,11 +121,12 @@ module.exports = function () {
r.which = dir;
this.requestRoute((dir === 'forw' ? [a, b] : [b, a]), [], this.queryParams, (err, res, body) => {
this.requestRoute((dir === 'forw' ? [a, b] : [b, a]), [], [], this.queryParams, (err, res, body) => {
if (err) return callback(err);
r.query = this.query;
r.json = JSON.parse(body);
r.code = r.json.code;
r.status = res.statusCode === 200 ? 'x' : null;
if (r.status) {
r.route = this.wayList(r.json.routes[0]);
+5 -3
View File
@@ -29,8 +29,10 @@ module.exports = function () {
}
var json;
got.code = 'unknown';
if (res.body.length) {
json = JSON.parse(res.body);
got.code = json.code;
}
if (headers.has('status')) {
@@ -153,11 +155,11 @@ module.exports = function () {
if (row.source) {
params.source = got.source = row.source;
}
}
if (row.destination) {
params.destination = got.destination = row.destination;
}
}
if (row.hasOwnProperty('roundtrip')) { //roundtrip is a boolean so row.roundtrip alone doesn't work as a check here
params.roundtrip = got.roundtrip = row.roundtrip;
+1 -1
View File
@@ -243,8 +243,8 @@ module.exports = function () {
processedCacheFile: this.processedCacheFile, environment: this.environment};
let queue = d3.queue(1);
queue.defer(this.extractData.bind(this), p);
queue.defer(this.contractData.bind(this), p);
queue.defer(this.partitionData.bind(this), p);
queue.defer(this.contractData.bind(this), p);
queue.defer(this.customizeData.bind(this), p);
queue.awaitAll(callback);
};
+2 -1
View File
@@ -39,7 +39,8 @@ module.exports = function () {
this.WAY_SPACING = 100;
this.DEFAULT_GRID_SIZE = 100; // meters
// get algorithm name from the command line profile argument
this.ROUTING_ALGORITHM = process.argv[process.argv.indexOf('-p') + 1] === 'mld' ? 'MLD' : 'CH';
this.ROUTING_ALGORITHM = process.argv[process.argv.indexOf('-p') + 1].match('mld') ? 'MLD' : 'CH';
this.TIMEZONE_NAMES = this.PLATFORM_WINDOWS ? 'win' : 'iana';
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
+9 -1
View File
@@ -46,8 +46,9 @@ module.exports = function () {
return waypoints.map(w => [w.lon, w.lat].map(ensureDecimal).join(','));
};
this.requestRoute = (waypoints, bearings, userParams, callback) => {
this.requestRoute = (waypoints, bearings, approaches, userParams, callback) => {
if (bearings.length && bearings.length !== waypoints.length) throw new Error('*** number of bearings does not equal the number of waypoints');
if (approaches.length && approaches.length !== waypoints.length) throw new Error('*** number of approaches does not equal the number of waypoints');
var defaults = {
output: 'json',
@@ -67,6 +68,9 @@ module.exports = function () {
}).join(';');
}
if (approaches.length) {
params.approaches = approaches.join(';');
}
return this.requestPath('route', params, callback);
};
@@ -163,6 +167,10 @@ module.exports = function () {
('out' in s.intersections[0] ? s.intersections[0].bearings[s.intersections[0].out] : 0));
};
this.approachList = (instructions) => {
return this.extractInstructionList(instructions, s => s.approaches || '');
};
this.annotationList = (instructions) => {
if (!('annotation' in instructions.legs[0]))
return '';
+2 -1
View File
@@ -15,7 +15,8 @@ module.exports = function () {
'{profile_file}': this.profileFile,
'{rastersource_file}': this.rasterCacheFile,
'{speeds_file}': this.speedsCacheFile,
'{penalties_file}': this.penaltiesCacheFile
'{penalties_file}': this.penaltiesCacheFile,
'{timezone_names}': this.TIMEZONE_NAMES
};
for (let k in table) {
+113 -100
View File
@@ -35,10 +35,12 @@ module.exports = function () {
if (err) return cb(err);
if (body && body.length) {
let destinations, pronunciations, instructions, refs, bearings, turns, modes, times,
distances, summary, intersections, lanes, locations, annotation, weight_name, weights;
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
let json = JSON.parse(body);
got.code = json.code;
let hasRoute = json.code === 'Ok';
if (hasRoute) {
@@ -58,6 +60,7 @@ module.exports = function () {
annotation = this.annotationList(json.routes[0]);
weight_name = this.weightName(json.routes[0]);
weights = this.weightList(json.routes[0]);
approaches = this.approachList(json.routes[0]);
}
if (headers.has('status')) {
@@ -79,102 +82,106 @@ module.exports = function () {
if (headers.has('route')) {
got.route = (instructions || '').trim();
if (headers.has('summary')) {
got.summary = (summary || '').trim();
}
if (headers.has('alternative')) {
// TODO examine more than first alternative?
got.alternative ='';
if (json.routes && json.routes.length > 1)
got.alternative = this.wayList(json.routes[1]);
}
var distance = hasRoute && json.routes[0].distance,
time = hasRoute && json.routes[0].duration,
weight = hasRoute && json.routes[0].weight;
if (headers.has('distance')) {
if (row.distance.length) {
if (!row.distance.match(/\d+m/))
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
got.distance = instructions ? util.format('%dm', distance) : '';
} else {
got.distance = '';
}
}
if (headers.has('weight')) {
if (row.weight.length) {
if (!row.weight.match(/[\d\.]+/))
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
got.weight = instructions ? util.format('%d', weight) : '';
} else {
got.weight = '';
}
}
if (headers.has('time')) {
if (!row.time.match(/\d+s/))
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
got.time = instructions ? util.format('%ds', time) : '';
}
if (headers.has('lanes')) {
got.lanes = (lanes || '').trim();
}
if (headers.has('speed')) {
if (row.speed !== '' && instructions) {
if (!row.speed.match(/\d+ km\/h/))
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
got.speed = util.format('%d km/h', speed);
} else {
got.speed = '';
}
}
if (headers.has('intersections')) {
got.intersections = (intersections || '').trim();
}
if (headers.has('locations')){
got.locations = (locations || '').trim();
}
// if header matches 'a:*', parse out the values for *
// and return in that header
headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) {
let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1)
return cb(new Error('Unrecognized annotation field', a_type));
if (annotation && !annotation[a_type])
return cb(new Error('Annotation not found in response', a_type));
got[k] = annotation && annotation[a_type] || '';
}
});
var putValue = (key, value) => {
if (headers.has(key)) got[key] = instructions ? value : '';
};
putValue('ref', refs);
putValue('bearing', bearings);
putValue('turns', turns);
putValue('modes', modes);
putValue('times', times);
putValue('distances', distances);
putValue('pronunciations', pronunciations);
putValue('destinations', destinations);
putValue('weight_name', weight_name);
putValue('weights', weights);
putValue('weight', weight);
}
if (headers.has('summary')) {
got.summary = (summary || '').trim();
}
if (headers.has('alternative')) {
// TODO examine more than first alternative?
got.alternative ='';
if (json.routes && json.routes.length > 1)
got.alternative = this.wayList(json.routes[1]);
}
var distance = hasRoute && json.routes[0].distance,
time = hasRoute && json.routes[0].duration,
weight = hasRoute && json.routes[0].weight;
if (headers.has('distance')) {
if (row.distance.length) {
if (!row.distance.match(/\d+m/))
return cb(new Error('*** Distance must be specified in meters. (ex: 250m)'));
got.distance = instructions ? util.format('%dm', distance) : '';
} else {
got.distance = '';
}
}
if (headers.has('weight')) {
if (row.weight.length) {
if (!row.weight.match(/[\d\.]+/))
return cb(new Error('*** Weight must be specified as a numeric value. (ex: 8)'));
got.weight = instructions ? util.format('%d', weight) : '';
} else {
got.weight = '';
}
}
if (headers.has('time')) {
if (!row.time.match(/\d+s/))
return cb(new Error('*** Time must be specied in seconds. (ex: 60s)'));
got.time = instructions ? util.format('%ds', time) : '';
}
if (headers.has('lanes')) {
got.lanes = (lanes || '').trim();
}
if (headers.has('speed')) {
if (row.speed !== '' && instructions) {
if (!row.speed.match(/\d+ km\/h/))
cb(new Error('*** Speed must be specied in km/h. (ex: 50 km/h)'));
var speed = time > 0 ? Math.round(3.6*distance/time) : null;
got.speed = util.format('%d km/h', speed);
} else {
got.speed = '';
}
}
if (headers.has('intersections')) {
got.intersections = (intersections || '').trim();
}
if (headers.has('locations')){
got.locations = (locations || '').trim();
}
/*
if (headers.has('approaches')){
got.approaches = (approaches || '').trim();
}*/
// if header matches 'a:*', parse out the values for *
// and return in that header
headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) {
let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1)
return cb(new Error('Unrecognized annotation field', a_type));
if (annotation && !annotation[a_type])
return cb(new Error('Annotation not found in response', a_type));
got[k] = annotation && annotation[a_type] || '';
}
});
var putValue = (key, value) => {
if (headers.has(key)) got[key] = instructions ? value : '';
};
putValue('ref', refs);
putValue('bearing', bearings);
putValue('turns', turns);
putValue('modes', modes);
putValue('times', times);
putValue('distances', distances);
putValue('pronunciations', pronunciations);
putValue('destinations', destinations);
putValue('weight_name', weight_name);
putValue('weights', weights);
putValue('weight', weight);
putValue('approach', approaches);
for (var key in row) {
if (this.FuzzyMatch.match(got[key], row[key])) {
got[key] = row[key];
@@ -208,25 +215,31 @@ module.exports = function () {
var params = this.overwriteParams(defaultParams, userParams),
waypoints = [],
bearings = [];
bearings = [],
approaches = [];
if (row.bearings) {
got.bearings = row.bearings;
bearings = row.bearings.split(' ').filter(b => !!b);
}
if (row.approaches) {
got.approaches = row.approaches;
approaches = row.approaches.split(' ').filter(b => !!b);
}
if (row.from && row.to) {
var fromNode = this.findNodeByName(row.from);
if (!fromNode) return cb(new Error(util.format('*** unknown from-node "%s"'), row.from));
if (!fromNode) return cb(new Error(util.format('*** unknown from-node "%s"', row.from)));
waypoints.push(fromNode);
var toNode = this.findNodeByName(row.to);
if (!toNode) return cb(new Error(util.format('*** unknown to-node "%s"'), row.to));
if (!toNode) return cb(new Error(util.format('*** unknown to-node "%s"', row.to)));
waypoints.push(toNode);
got.from = row.from;
got.to = row.to;
this.requestRoute(waypoints, bearings, params, afterRequest);
this.requestRoute(waypoints, bearings, approaches, params, afterRequest);
} else if (row.waypoints) {
row.waypoints.split(',').forEach((n) => {
var node = this.findNodeByName(n.trim());
@@ -234,7 +247,7 @@ module.exports = function () {
waypoints.push(node);
});
got.waypoints = row.waypoints;
this.requestRoute(waypoints, bearings, params, afterRequest);
this.requestRoute(waypoints, bearings, approaches, params, afterRequest);
} else {
return cb(new Error('*** no waypoints'));
}
+35
View File
@@ -30,3 +30,38 @@ Feature: Alternative route
| 3 | 4 | bd,dc,ca,ab,bd,bd | |
| 5 | 6 | dc,ca,ab,bd,dc,dc | |
| 7 | 8 | ca,ab,bd,dc,ca,ca | |
@4111
Scenario: Alternative Loop Paths with single node path
Given the node map
"""
a1b2c3d
e f
"""
And the ways
| nodes | maxspeed |
| ab | 30 |
| bc | 3 |
| cd | 30 |
| ae | 30 |
| ef | 30 |
| fd | 30 |
And the query options
| alternatives | true |
When I route I should get
| from | to | route | alternative |
| b | c | bc,bc | ab,ae,ef,fd,cd,cd |
#| c | b | bc,bc | cd,fd,ef,ae,ab,ab | # alternative path depends on phantom snapping order
| 1 | c | ab,bc,bc | ab,ae,ef,fd,cd,cd |
#| c | 1 | bc,ab | cd,fd,ef,ae,ab | # alternative path depends on phantom snapping order
| 2 | c | bc,bc | |
| c | 2 | bc,bc | |
| 1 | 3 | ab,ae,ef,fd,cd | ab,bc,cd |
#| 3 | 1 | cd,fd,ef,ae,ab | cd,bc,ab | # alternative path depends on phantom snapping order
| b | 3 | bc,cd | ab,ae,ef,fd,cd |
#| 3 | b | cd,bc,bc | cd,fd,ef,ae,ab,ab | # alternative path depends on phantom snapping order
+5
View File
@@ -12,6 +12,7 @@ Feature: Testbot - Handle ferry routes
i j k l
m n o p
q r s t
u v w x
"""
And the ways
@@ -26,11 +27,14 @@ Feature: Testbot - Handle ferry routes
| op | primary | | |
| qr | primary | | |
| st | primary | | |
| uv | primary | | |
| wx | primary | | |
| bc | | ferry | 0:01 |
| fg | | ferry | 0:10 |
| jk | | ferry | 1:00 |
| no | | ferry | 24:00 |
| rs | | ferry | 96:00 |
| vw | | ferry | P5D |
When I route I should get
| from | to | route | time |
@@ -39,6 +43,7 @@ Feature: Testbot - Handle ferry routes
| j | k | jk,jk | 3600s +-1 |
| n | o | no,no | 86400s +-1 |
| r | s | rs,rs | 345600s +-1 |
| v | w | vw,vw | 419430s +-1|
@todo
Scenario: Testbot - Week long ferry routes
+2 -3
View File
@@ -4,7 +4,6 @@ Feature: Basic Map Matching
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Given the extract extra arguments "--generate-edge-lookup"
Given the query options
| geometries | geojson |
@@ -213,7 +212,7 @@ Feature: Basic Map Matching
And the speed file
"""
1,2,36
1,2,36,10
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
@@ -240,7 +239,7 @@ Feature: Basic Map Matching
And the speed file
"""
1,2,36
1,2,36,10
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
+35
View File
@@ -36,3 +36,38 @@ Feature: Projection to nearest point on road
| from | to | route | distance |
| d | b | abc,abc | 0m |
| b | d | abc,abc | 0m |
Scenario: Projection results negative duration
Given the profile file "testbot" extended with
"""
api_version = 1
function segment_function (segment)
segment.weight = 5.5
segment.duration = 2.8
end
"""
Given the node locations
| node | lon | lat |
| e | -51.218994 | -30.023866 |
| f | -51.218918 | -30.023741 |
| 1 | -51.219109 | -30.023766 |
| 2 | -51.219109 | -30.023764 |
| 3 | -51.219109 | -30.023763 |
| 4 | -51.219109 | -30.023762 |
| 5 | -51.219109 | -30.023761 |
| 6 | -51.219109 | -30.023756 |
And the ways
| nodes |
| ef |
When I route I should get
| waypoints | route | distance | time | weight |
| 1,4 | ef,ef | 0.4m | 0.1s | 0.1 |
| 2,4 | ef,ef | 0.1m | 0s | 0 |
| 3,4 | ef,ef | 0.1m | 0s | 0 |
| 4,4 | ef,ef | 0m | 0s | 0 |
| 5,4 | ef,ef | 0.1m | 0s | 0.1 |
| 6,4 | ef,ef | 0.6m | 0.1s | 0.2 |
+56 -41
View File
@@ -2,15 +2,22 @@
Feature: Traffic - speeds
Background: Use specific speeds
# __ a
# / /
#c----b / g
# \ |\/
# \ e/\_.f
# \ | /
# d./
Given the node locations
| node | lat | lon |
| a | 0.1 | 0.1 |
| b | 0.05 | 0.1 |
| c | 0.0 | 0.1 |
| d | 0.05 | 0.03 |
| e | 0.05 | 0.066 |
| f | 0.075 | 0.066 |
| g | 0.075 | 0.1 |
| node | lat | lon | id |
| a | 0.1 | 0.1 | 1 |
| b | 0.05 | 0.1 | 2 |
| c | 0.0 | 0.1 | 3 |
| d | 0.05 | 0.03 | 4 |
| e | 0.05 | 0.066 | 5 |
| f | 0.075 | 0.066 | 6 |
| g | 0.075 | 0.1 | 7 |
And the ways
| nodes | highway |
| ab | primary |
@@ -22,7 +29,6 @@ Feature: Traffic - speeds
| df | primary |
| fb | primary |
And the profile "testbot"
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on speed file
@@ -30,12 +36,12 @@ Feature: Traffic - speeds
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,0
2,1,0
2,3,27
3,2,27
1,4,27
4,1,27
1,2,0,0
2,1,0,0
2,3,27,7.5
3,2,27,7.5
1,4,27,7.5
4,1,27,7.5
"""
And the query options
| annotations | datasources |
@@ -56,12 +62,12 @@ Feature: Traffic - speeds
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,1,20020.7
2,1,1,20020.7
2,3,27,741.5
3,2,27,741.5
1,4,27,1275.7
4,1,27,1275.7
1,2,1,0.2777777
2,1,1
2,3,27
3,2,27,7.5
1,4,27,7.5
4,1,27,7.5
"""
And the query options
| annotations | datasources |
@@ -83,32 +89,32 @@ Feature: Traffic - speeds
api_version = 1
properties.traffic_signal_penalty = 0
properties.u_turn_penalty = 0
properties.weight_precision = 3
properties.weight_precision = 2
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,1,20020.789
2,1,1,20020.123
2,3,27,741.56789
3,2,27,741.3
1,4,1,34445.12
4,1,1,34445.3
1,2,1,0.27777777
2,1,1,0.27777777
2,3,27,7.5
3,2,27
1,4,1
4,1,1
"""
And the query options
| annotations | datasources |
When I route I should get
| from | to | route | speed | weights | a:datasources |
| a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
| b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
| from | to | route | speed | weights | a:datasources |
| a | b | ab,ab | 1 km/h | 20020.73,0 | 1:0 |
| a | c | ab,bc,bc | 2 km/h | 20020.73,741.51,0 | 1:1:0 |
| b | c | bc,bc | 27 km/h | 741.51,0 | 1:0 |
| a | d | ab,eb,de,de | 2 km/h | 20020.73,378.17,400.41,0 | 1:0:0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
| g | b | ab,ab | 1 km/h | 10010.37,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.36,0 | 1 |
| g | a | ab,ab | 1 km/h | 10010.36,0 | 1:1 |
Scenario: Speeds that isolate a single node (a)
@@ -121,10 +127,10 @@ Feature: Traffic - speeds
"""
1,2,0
2,1,0
2,3,27
3,2,27
1,4,0
4,1,0
2,3,27,7.5
3,2,27,7.5
1,4,0,0
4,1,0,0
"""
And the query options
| annotations | true |
@@ -154,3 +160,12 @@ Feature: Traffic - speeds
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And stderr should contain "malformed"
And it should exit with an error
Scenario: Check with an empty speed file
Given the speed file
"""
"""
And the data has been extracted
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
And it should exit successfully
@@ -0,0 +1,30 @@
@routing @speed @traffic
Feature: Traffic - speeds edge cases
Scenario: Weighting based on speed file weights that cause segment weight overflows
Given the node map
"""
a-----b
"""
And the ways
| nodes | highway |
| ab | primary |
And the profile file "testbot" extended with
"""
api_version = 1
properties.traffic_signal_penalty = 0
properties.u_turn_penalty = 0
properties.weight_precision = 2
"""
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,1,0.001
2,1,1,0.001
"""
And the query options
| annotations | datasources |
When I route I should get
| from | to | route | speed | weights | a:datasources |
| a | b | ab,ab | 1 km/h | 41943.02,0 | 1 |
@@ -31,7 +31,6 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
| dg | primary |
And the profile "testbot"
# Since testbot doesn't have turn penalties, a penalty from file of 0 should produce a neutral effect
And the extract extra arguments "--generate-edge-lookup"
Scenario: Weighting based on turn penalty file, with an extreme negative value -- clamps and does not fail
Given the turn penalty file
+36
View File
@@ -0,0 +1,36 @@
@routing @testbot @turn_penalty
Feature: Turn Penalties
Background:
Given the profile "turnbot"
Given a grid size of 200 meters
Scenario: Turns should incur a delay that depend on the angle
Given the node map
"""
c d e
b j f
a s g
"""
And the ways
| nodes |
| sj |
| ja |
| jb |
| jc |
| jd |
| je |
| jf |
| jg |
When I route I should get
| from | to | route | time | distance |
| s | a | sj,ja,ja | 63s +-1 | 483m +-1 |
| s | b | sj,jb,jb | 50s +-1 | 400m +-1 |
| s | c | sj,jc,jc | 54s +-1 | 483m +-1 |
| s | d | sj,jd,jd | 40s +-1 | 400m +-1 |
| s | e | sj,je,je | 53s +-1 | 483m +-1 |
| s | f | sj,jf,jf | 50s +-1 | 400m +-1 |
| s | g | sj,jg,jg | 63s +-1 | 483m +-1 |
+64 -31
View File
@@ -224,34 +224,6 @@ Feature: Via points
| a,d,c | abc,bd,bd,bd,abc,abc |
| c,d,a | abc,bd,bd,bd,abc,abc |
# See issue #1896
Scenario: Via point at a dead end with barrier
Given the profile "car"
Given the node map
"""
a b c
1
d
f e
"""
And the nodes
| node | barrier |
| d | bollard |
And the ways
| nodes |
| abc |
| bd |
| afed |
When I route I should get
| waypoints | route |
| a,1,c | abc,bd,bd,bd,bd,abc,abc |
| c,1,a | abc,bd,bd,bd,bd,abc,abc |
Scenario: Via points on ring on the same oneway, forces one of the vertices to be top node
Given the node map
"""
@@ -349,6 +321,67 @@ Feature: Via points
| ab |
When I route I should get
| waypoints | bearings | route | turns |
| 1,a | 90,2 270,2 | ab,ab,ab | depart,turn uturn,arrive |
| 1,b | 270,2 90,2 | ab,ab,ab | depart,turn uturn,arrive |
| waypoints | bearings | route | turns |
| 1,a | 90,2 270,2 | ab,ab,ab | depart,continue uturn,arrive |
| 1,b | 270,2 90,2 | ab,ab,ab | depart,continue uturn,arrive |
Scenario: Continue Straight in presence of Bearings
Given the node map
"""
h - a 1 b -- g
| |
| |- 2 c - f
| 3
e ------ d - i
|
j
"""
And the query options
| continue_straight | false |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cdea | no |
| ah | yes |
| bg | yes |
| cf | yes |
| di | yes |
| dj | yes |
When I route I should get
| waypoints | bearings | route |
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,cdea,cdea |
Scenario: Continue Straight in presence of Bearings
Given the node map
"""
h - a 1 b -- g
| |
| |- 2 c - f
| 3
e ------ d - i
|
j
"""
And the query options
| continue_straight | true |
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cdea | no |
| ah | yes |
| bg | yes |
| cf | yes |
| di | yes |
| dj | yes |
When I route I should get
| waypoints | bearings | route |
| 1,2,3 | 270,90 180,180 180,180 | ab,cdea,cdea,bc,bc,bc,ab,cdea,cdea,cdea |
+4 -5
View File
@@ -4,7 +4,6 @@ Feature: Weight tests
Background:
Given the profile "testbot"
Given a grid size of 10 meters
Given the extract extra arguments "--generate-edge-lookup"
Given the query options
| geometries | geojson |
@@ -284,8 +283,8 @@ Feature: Weight tests
When I route I should get
| waypoints | route | distance | weights | times |
| a,d | , | 59.9m | 62,0 | 24s,0s |
| a,e | ,, | 60.1m | 68.7,10,0 | 38.5s,11s,0s |
| a,d | , | 59.9m | 20.5,0 | 24s,0s |
| a,e | ,, | 60.1m | 27.2,10,0 | 38.5s,11s,0s |
| d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s |
@traffic @speed
@@ -320,6 +319,6 @@ Feature: Weight tests
When I route I should get
| waypoints | route | distance | weights | times |
| a,d | abcd,abcd | 59.9m | 6.993,0 | 7s,0s |
| a,e | abcd,ce,ce | 60.1m | 6.002,2.002,0 | 6s,2s,0s |
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
+166
View File
@@ -0,0 +1,166 @@
Feature: Check zero speed updates
Background:
Given the profile "testbot"
Scenario: Matching on restricted way, single segment
Given the query options
| geometries | geojson |
| annotations | true |
Given the node map
"""
a-1--b--c-2-d
"""
And the ways
| nodes |
| abcd |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
"""
When I match I should get
| trace | code |
| 12 | NoMatch |
Scenario: Matching restricted way, both segments
Given the node map
"""
a-1--b-2-c
"""
And the ways
| nodes | oneway |
| abc | no |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I match I should get
| trace | code |
| 12 | NoMatch |
Scenario: Matching on restricted oneway
Given the node map
"""
a-1--b-2-c
"""
And the ways
| nodes | oneway |
| abc | yes |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
"""
When I match I should get
| trace | code |
| 12 | NoMatch |
Scenario: Routing on restricted way
Given the node map
"""
a-1-b-2-c
"""
And the ways
| nodes | oneway |
| abc | no |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I route I should get
| from | to | code |
| 1 | 2 | NoRoute |
Scenario: Routing on restricted oneway
Given the node map
"""
a-1-b-2-c
"""
And the ways
| nodes | oneway |
| abc | yes |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I route I should get
| from | to | bearings | code |
| 1 | 2 | 270 270 | NoSegment |
Scenario: Via routing on restricted oneway
Given the node map
"""
a-1-b-2-c-3-d
"""
And the ways
| nodes | oneway |
| abc | no |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,3,0
3,2,0
"""
When I route I should get
| waypoints | code |
| 1,2,3 | NoRoute |
| 3,2,1 | NoRoute |
@trip
Scenario: Trip
Given the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| bc |
| cb |
| da |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,0
2,1,0
"""
When I plan a trip I should get
| waypoints | trips | code |
| a,b,c,d | abcda | NoTrips |
| d,b,c,a | dbcad | NoTrips |
+3 -9
View File
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "contractor/contractor_config.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "util/deallocating_vector.hpp"
#include "util/typedefs.hpp"
@@ -66,14 +66,8 @@ class Contractor
std::vector<bool> &is_core_node,
std::vector<float> &inout_node_levels) const;
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
void WriteNodeLevels(std::vector<float> &&node_levels) const;
void ReadNodeLevels(std::vector<float> &contraction_order) const;
std::size_t
WriteContractedGraph(unsigned number_of_edge_based_nodes,
const util::DeallocatingVector<QueryEdge> &contracted_edge_list);
void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<extractor::EdgeBasedEdge> &edges,
std::vector<extractor::EdgeBasedNode> &nodes) const;
void WriteContractedGraph(unsigned number_of_edge_based_nodes,
util::DeallocatingVector<QueryEdge> contracted_edge_list);
private:
ContractorConfig config;
+6 -6
View File
@@ -1,7 +1,7 @@
#ifndef OSRM_CONTRACTOR_CONTRACTOR_HEAP_HPP_
#define OSRM_CONTRACTOR_CONTRACTOR_HEAP_HPP_
#include "util/binary_heap.hpp"
#include "util/query_heap.hpp"
#include "util/typedefs.hpp"
#include "util/xor_fast_hash_storage.hpp"
@@ -18,11 +18,11 @@ struct ContractorHeapData
bool target = false;
};
using ContractorHeap = util::BinaryHeap<NodeID,
NodeID,
EdgeWeight,
ContractorHeapData,
util::XORFastHashStorage<NodeID, NodeID>>;
using ContractorHeap = util::QueryHeap<NodeID,
NodeID,
EdgeWeight,
ContractorHeapData,
util::XORFastHashStorage<NodeID, NodeID>>;
} // namespace contractor
} // namespace osrm
+69
View File
@@ -0,0 +1,69 @@
#ifndef OSRM_CONTRACTOR_FILES_HPP
#define OSRM_CONTRACTOR_FILES_HPP
#include "contractor/query_graph.hpp"
#include "util/serialization.hpp"
#include "storage/io.hpp"
#include "storage/serialization.hpp"
namespace osrm
{
namespace contractor
{
namespace files
{
// reads .osrm.hsgr file
template <typename QueryGraphT>
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
{
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.ReadInto(checksum);
util::serialization::read(reader, graph);
}
// writes .osrm.hsgr file
template <typename QueryGraphT>
inline void
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
{
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteOne(checksum);
util::serialization::write(writer, graph);
}
// reads .levels file
inline void readLevels(const boost::filesystem::path &path, std::vector<float> &node_levels)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
storage::serialization::read(reader, node_levels);
}
// writes .levels file
inline void writeLevels(const boost::filesystem::path &path, const std::vector<float> &node_levels)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, node_levels);
}
}
}
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef OSRM_CONTRACTOR_QUERY_GRAPH_HPP
#define OSRM_CONTRACTOR_QUERY_GRAPH_HPP
#include "contractor/query_edge.hpp"
#include "util/static_graph.hpp"
#include "util/typedefs.hpp"
namespace osrm
{
namespace contractor
{
namespace detail
{
template <storage::Ownership Ownership>
using QueryGraph = util::StaticGraph<typename QueryEdge::EdgeData, Ownership>;
}
using QueryGraph = detail::QueryGraph<storage::Ownership::Container>;
using QueryGraphView = detail::QueryGraph<storage::Ownership::View>;
}
}
#endif // QUERYEDGE_HPP
+2 -2
View File
@@ -3,7 +3,7 @@
#include "partition/cell_storage.hpp"
#include "partition/multi_level_partition.hpp"
#include "util/binary_heap.hpp"
#include "util/query_heap.hpp"
#include <tbb/enumerable_thread_specific.h>
@@ -24,7 +24,7 @@ class CellCustomizer
public:
using Heap =
util::BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
util::QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
-18
View File
@@ -1,18 +0,0 @@
#ifndef OSRM_CUSTOMIZER_IO_HPP
#define OSRM_CUSTOMIZER_IO_HPP
#include "customizer/edge_based_graph.hpp"
#include "storage/io.hpp"
namespace osrm
{
namespace customizer
{
namespace io
{
}
}
}
#endif
+35 -39
View File
@@ -7,30 +7,36 @@ namespace osrm
{
namespace engine
{
namespace algorithm
namespace routing_algorithms
{
// Contraction Hiearchy
struct CH final
namespace ch
{
struct Algorithm final
{
};
}
// Contraction Hiearchy with core
struct CoreCH final
namespace corech
{
struct Algorithm final
{
};
}
// Multi-Level Dijkstra
struct MLD final
namespace mld
{
struct Algorithm final
{
};
template <typename AlgorithmT> const char *name();
template <> inline const char *name<CH>() { return "CH"; }
template <> inline const char *name<CoreCH>() { return "CoreCH"; }
template <> inline const char *name<MLD>() { return "MLD"; }
}
namespace algorithm_trais
{
// Algorithm names
template <typename AlgorithmT> const char *name();
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
{
@@ -51,62 +57,52 @@ template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
{
};
template <> struct HasAlternativePathSearch<algorithm::CH> final : std::true_type
// Algorithms supported by Contraction Hierarchies
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::CH> final : std::true_type
template <> struct HasShortestPathSearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::CH> final : std::true_type
template <> struct HasDirectShortestPathSearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::CH> final : std::true_type
template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::CH> final : std::true_type
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<algorithm::CH> final : std::true_type
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
{
};
// disbaled because of perfomance reasons
template <> struct HasAlternativePathSearch<algorithm::CoreCH> final : std::false_type
// Algorithms supported by Contraction Hierarchies with core
// the rest is disabled because of performance reasons
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::CoreCH> final : std::false_type
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::CoreCH> final : std::true_type
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::CoreCH> final : std::true_type
{
};
template <> struct HasGetTileTurns<algorithm::CoreCH> final : std::true_type
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
{
};
// disbaled because of perfomance reasons
template <> struct HasAlternativePathSearch<algorithm::MLD> final : std::false_type
// Algorithms supported by Multi-Level Dijkstra
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasManyToManySearch<algorithm::MLD> final : std::false_type
template <> struct HasShortestPathSearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasShortestPathSearch<algorithm::MLD> final : std::false_type
template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<algorithm::MLD> final : std::true_type
{
};
template <> struct HasMapMatching<algorithm::MLD> final : std::false_type
{
};
template <> struct HasGetTileTurns<algorithm::MLD> final : std::false_type
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
{
};
}
+10 -5
View File
@@ -50,14 +50,19 @@ class BaseAPI
{
if (parameters.generate_hints)
{
return json::makeWaypoint(phantom.location,
facade.GetNameForID(phantom.name_id).to_string(),
Hint{phantom, facade.GetCheckSum()});
// TODO: check forward/reverse
return json::makeWaypoint(
phantom.location,
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string(),
Hint{phantom, facade.GetCheckSum()});
}
else
{
return json::makeWaypoint(phantom.location,
facade.GetNameForID(phantom.name_id).to_string());
// TODO: check forward/reverse
return json::makeWaypoint(
phantom.location,
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))
.to_string());
}
}
+6 -1
View File
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ENGINE_API_BASE_PARAMETERS_HPP
#define ENGINE_API_BASE_PARAMETERS_HPP
#include "engine/approach.hpp"
#include "engine/bearing.hpp"
#include "engine/hint.hpp"
#include "util/coordinate.hpp"
@@ -55,6 +56,7 @@ namespace api
* optional per coordinate
* - bearings: limits the search for segments in the road network to given bearing(s) in degree
* towards true north in clockwise direction, optional per coordinate
* - approaches: force the phantom node to start towards the node with the road country side.
*
* \see OSRM, Coordinate, Hint, Bearing, RouteParame, RouteParameters, TableParameters,
* NearestParameters, TripParameters, MatchParameters and TileParameters
@@ -65,6 +67,7 @@ struct BaseParameters
std::vector<boost::optional<Hint>> hints;
std::vector<boost::optional<double>> radiuses;
std::vector<boost::optional<Bearing>> bearings;
std::vector<boost::optional<Approach>> approaches;
// Adds hints to response which can be included in subsequent requests, see `hints` above.
bool generate_hints = true;
@@ -73,9 +76,10 @@ struct BaseParameters
const std::vector<boost::optional<Hint>> hints_ = {},
std::vector<boost::optional<double>> radiuses_ = {},
std::vector<boost::optional<Bearing>> bearings_ = {},
std::vector<boost::optional<Approach>> approaches_ = {},
bool generate_hints_ = true)
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
generate_hints(generate_hints_)
approaches(approaches_), generate_hints(generate_hints_)
{
}
@@ -85,6 +89,7 @@ struct BaseParameters
return (hints.empty() || hints.size() == coordinates.size()) &&
(bearings.empty() || bearings.size() == coordinates.size()) &&
(radiuses.empty() || radiuses.size() == coordinates.size()) &&
(approaches.empty() || approaches.size() == coordinates.size()) &&
std::all_of(bearings.begin(),
bearings.end(),
[](const boost::optional<Bearing> bearing_and_range) {
+8 -7
View File
@@ -80,22 +80,21 @@ inline Result keep_all(const MatchParameters &params)
inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
BOOST_ASSERT(!params.coordinates.empty());
Result result;
result.can_be_removed.resize(params.coordinates.size(), false);
result.tidied_to_original.push_back(0);
std::size_t last_good = 0;
const auto uses_timestamps = !params.timestamps.empty();
Thresholds running{0., 0};
// Walk over adjacent (coord, ts)-pairs, with rhs being the candidate to discard or keep
for (std::size_t current = 0; current < params.coordinates.size() - 1; ++current)
for (std::size_t current = 0, next = 1; next < params.coordinates.size() - 1; ++current, ++next)
{
const auto next = current + 1;
auto distance_delta = util::coordinate_calculation::haversineDistance(
params.coordinates[current], params.coordinates[next]);
running.distance_in_meters += distance_delta;
@@ -109,7 +108,6 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
if (over_distance && over_duration)
{
last_good = next;
result.tidied_to_original.push_back(next);
running = {0., 0}; // reset running distance and time
}
@@ -122,7 +120,6 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
{
if (over_distance)
{
last_good = next;
result.tidied_to_original.push_back(next);
running = {0., 0}; // reset running distance and time
}
@@ -133,7 +130,11 @@ inline Result tidy(const MatchParameters &params, Thresholds cfg = {15., 5})
}
}
BOOST_ASSERT(result.can_be_removed.size() == params.coordinates.size());
// Always use the last coordinate if more than two original coordinates
if (params.coordinates.size() > 1)
{
result.tidied_to_original.push_back(params.coordinates.size() - 1);
}
// We have to filter parallel arrays that may be empty or the exact same size.
// result.parameters contains an empty MatchParameters at this point: conditionally fill.
+24 -19
View File
@@ -41,26 +41,27 @@ class RouteAPI : public BaseAPI
{
}
void MakeResponse(const InternalRouteResult &raw_route, util::json::Object &response) const
void MakeResponse(const InternalManyRoutesResult &raw_routes,
util::json::Object &response) const
{
auto number_of_routes = raw_route.has_alternative() ? 2UL : 1UL;
util::json::Array routes;
routes.values.resize(number_of_routes);
routes.values[0] = MakeRoute(raw_route.segment_end_coordinates,
raw_route.unpacked_path_segments,
raw_route.source_traversed_in_reverse,
raw_route.target_traversed_in_reverse);
if (raw_route.has_alternative())
BOOST_ASSERT(!raw_routes.routes.empty());
util::json::Array jsRoutes;
for (const auto &route : raw_routes.routes)
{
std::vector<std::vector<PathData>> wrapped_leg(1);
wrapped_leg.front() = std::move(raw_route.unpacked_alternative);
routes.values[1] = MakeRoute(raw_route.segment_end_coordinates,
wrapped_leg,
raw_route.alt_source_traversed_in_reverse,
raw_route.alt_target_traversed_in_reverse);
if (!route.is_valid())
continue;
jsRoutes.values.push_back(MakeRoute(route.segment_end_coordinates,
route.unpacked_path_segments,
route.source_traversed_in_reverse,
route.target_traversed_in_reverse));
}
response.values["waypoints"] = BaseAPI::MakeWaypoints(raw_route.segment_end_coordinates);
response.values["routes"] = std::move(routes);
response.values["waypoints"] =
BaseAPI::MakeWaypoints(raw_routes.routes[0].segment_end_coordinates);
response.values["routes"] = std::move(jsRoutes);
response.values["code"] = "Ok";
}
@@ -164,11 +165,15 @@ class RouteAPI : public BaseAPI
* to find a via point.
* The same exit will be emitted, though, if we should start routing at S, making
* the overall response consistent.
*
* ⚠ CAUTION: order of post-processing steps is important
* - postProcess must be called before collapseTurnInstructions that expects
* post-processed roundabouts without Exit instructions
*/
guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::collapseTurnInstructions(std::move(steps));
leg.steps = guidance::postProcess(std::move(leg.steps));
leg.steps = guidance::postProcess(std::move(steps));
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
leg.steps = guidance::buildIntersections(std::move(leg.steps));
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
+46
View File
@@ -0,0 +1,46 @@
/*
Copyright (c) 2016, Project OSRM contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OSRM_ENGINE_APPROACH_HPP
#define OSRM_ENGINE_APPROACH_HPP
#include <cstdint>
namespace osrm
{
namespace engine
{
enum class Approach : std::uint8_t
{
CURB = 0,
UNRESTRICTED = 1
};
}
}
#endif
@@ -17,11 +17,16 @@ namespace engine
namespace datafacade
{
// Namespace local aliases for algorithms
using CH = routing_algorithms::ch::Algorithm;
using CoreCH = routing_algorithms::corech::Algorithm;
using MLD = routing_algorithms::mld::Algorithm;
using EdgeRange = util::range<EdgeID>;
template <typename AlgorithmT> class AlgorithmDataFacade;
template <> class AlgorithmDataFacade<algorithm::CH>
template <> class AlgorithmDataFacade<CH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
@@ -56,7 +61,7 @@ template <> class AlgorithmDataFacade<algorithm::CH>
const std::function<bool(EdgeData)> filter) const = 0;
};
template <> class AlgorithmDataFacade<algorithm::CoreCH>
template <> class AlgorithmDataFacade<CoreCH>
{
public:
using EdgeData = contractor::QueryEdge::EdgeData;
@@ -64,7 +69,7 @@ template <> class AlgorithmDataFacade<algorithm::CoreCH>
virtual bool IsCoreNode(const NodeID id) const = 0;
};
template <> class AlgorithmDataFacade<algorithm::MLD>
template <> class AlgorithmDataFacade<MLD>
{
public:
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
@@ -6,6 +6,7 @@
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/algorithm.hpp"
#include "engine/approach.hpp"
#include "engine/geospatial_query.hpp"
#include "customizer/edge_based_graph.hpp"
@@ -13,8 +14,13 @@
#include "extractor/datasources.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/segment_data_container.hpp"
#include "extractor/turn_data_container.hpp"
#include "contractor/query_graph.hpp"
#include "partition/cell_storage.hpp"
#include "partition/multi_level_partition.hpp"
@@ -58,15 +64,14 @@ namespace datafacade
template <typename AlgorithmT> class ContiguousInternalMemoryAlgorithmDataFacade;
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
: public datafacade::AlgorithmDataFacade<algorithm::CH>
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
{
private:
using QueryGraph = util::StaticGraph<EdgeData, storage::Ownership::View>;
using QueryGraph = contractor::QueryGraphView;
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
std::unique_ptr<QueryGraph> m_query_graph;
QueryGraph m_query_graph;
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
@@ -83,7 +88,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
util::vector_view<GraphEdge> edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
m_query_graph.reset(new QueryGraph(node_list, edge_list));
m_query_graph = QueryGraph(node_list, edge_list);
}
public:
@@ -100,59 +105,59 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
}
// search graph access
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
unsigned GetNumberOfNodes() const override final { return m_query_graph.GetNumberOfNodes(); }
unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final
{
return m_query_graph->GetOutDegree(n);
return m_query_graph.GetOutDegree(n);
}
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); }
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); }
EdgeData &GetEdgeData(const EdgeID e) const override final
const EdgeData &GetEdgeData(const EdgeID e) const override final
{
return m_query_graph->GetEdgeData(e);
return m_query_graph.GetEdgeData(e);
}
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); }
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); }
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);
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);
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);
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);
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);
return m_query_graph.FindSmallestEdge(from, to, filter);
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
: public datafacade::AlgorithmDataFacade<algorithm::CoreCH>
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
: public datafacade::AlgorithmDataFacade<CoreCH>
{
private:
util::vector_view<bool> m_is_core_node;
@@ -202,8 +207,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
using super = BaseDataFacade;
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
using RTreeLeaf = super::RTreeLeaf;
using SharedRTree =
util::StaticRTree<RTreeLeaf, util::vector_view<util::Coordinate>, storage::Ownership::View>;
using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>;
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using RTreeNode = SharedRTree::TreeNode;
@@ -213,22 +217,15 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
unsigned m_check_sum;
util::vector_view<util::Coordinate> m_coordinate_list;
util::PackedVector<OSMNodeID, storage::Ownership::View> m_osmnodeid_list;
util::vector_view<GeometryID> m_via_geometry_list;
util::vector_view<NameID> m_name_ID_list;
util::vector_view<LaneDataID> m_lane_data_id;
util::vector_view<extractor::guidance::TurnInstruction> m_turn_instruction_list;
util::vector_view<extractor::TravelMode> m_travel_mode_list;
util::vector_view<util::guidance::TurnBearing> m_pre_turn_bearing;
util::vector_view<util::guidance::TurnBearing> m_post_turn_bearing;
extractor::PackedOSMIDsView m_osmnodeid_list;
util::NameTable m_names_table;
util::vector_view<unsigned> m_name_begin_indices;
util::vector_view<bool> m_is_core_node;
util::vector_view<std::uint32_t> m_lane_description_offsets;
util::vector_view<extractor::guidance::TurnLaneType::Mask> m_lane_description_masks;
util::vector_view<TurnPenalty> m_turn_weight_penalties;
util::vector_view<TurnPenalty> m_turn_duration_penalties;
extractor::SegmentDataView segment_data;
extractor::TurnDataView turn_data;
extractor::EdgeBasedNodeDataView edge_based_node_data;
util::vector_view<char> m_datasource_name_data;
util::vector_view<std::size_t> m_datasource_name_offsets;
@@ -293,97 +290,100 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
"Is any data loaded into shared memory?" + SOURCE_REF);
}
auto tree_ptr =
auto tree_nodes_ptr =
data_layout.GetBlockPtr<RTreeNode>(memory_block, storage::DataLayout::R_SEARCH_TREE);
auto tree_level_sizes_ptr = data_layout.GetBlockPtr<std::uint64_t>(
memory_block, storage::DataLayout::R_SEARCH_TREE_LEVELS);
m_static_rtree.reset(
new SharedRTree(tree_ptr,
new SharedRTree(tree_nodes_ptr,
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE],
tree_level_sizes_ptr,
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE_LEVELS],
file_index_path,
m_coordinate_list));
m_geospatial_query.reset(
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void InitializeNodeAndEdgeInformationPointers(storage::DataLayout &data_layout,
char *memory_block)
void InitializeNodeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
{
const auto coordinate_list_ptr = data_layout.GetBlockPtr<util::Coordinate>(
memory_block, storage::DataLayout::COORDINATE_LIST);
const auto coordinate_list_ptr =
layout.GetBlockPtr<util::Coordinate>(memory_ptr, storage::DataLayout::COORDINATE_LIST);
m_coordinate_list.reset(coordinate_list_ptr,
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
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>(
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::DataLayout::COORDINATE_LIST]);
const auto travel_mode_list_ptr = data_layout.GetBlockPtr<extractor::TravelMode>(
memory_block, storage::DataLayout::TRAVEL_MODE);
util::vector_view<extractor::TravelMode> travel_mode_list(
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>(memory_block, storage::DataLayout::LANE_DATA_ID);
util::vector_view<LaneDataID> 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>(
memory_block, storage::DataLayout::TURN_LANE_DATA);
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
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>(
memory_block, storage::DataLayout::TURN_INSTRUCTION);
util::vector_view<extractor::guidance::TurnInstruction> turn_instruction_list(
turn_instruction_list_ptr,
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<NameID>(memory_block, storage::DataLayout::NAME_ID_LIST);
util::vector_view<NameID> 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>(memory_block, storage::DataLayout::ENTRY_CLASSID);
typename util::vector_view<EntryClassID> entry_class_id_list(
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>(
memory_block, storage::DataLayout::PRE_TURN_BEARING);
typename util::vector_view<util::guidance::TurnBearing> 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>(
memory_block, storage::DataLayout::POST_TURN_BEARING);
typename util::vector_view<util::guidance::TurnBearing> 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);
const auto osmnodeid_ptr = layout.GetBlockPtr<extractor::PackedOSMIDsView::block_type>(
memory_ptr, storage::DataLayout::OSM_NODE_ID_LIST);
m_osmnodeid_list = extractor::PackedOSMIDsView(
util::vector_view<extractor::PackedOSMIDsView::block_type>(
osmnodeid_ptr, 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
layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
}
void InitializeViaNodeListPointer(storage::DataLayout &data_layout, char *memory_block)
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
char *memory_ptr)
{
auto via_geometry_list_ptr =
data_layout.GetBlockPtr<GeometryID>(memory_block, storage::DataLayout::VIA_NODE_LIST);
util::vector_view<GeometryID> via_geometry_list(
via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
m_via_geometry_list = std::move(via_geometry_list);
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST);
util::vector_view<GeometryID> geometry_ids(
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]);
const auto name_id_list_ptr =
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST);
util::vector_view<NameID> name_ids(name_id_list_ptr,
layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
const auto component_id_list_ptr =
layout.GetBlockPtr<ComponentID>(memory_ptr, storage::DataLayout::COMPONENT_ID_LIST);
util::vector_view<ComponentID> component_ids(
component_id_list_ptr, layout.num_entries[storage::DataLayout::COMPONENT_ID_LIST]);
const auto travel_mode_list_ptr = layout.GetBlockPtr<extractor::TravelMode>(
memory_ptr, storage::DataLayout::TRAVEL_MODE_LIST);
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
std::move(name_ids),
std::move(component_ids),
std::move(travel_modes));
}
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
{
const auto lane_data_id_ptr =
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
util::vector_view<LaneDataID> lane_data_ids(
lane_data_id_ptr, layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
const auto turn_instruction_list_ptr =
layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
memory_ptr, storage::DataLayout::TURN_INSTRUCTION);
util::vector_view<extractor::guidance::TurnInstruction> turn_instructions(
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
const auto entry_class_id_list_ptr =
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
util::vector_view<EntryClassID> entry_class_ids(
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
util::vector_view<util::guidance::TurnBearing> pre_turn_bearings(
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
const auto post_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
turn_data = extractor::TurnDataView(std::move(turn_instructions),
std::move(lane_data_ids),
std::move(entry_class_ids),
std::move(pre_turn_bearings),
std::move(post_turn_bearings));
}
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
@@ -409,6 +409,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
util::vector_view<extractor::guidance::TurnLaneType::Mask> masks(
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
m_lane_description_masks = std::move(masks);
const auto lane_tupel_id_pair_ptr =
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
memory_block, storage::DataLayout::TURN_LANE_DATA);
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
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);
}
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
@@ -432,35 +439,47 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
util::vector_view<unsigned> geometry_begin_indices(
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
auto num_entries = data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST];
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::vector_view<NodeID> geometry_node_list(
geometries_node_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]);
util::vector_view<NodeID> geometry_node_list(geometries_node_list_ptr, num_entries);
auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
util::vector_view<EdgeWeight> geometry_fwd_weight_list(
geometries_fwd_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
auto geometries_fwd_weight_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentWeightVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
extractor::SegmentDataView::SegmentWeightVector geometry_fwd_weight_list(
util::vector_view<extractor::SegmentDataView::SegmentWeightVector::block_type>(
geometries_fwd_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]),
num_entries);
auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
util::vector_view<EdgeWeight> geometry_rev_weight_list(
geometries_rev_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
auto geometries_rev_weight_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentWeightVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
extractor::SegmentDataView::SegmentWeightVector geometry_rev_weight_list(
util::vector_view<extractor::SegmentDataView::SegmentWeightVector::block_type>(
geometries_rev_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]),
num_entries);
auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
util::vector_view<EdgeWeight> geometry_fwd_duration_list(
geometries_fwd_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
auto geometries_fwd_duration_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentDurationVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
extractor::SegmentDataView::SegmentDurationVector geometry_fwd_duration_list(
util::vector_view<extractor::SegmentDataView::SegmentDurationVector::block_type>(
geometries_fwd_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]),
num_entries);
auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
util::vector_view<EdgeWeight> geometry_rev_duration_list(
geometries_rev_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]);
auto geometries_rev_duration_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentDurationVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
extractor::SegmentDataView::SegmentDurationVector geometry_rev_duration_list(
util::vector_view<extractor::SegmentDataView::SegmentDurationVector::block_type>(
geometries_rev_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]),
num_entries);
auto datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
memory_block, storage::DataLayout::DATASOURCES_LIST);
@@ -515,11 +534,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeChecksumPointer(data_layout, memory_block);
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
InitializeNodeInformationPointers(data_layout, memory_block);
InitializeEdgeBasedNodeDataInformationPointers(data_layout, memory_block);
InitializeEdgeInformationPointers(data_layout, memory_block);
InitializeTurnPenalties(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);
InitializeProfilePropertiesPointer(data_layout, memory_block);
@@ -544,10 +564,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const override final
{
return m_osmnodeid_list.at(id);
return m_osmnodeid_list[id];
}
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
{
auto range = segment_data.GetForwardGeometry(id);
@@ -606,11 +626,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return std::vector<DatasourceID>{range.begin(), range.end()};
}
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final
{
return m_via_geometry_list.at(id);
}
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
{
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
@@ -626,12 +641,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const EdgeID id) const override final
{
return m_turn_instruction_list.at(id);
}
extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final
{
return m_travel_mode_list.at(id);
return turn_data.GetTurnInstruction(id);
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
@@ -645,54 +655,61 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) const override final
const float max_distance,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
return m_geospatial_query->NearestPhantomNodesInRange(
input_coordinate, max_distance, approach);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) const override final
const int bearing_range,
const Approach approach) 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);
input_coordinate, max_distance, bearing, bearing_range, approach);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) const override final
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, approach);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(
input_coordinate, max_results, max_distance, approach);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) const override final
const int bearing_range,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(
input_coordinate, max_results, bearing, bearing_range);
input_coordinate, max_results, bearing, bearing_range, approach);
}
std::vector<PhantomNodeWithDistance>
@@ -700,60 +717,81 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) const override final
const int bearing_range,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(
input_coordinate, max_results, max_distance, bearing, bearing_range);
input_coordinate, max_results, max_distance, bearing, bearing_range, approach);
}
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate) const override final
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate);
input_coordinate, approach);
}
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const double max_distance) const override final
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance);
input_coordinate, max_distance, approach);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) const override final
const int bearing_range,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range);
input_coordinate, max_distance, bearing, bearing_range, approach);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) const override final
const int bearing_range,
const Approach approach) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range);
input_coordinate, bearing, bearing_range, approach);
}
unsigned GetCheckSum() const override final { return m_check_sum; }
NameID GetNameIndexFromEdgeID(const EdgeID id) const override final
GeometryID GetGeometryIndex(const NodeID id) const override final
{
return m_name_ID_list.at(id);
return edge_based_node_data.GetGeometryID(id);
}
ComponentID GetComponentID(const NodeID id) const override final
{
return edge_based_node_data.GetComponentID(id);
}
extractor::TravelMode GetTravelMode(const NodeID id) const override final
{
return edge_based_node_data.GetTravelMode(id);
}
NameID GetNameIndex(const NodeID id) const override final
{
return edge_based_node_data.GetNameID(id);
}
StringView GetNameForID(const NameID id) const override final
@@ -825,16 +863,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return m_entry_class_id_list.at(eid);
return turn_data.GetEntryClassID(eid);
}
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
{
return m_pre_turn_bearing.at(eid);
return turn_data.GetPreTurnBearing(eid);
}
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
{
return m_post_turn_bearing.at(eid);
return turn_data.GetPostTurnBearing(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
@@ -842,15 +880,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return INVALID_LANE_DATAID != m_lane_data_id.at(id);
}
bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); }
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
BOOST_ASSERT(HasLaneData(id));
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id));
}
extractor::guidance::TurnLaneDescription
@@ -864,41 +899,44 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
m_lane_description_masks.begin() +
m_lane_description_offsets[lane_description_id + 1]);
}
bool IsLeftHandDriving() const override final
{
return m_profile_properties->left_hand_driving;
}
};
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
template <>
class ContiguousInternalMemoryDataFacade<algorithm::CH>
class ContiguousInternalMemoryDataFacade<CH>
: public ContiguousInternalMemoryDataFacadeBase,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>(allocator)
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator)
{
}
};
template <>
class ContiguousInternalMemoryDataFacade<algorithm::CoreCH> final
: public ContiguousInternalMemoryDataFacade<algorithm::CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
class ContiguousInternalMemoryDataFacade<CoreCH> final
: public ContiguousInternalMemoryDataFacade<CH>,
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacade<algorithm::CH>(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>(allocator)
: ContiguousInternalMemoryDataFacade<CH>(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator)
{
}
};
template <>
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
: public datafacade::AlgorithmDataFacade<algorithm::MLD>
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
{
// MLD data
partition::MultiLevelPartitionView mld_partition;
@@ -923,7 +961,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
auto level_data =
*data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
memory_block, storage::DataLayout::MLD_LEVEL_DATA);
auto mld_partition_ptr = data_layout.GetBlockPtr<PartitionID>(
@@ -1065,15 +1103,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
};
template <>
class ContiguousInternalMemoryDataFacade<algorithm::MLD> final
class ContiguousInternalMemoryDataFacade<MLD> final
: public ContiguousInternalMemoryDataFacadeBase,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
public ContiguousInternalMemoryAlgorithmDataFacade<MLD>
{
private:
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>(allocator)
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator)
{
}
+34 -19
View File
@@ -4,11 +4,12 @@
// Exposes all data access interfaces to the algorithms via base class ptr
#include "contractor/query_edge.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/original_edge_data.hpp"
#include "engine/approach.hpp"
#include "engine/phantom_node.hpp"
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
@@ -40,7 +41,7 @@ using StringView = util::StringView;
class BaseDataFacade
{
public:
using RTreeLeaf = extractor::EdgeBasedNode;
using RTreeLeaf = extractor::EdgeBasedNodeSegment;
BaseDataFacade() {}
virtual ~BaseDataFacade() {}
@@ -51,7 +52,9 @@ class BaseDataFacade
virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const = 0;
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const = 0;
virtual GeometryID GetGeometryIndex(const NodeID id) const = 0;
virtual ComponentID GetComponentID(const NodeID id) const = 0;
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const = 0;
@@ -82,7 +85,7 @@ class BaseDataFacade
virtual extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const EdgeID id) const = 0;
virtual extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const = 0;
virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0;
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) const = 0;
@@ -91,51 +94,61 @@ class BaseDataFacade
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) const = 0;
const int bearing_range,
const Approach approach) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) const = 0;
const float max_distance,
const Approach approach) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) const = 0;
const int bearing_range,
const Approach approach) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results) const = 0;
const int bearing_range,
const Approach approach) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) const = 0;
const Approach approach) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance,
const Approach approach) const = 0;
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) const = 0;
const Approach approach) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) const = 0;
const int bearing_range,
const Approach approach) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) const = 0;
const int bearing_range,
const Approach approach) const = 0;
virtual bool hasLaneData(const EdgeID id) const = 0;
virtual bool HasLaneData(const EdgeID id) const = 0;
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
virtual extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
virtual NameID GetNameIndexFromEdgeID(const EdgeID id) const = 0;
virtual NameID GetNameIndex(const NodeID id) const = 0;
virtual StringView GetNameForID(const NameID id) const = 0;
@@ -168,6 +181,8 @@ class BaseDataFacade
virtual EntryClassID GetEntryClassID(const EdgeID eid) const = 0;
virtual util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const = 0;
virtual bool IsLeftHandDriving() const = 0;
};
}
}
+55 -28
View File
@@ -22,6 +22,7 @@
#include "engine/status.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/fingerprint.hpp"
#include "util/json_container.hpp"
#include <memory>
@@ -49,7 +50,7 @@ class EngineInterface
virtual Status Tile(const api::TileParameters &parameters, std::string &result) const = 0;
};
template <typename AlgorithmT> class Engine final : public EngineInterface
template <typename Algorithm> class Engine final : public EngineInterface
{
public:
explicit Engine(const EngineConfig &config)
@@ -64,15 +65,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
if (config.use_shared_memory)
{
util::Log(logDEBUG) << "Using shared memory with algorithm "
<< algorithm::name<AlgorithmT>();
facade_provider = std::make_unique<WatchingProvider<AlgorithmT>>();
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<WatchingProvider<Algorithm>>();
}
else
{
util::Log(logDEBUG) << "Using internal memory with algorithm "
<< algorithm::name<AlgorithmT>();
facade_provider =
std::make_unique<ImmutableProvider<AlgorithmT>>(config.storage_config);
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ImmutableProvider<Algorithm>>(config.storage_config);
}
}
@@ -87,7 +87,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return route_plugin.HandleRequest(*facade, algorithms, params, result);
}
@@ -95,7 +95,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return table_plugin.HandleRequest(*facade, algorithms, params, result);
}
@@ -103,14 +103,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return nearest_plugin.HandleRequest(*facade, algorithms, params, result);
}
Status Trip(const api::TripParameters &params, util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return trip_plugin.HandleRequest(*facade, algorithms, params, result);
}
@@ -118,22 +118,22 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
util::json::Object &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return match_plugin.HandleRequest(*facade, algorithms, params, result);
}
Status Tile(const api::TileParameters &params, std::string &result) const override final
{
auto facade = facade_provider->Get();
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
return tile_plugin.HandleRequest(*facade, algorithms, params, result);
}
static bool CheckCompability(const EngineConfig &config);
private:
std::unique_ptr<DataFacadeProvider<AlgorithmT>> facade_provider;
mutable SearchEngineData heaps;
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
mutable SearchEngineData<Algorithm> heaps;
const plugins::ViaRoutePlugin route_plugin;
const plugins::TablePlugin table_plugin;
@@ -143,7 +143,8 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
const plugins::TilePlugin tile_plugin;
};
template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &config)
template <>
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (config.use_shared_memory)
{
@@ -158,19 +159,20 @@ template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &con
}
else
{
std::ifstream in(config.storage_config.hsgr_data_path.string().c_str());
if (!in)
if (!boost::filesystem::exists(config.storage_config.hsgr_data_path))
return false;
storage::io::FileReader in(config.storage_config.hsgr_data_path,
storage::io::FileReader::VerifyFingerprint);
in.seekg(0, std::ios::end);
auto size = in.tellg();
auto size = in.GetSize();
return size > 0;
}
}
template <> bool Engine<algorithm::CoreCH>::CheckCompability(const EngineConfig &config)
template <>
bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (!Engine<algorithm::CH>::CheckCompability(config))
if (!Engine<routing_algorithms::ch::Algorithm>::CheckCompability(config))
{
return false;
}
@@ -183,18 +185,43 @@ template <> bool Engine<algorithm::CoreCH>::CheckCompability(const EngineConfig
auto mem = storage::makeSharedMemory(barrier.data().region);
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER) > 4;
return layout->GetBlockSize(storage::DataLayout::CH_CORE_MARKER) >
sizeof(std::uint64_t) + sizeof(util::FingerPrint);
}
else
{
std::ifstream in(config.storage_config.core_data_path.string().c_str());
if (!in)
if (!boost::filesystem::exists(config.storage_config.core_data_path))
return false;
storage::io::FileReader in(config.storage_config.core_data_path,
storage::io::FileReader::VerifyFingerprint);
in.seekg(0, std::ios::end);
std::size_t size = in.tellg();
// An empty core files is only the 4 byte size header.
return size > sizeof(std::uint32_t);
auto size = in.GetSize();
return size > sizeof(std::uint64_t);
}
}
template <>
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompability(const EngineConfig &config)
{
if (config.use_shared_memory)
{
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
using mutex_type = typename decltype(barrier)::mutex_type;
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
auto mem = storage::makeSharedMemory(barrier.data().region);
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
return layout->GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0;
}
else
{
if (!boost::filesystem::exists(config.storage_config.mld_partition_path))
return false;
storage::io::FileReader in(config.storage_config.mld_partition_path,
storage::io::FileReader::VerifyFingerprint);
auto size = in.GetSize();
return size > 0;
}
}
}
+208 -89
View File
@@ -1,6 +1,7 @@
#ifndef GEOSPATIAL_QUERY_HPP
#define GEOSPATIAL_QUERY_HPP
#include "engine/approach.hpp"
#include "engine/phantom_node.hpp"
#include "util/bearing.hpp"
#include "util/coordinate_calculation.hpp"
@@ -50,15 +51,19 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const double max_distance) const
const double max_distance,
const Approach approach) const
{
auto results =
rtree.Nearest(input_coordinate,
[this](const CandidateSegment &segment) { return HasValidEdge(segment); },
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment) {
return CheckSegmentDistance(input_coordinate, segment, max_distance);
});
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate](const CandidateSegment &segment) {
return boolPairAnd(HasValidEdge(segment),
CheckApproach(input_coordinate, segment, approach));
},
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment) {
return CheckSegmentDistance(input_coordinate, segment, max_distance);
});
return MakePhantomNodes(input_coordinate, results);
}
@@ -69,13 +74,18 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) const
const int bearing_range,
const Approach approach) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range, max_distance](const CandidateSegment &segment) {
return boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
HasValidEdge(segment));
[this, approach, &input_coordinate, bearing, bearing_range, max_distance](
const CandidateSegment &segment) {
auto use_direction = boolPairAnd(
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
use_direction =
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
return use_direction;
},
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment) {
@@ -91,13 +101,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) const
const int bearing_range,
const Approach approach) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range](const CandidateSegment &segment) {
return boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
HasValidEdge(segment));
[this, approach, &input_coordinate, bearing, bearing_range](
const CandidateSegment &segment) {
auto use_direction = boolPairAnd(
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
return boolPairAnd(use_direction,
CheckApproach(input_coordinate, segment, approach));
},
[max_results](const std::size_t num_results, const CandidateSegment &) {
return num_results >= max_results;
@@ -114,13 +128,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) const
const int bearing_range,
const Approach approach) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range](const CandidateSegment &segment) {
return boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
HasValidEdge(segment));
[this, approach, &input_coordinate, bearing, bearing_range](
const CandidateSegment &segment) {
auto use_direction = boolPairAnd(
CheckSegmentBearing(segment, bearing, bearing_range), HasValidEdge(segment));
return boolPairAnd(use_direction,
CheckApproach(input_coordinate, segment, approach));
},
[this, max_distance, max_results, input_coordinate](const std::size_t num_results,
const CandidateSegment &segment) {
@@ -134,14 +152,19 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns max_results nearest PhantomNodes.
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const Approach approach) const
{
auto results =
rtree.Nearest(input_coordinate,
[this](const CandidateSegment &segment) { return HasValidEdge(segment); },
[max_results](const std::size_t num_results, const CandidateSegment &) {
return num_results >= max_results;
});
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate](const CandidateSegment &segment) {
return boolPairAnd(HasValidEdge(segment),
CheckApproach(input_coordinate, segment, approach));
},
[max_results](const std::size_t num_results, const CandidateSegment &) {
return num_results >= max_results;
});
return MakePhantomNodes(input_coordinate, results);
}
@@ -151,16 +174,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) const
const double max_distance,
const Approach approach) const
{
auto results =
rtree.Nearest(input_coordinate,
[this](const CandidateSegment &segment) { return HasValidEdge(segment); },
[this, max_distance, max_results, input_coordinate](
const std::size_t num_results, const CandidateSegment &segment) {
return num_results >= max_results ||
CheckSegmentDistance(input_coordinate, segment, max_distance);
});
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate](const CandidateSegment &segment) {
return boolPairAnd(HasValidEdge(segment),
CheckApproach(input_coordinate, segment, approach));
},
[this, max_distance, max_results, input_coordinate](const std::size_t num_results,
const CandidateSegment &segment) {
return num_results >= max_results ||
CheckSegmentDistance(input_coordinate, segment, max_distance);
});
return MakePhantomNodes(input_coordinate, results);
}
@@ -169,24 +196,29 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) const
const double max_distance,
const Approach approach) const
{
bool has_small_component = false;
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, &has_big_component, &has_small_component](const CandidateSegment &segment) {
auto use_segment = (!has_small_component ||
(!has_big_component && !segment.data.component.is_tiny));
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
const CandidateSegment &segment) {
auto use_segment =
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
auto use_directions = std::make_pair(use_segment, use_segment);
const auto valid_edges = HasValidEdge(segment);
if (valid_edges.first || valid_edges.second)
{
has_big_component = has_big_component || !segment.data.component.is_tiny;
has_small_component = has_small_component || segment.data.component.is_tiny;
}
use_directions = boolPairAnd(use_directions, valid_edges);
use_directions =
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
if (use_directions.first || use_directions.second)
{
has_big_component = has_big_component || !IsTinyComponent(segment);
has_small_component = has_small_component || IsTinyComponent(segment);
}
return use_directions;
},
[this, &has_big_component, max_distance, input_coordinate](
@@ -208,28 +240,30 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns the nearest phantom node. If this phantom node is not from a big component
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const Approach approach) const
{
bool has_small_component = false;
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, &has_big_component, &has_small_component](const CandidateSegment &segment) {
auto use_segment = (!has_small_component ||
(!has_big_component && !segment.data.component.is_tiny));
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
const CandidateSegment &segment) {
auto use_segment =
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
auto use_directions = std::make_pair(use_segment, use_segment);
if (!use_directions.first && !use_directions.second)
return use_directions;
const auto valid_edges = HasValidEdge(segment);
use_directions = boolPairAnd(use_directions, valid_edges);
use_directions =
boolPairAnd(use_directions, CheckApproach(input_coordinate, segment, approach));
if (valid_edges.first || valid_edges.second)
if (use_directions.first || use_directions.second)
{
has_big_component = has_big_component || !segment.data.component.is_tiny;
has_small_component = has_small_component || segment.data.component.is_tiny;
has_big_component = has_big_component || !IsTinyComponent(segment);
has_small_component = has_small_component || IsTinyComponent(segment);
}
use_directions = boolPairAnd(use_directions, valid_edges);
return use_directions;
},
[&has_big_component](const std::size_t num_results, const CandidateSegment &) {
@@ -248,17 +282,25 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns the nearest phantom node. If this phantom node is not from a big component
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range,
const Approach approach) const
{
bool has_small_component = false;
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range, &has_big_component, &has_small_component](
const CandidateSegment &segment) {
auto use_segment = (!has_small_component ||
(!has_big_component && !segment.data.component.is_tiny));
[this,
approach,
&input_coordinate,
bearing,
bearing_range,
&has_big_component,
&has_small_component](const CandidateSegment &segment) {
auto use_segment =
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
auto use_directions = std::make_pair(use_segment, use_segment);
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
@@ -267,10 +309,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
use_directions =
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
HasValidEdge(segment));
use_directions = boolPairAnd(
use_directions, CheckApproach(input_coordinate, segment, approach));
if (use_directions.first || use_directions.second)
{
has_big_component = has_big_component || !segment.data.component.is_tiny;
has_small_component = has_small_component || segment.data.component.is_tiny;
has_big_component = has_big_component || !IsTinyComponent(segment);
has_small_component = has_small_component || IsTinyComponent(segment);
}
}
@@ -296,16 +341,22 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) const
const int bearing_range,
const Approach approach) const
{
bool has_small_component = false;
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, bearing, bearing_range, &has_big_component, &has_small_component](
const CandidateSegment &segment) {
auto use_segment = (!has_small_component ||
(!has_big_component && !segment.data.component.is_tiny));
[this,
approach,
&input_coordinate,
bearing,
bearing_range,
&has_big_component,
&has_small_component](const CandidateSegment &segment) {
auto use_segment =
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
auto use_directions = std::make_pair(use_segment, use_segment);
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
@@ -314,10 +365,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
use_directions =
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
HasValidEdge(segment));
use_directions = boolPairAnd(
use_directions, CheckApproach(input_coordinate, segment, approach));
if (use_directions.first || use_directions.second)
{
has_big_component = has_big_component || !segment.data.component.is_tiny;
has_small_component = has_small_component || segment.data.component.is_tiny;
has_big_component = has_big_component || !IsTinyComponent(segment);
has_small_component = has_small_component || IsTinyComponent(segment);
}
}
@@ -371,17 +425,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
EdgeWeight forward_weight_offset = 0, forward_weight = 0;
EdgeWeight reverse_weight_offset = 0, reverse_weight = 0;
EdgeWeight forward_duration_offset = 0, forward_duration = 0;
EdgeWeight reverse_duration_offset = 0, reverse_duration = 0;
EdgeDuration forward_duration_offset = 0, forward_duration = 0;
EdgeDuration reverse_duration_offset = 0, reverse_duration = 0;
BOOST_ASSERT(data.forward_segment_id.enabled || data.reverse_segment_id.enabled);
BOOST_ASSERT(!data.reverse_segment_id.enabled ||
datafacade.GetGeometryIndex(data.forward_segment_id.id).id ==
datafacade.GetGeometryIndex(data.reverse_segment_id.id).id);
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
const auto component_id = datafacade.GetComponentID(data.forward_segment_id.id);
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(data.packed_geometry_id);
datafacade.GetUncompressedForwardWeights(geometry_id);
const std::vector<EdgeWeight> reverse_weight_vector =
datafacade.GetUncompressedReverseWeights(data.packed_geometry_id);
datafacade.GetUncompressedReverseWeights(geometry_id);
const std::vector<EdgeWeight> forward_duration_vector =
datafacade.GetUncompressedForwardDurations(data.packed_geometry_id);
datafacade.GetUncompressedForwardDurations(geometry_id);
const std::vector<EdgeWeight> reverse_duration_vector =
datafacade.GetUncompressedReverseDurations(data.packed_geometry_id);
datafacade.GetUncompressedReverseDurations(geometry_id);
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
{
@@ -408,15 +469,30 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
{
forward_weight = static_cast<EdgeWeight>(forward_weight * ratio);
forward_duration = static_cast<EdgeWeight>(forward_duration * ratio);
forward_duration = static_cast<EdgeDuration>(forward_duration * ratio);
}
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
{
reverse_weight -= static_cast<EdgeWeight>(reverse_weight * ratio);
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
reverse_duration -= static_cast<EdgeDuration>(reverse_duration * ratio);
}
// check phantom node segments validity
auto areSegmentsValid = [](auto first, auto last) -> bool {
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
};
bool is_forward_valid_source =
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
bool is_forward_valid_target =
areSegmentsValid(forward_weight_vector.begin(),
forward_weight_vector.begin() + data.fwd_segment_position + 1);
bool is_reverse_valid_source =
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
bool is_reverse_valid_target = areSegmentsValid(
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
component_id,
forward_weight,
reverse_weight,
forward_weight_offset,
@@ -425,6 +501,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_duration,
forward_duration_offset,
reverse_duration_offset,
is_forward_valid_source,
is_forward_valid_target,
is_reverse_valid_source,
is_reverse_valid_target,
point_on_segment,
input_coordinate},
current_perpendicular_distance};
@@ -477,7 +557,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
/**
* Checks to see if the edge weights are valid. We might have an edge,
* but a traffic update might set the speed to 0 (weight == INVALID_EDGE_WEIGHT).
* but a traffic update might set the speed to 0 (weight == INVALID_SEGMENT_WEIGHT).
* which means that this edge is not currently traversible. If this is the case,
* then we shouldn't snap to this edge.
*/
@@ -487,25 +567,64 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool forward_edge_valid = false;
bool reverse_edge_valid = false;
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(segment.data.packed_geometry_id);
const auto &data = segment.data;
BOOST_ASSERT(data.forward_segment_id.enabled);
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
if (forward_weight_vector[segment.data.fwd_segment_position] != INVALID_EDGE_WEIGHT)
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(geometry_id);
if (forward_weight_vector[data.fwd_segment_position] != INVALID_SEGMENT_WEIGHT)
{
forward_edge_valid = segment.data.forward_segment_id.enabled;
forward_edge_valid = data.forward_segment_id.enabled;
}
const std::vector<EdgeWeight> reverse_weight_vector =
datafacade.GetUncompressedReverseWeights(segment.data.packed_geometry_id);
if (reverse_weight_vector[reverse_weight_vector.size() - segment.data.fwd_segment_position -
1] != INVALID_EDGE_WEIGHT)
datafacade.GetUncompressedReverseWeights(geometry_id);
if (reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1] !=
INVALID_SEGMENT_WEIGHT)
{
reverse_edge_valid = segment.data.reverse_segment_id.enabled;
reverse_edge_valid = data.reverse_segment_id.enabled;
}
return std::make_pair(forward_edge_valid, reverse_edge_valid);
}
bool IsTinyComponent(const CandidateSegment &segment) const
{
const auto &data = segment.data;
BOOST_ASSERT(data.forward_segment_id.enabled);
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
return datafacade.GetComponentID(data.forward_segment_id.id).is_tiny;
}
std::pair<bool, bool> CheckApproach(const util::Coordinate &input_coordinate,
const CandidateSegment &segment,
const Approach approach) const
{
bool isOnewaySegment =
!(segment.data.forward_segment_id.enabled && segment.data.reverse_segment_id.enabled);
if (!isOnewaySegment && approach == Approach::CURB)
{
// Check the counter clockwise
//
// input_coordinate
// |
// |
// segment.data.u ---------------- segment.data.v
bool input_coordinate_is_at_right = !util::coordinate_calculation::isCCW(
coordinates[segment.data.u], coordinates[segment.data.v], input_coordinate);
if (datafacade.IsLeftHandDriving())
input_coordinate_is_at_right = !input_coordinate_is_at_right;
return std::make_pair(input_coordinate_is_at_right, (!input_coordinate_is_at_right));
}
return std::make_pair(true, true);
}
const RTreeT &rtree;
const CoordinateList &coordinates;
DataFacadeT &datafacade;
@@ -51,8 +51,11 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
// source node rev: 2 0 <- 1 <- 2
const auto source_segment_start_coordinate =
source_node.fwd_segment_position + (reversed_source ? 1 : 0);
const auto source_node_id =
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
const auto source_gemetry_id = facade.GetGeometryIndex(source_node_id).id;
const std::vector<NodeID> source_geometry =
facade.GetUncompressedForwardGeometry(source_node.packed_geometry_id);
facade.GetUncompressedForwardGeometry(source_gemetry_id);
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate]));
@@ -89,8 +92,11 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
// segment leading to the target node
geometry.segment_distances.push_back(cumulative_distance);
const auto target_node_id =
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
const auto target_gemetry_id = facade.GetGeometryIndex(target_node_id).id;
const std::vector<DatasourceID> forward_datasources =
facade.GetUncompressedForwardDatasources(target_node.packed_geometry_id);
facade.GetUncompressedForwardDatasources(target_gemetry_id);
// FIXME if source and target phantoms are on the same segment then duration and weight
// will be from one projected point till end of segment
@@ -113,7 +119,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto target_segment_end_coordinate =
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
const std::vector<NodeID> target_geometry =
facade.GetUncompressedForwardGeometry(target_node.packed_geometry_id);
facade.GetUncompressedForwardGeometry(target_gemetry_id);
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate]));
+11 -5
View File
@@ -40,7 +40,8 @@ struct NamedSegment
template <std::size_t SegmentNumber>
std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathData> &route_data,
std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDataFacade &facade,
const std::vector<PathData> &route_data,
const PhantomNode &target_node,
const bool target_traversed_in_reverse)
{
@@ -80,8 +81,10 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathDa
});
const auto target_duration =
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
: target_node.forward_segment_id.id;
if (target_duration > 1)
segments.push_back({target_duration, index++, target_node.name_id});
segments.push_back({target_duration, index++, facade.GetNameIndex(target_node_id)});
// this makes sure that the segment with the lowest position comes first
std::sort(
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
@@ -170,17 +173,20 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
weight = weight + target_weight;
if (route_data.empty())
{
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
weight -=
(target_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight);
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
: source_node.forward_duration);
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
duration = std::max(0, duration);
}
std::string summary;
if (needs_summary)
{
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(
route_data, target_node, target_traversed_in_reverse);
facade, route_data, target_node, target_traversed_in_reverse);
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
BOOST_ASSERT(summary_array.begin() != summary_array.end());
+26 -19
View File
@@ -49,15 +49,19 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
const EdgeWeight source_duration =
source_traversed_in_reverse ? source_node.reverse_duration : source_node.forward_duration;
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
: source_node.forward_travel_mode;
const auto source_node_id = source_traversed_in_reverse ? source_node.reverse_segment_id.id
: source_node.forward_segment_id.id;
const auto source_name_id = facade.GetNameIndex(source_node_id);
const auto source_mode = facade.GetTravelMode(source_node_id);
const EdgeWeight target_duration =
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
const EdgeWeight target_weight =
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
: target_node.forward_travel_mode;
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
: target_node.forward_segment_id.id;
const auto target_name_id = facade.GetNameIndex(target_node_id);
const auto target_mode = facade.GetTravelMode(target_node_id);
const auto number_of_segments = leg_geometry.GetNumberOfSegments();
@@ -95,7 +99,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// some name changes are not announced in our processing. For these, we have to keep the
// first name on the segment
auto step_name_id = source_node.name_id;
auto step_name_id = source_name_id;
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
{
const auto &path_point = leg_data[leg_data_index];
@@ -134,7 +138,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
}
else
{
step_name_id = target_node.name_id;
step_name_id = facade.GetNameIndex(target_node_id);
}
// extract bearings
@@ -222,16 +226,19 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
// u-------------v
// | |---------| source_weight
// | |---| target_weight
BOOST_ASSERT(target_weight >= source_weight);
const EdgeWeight weight = target_weight - source_weight;
const EdgeWeight duration = target_duration - source_duration;
BOOST_ASSERT(weight >= 0);
BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{source_node.name_id,
facade.GetNameForID(source_node.name_id).to_string(),
facade.GetRefForID(source_node.name_id).to_string(),
facade.GetPronunciationForID(source_node.name_id).to_string(),
facade.GetDestinationsForID(source_node.name_id).to_string(),
// use rectified linear unit function to avoid negative duration values
// due to flooring errors in phantom snapping
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
const EdgeWeight duration = std::max(0, target_duration - source_duration);
steps.push_back(RouteStep{source_name_id,
facade.GetNameForID(source_name_id).to_string(),
facade.GetRefForID(source_name_id).to_string(),
facade.GetPronunciationForID(source_name_id).to_string(),
facade.GetDestinationsForID(source_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
duration / 10.,
@@ -265,11 +272,11 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
0};
BOOST_ASSERT(!leg_geometry.locations.empty());
steps.push_back(RouteStep{target_node.name_id,
facade.GetNameForID(target_node.name_id).to_string(),
facade.GetRefForID(target_node.name_id).to_string(),
facade.GetPronunciationForID(target_node.name_id).to_string(),
facade.GetDestinationsForID(target_node.name_id).to_string(),
steps.push_back(RouteStep{target_name_id,
facade.GetNameForID(target_name_id).to_string(),
facade.GetRefForID(target_name_id).to_string(),
facade.GetPronunciationForID(target_name_id).to_string(),
facade.GetDestinationsForID(target_name_id).to_string(),
NO_ROTARY_NAME,
NO_ROTARY_NAME,
ZERO_DURATION,
+2 -2
View File
@@ -63,8 +63,8 @@ struct Hint
friend std::ostream &operator<<(std::ostream &, const Hint &);
};
static_assert(sizeof(Hint) == 72 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 104;
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 92;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
}
+10 -12
View File
@@ -16,8 +16,6 @@ namespace osrm
namespace engine
{
const constexpr unsigned INVALID_EXIT_NR = 0;
struct PathData
{
// id of via node of the turn
@@ -49,28 +47,28 @@ struct PathData
struct InternalRouteResult
{
std::vector<std::vector<PathData>> unpacked_path_segments;
std::vector<PathData> unpacked_alternative;
std::vector<PhantomNodes> segment_end_coordinates;
std::vector<bool> source_traversed_in_reverse;
std::vector<bool> target_traversed_in_reverse;
std::vector<bool> alt_source_traversed_in_reverse;
std::vector<bool> alt_target_traversed_in_reverse;
int shortest_path_length;
int alternative_path_length;
EdgeWeight shortest_path_weight = INVALID_EDGE_WEIGHT;
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_length; }
bool has_alternative() const { return INVALID_EDGE_WEIGHT != alternative_path_length; }
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_weight; }
bool is_via_leg(const std::size_t leg) const
{
return (leg != unpacked_path_segments.size() - 1);
}
};
InternalRouteResult()
: shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT)
struct InternalManyRoutesResult
{
InternalManyRoutesResult() = default;
InternalManyRoutesResult(InternalRouteResult route) : routes{std::move(route)} {}
InternalManyRoutesResult(std::vector<InternalRouteResult> routes_) : routes{std::move(routes_)}
{
}
std::vector<InternalRouteResult> routes;
};
}
}
+44 -61
View File
@@ -46,47 +46,14 @@ namespace engine
struct PhantomNode
{
PhantomNode(SegmentID forward_segment_id,
SegmentID reverse_segment_id,
unsigned name_id,
EdgeWeight forward_weight,
EdgeWeight reverse_weight,
EdgeWeight forward_weight_offset,
EdgeWeight reverse_weight_offset,
EdgeWeight forward_duration,
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
unsigned packed_geometry_id_,
bool is_tiny_component,
unsigned component_id,
util::Coordinate location,
util::Coordinate input_location,
unsigned short fwd_segment_position,
extractor::TravelMode forward_travel_mode,
extractor::TravelMode backward_travel_mode)
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
forward_weight_offset(forward_weight_offset),
reverse_weight_offset(reverse_weight_offset), forward_duration(forward_duration),
reverse_duration(reverse_duration), forward_duration_offset(forward_duration_offset),
reverse_duration_offset(reverse_duration_offset), packed_geometry_id(packed_geometry_id_),
component{component_id, is_tiny_component}, location(std::move(location)),
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
{
}
PhantomNode()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false},
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
forward_duration_offset(0), reverse_duration_offset(0),
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
is_valid_forward_source{false}, is_valid_forward_target{false},
is_valid_reverse_source{false}, is_valid_reverse_target{false}
{
}
@@ -124,7 +91,7 @@ struct PhantomNode
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
((forward_duration != MAXIMAL_EDGE_DURATION) ||
(reverse_duration != MAXIMAL_EDGE_DURATION)) &&
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
(component.id != INVALID_COMPONENTID);
}
bool IsValid(const unsigned number_of_nodes, const util::Coordinate queried_coordinate) const
@@ -132,12 +99,30 @@ struct PhantomNode
return queried_coordinate == input_location && IsValid(number_of_nodes);
}
bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
bool IsValid() const { return location.IsValid(); }
bool IsValidForwardSource() const
{
return forward_segment_id.enabled && is_valid_forward_source;
}
bool IsValidForwardTarget() const
{
return forward_segment_id.enabled && is_valid_forward_target;
}
bool IsValidReverseSource() const
{
return reverse_segment_id.enabled && is_valid_reverse_source;
}
bool IsValidReverseTarget() const
{
return reverse_segment_id.enabled && is_valid_reverse_target;
}
bool operator==(const PhantomNode &other) const { return location == other.location; }
template <class OtherT>
explicit PhantomNode(const OtherT &other,
ComponentID component,
EdgeWeight forward_weight,
EdgeWeight reverse_weight,
EdgeWeight forward_weight_offset,
@@ -146,26 +131,29 @@ struct PhantomNode
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
EdgeWeight reverse_duration_offset,
bool is_valid_forward_source,
bool is_valid_forward_target,
bool is_valid_reverse_source,
bool is_valid_reverse_target,
const util::Coordinate location,
const util::Coordinate input_location)
: forward_segment_id{other.forward_segment_id},
reverse_segment_id{other.reverse_segment_id}, name_id{other.name_id},
forward_weight{forward_weight}, reverse_weight{reverse_weight},
forward_weight_offset{forward_weight_offset},
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
reverse_weight_offset{reverse_weight_offset}, forward_duration{forward_duration},
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
reverse_duration_offset{reverse_duration_offset},
packed_geometry_id{other.packed_geometry_id},
component{other.component.id, other.component.is_tiny}, location{location},
component{component.id, component.is_tiny}, location{location},
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
forward_travel_mode{other.forward_travel_mode},
backward_travel_mode{other.backward_travel_mode}
is_valid_forward_source{is_valid_forward_source},
is_valid_forward_target{is_valid_forward_target},
is_valid_reverse_source{is_valid_reverse_source},
is_valid_reverse_target{is_valid_reverse_target}
{
}
SegmentID forward_segment_id;
SegmentID reverse_segment_id;
unsigned name_id;
EdgeWeight forward_weight;
EdgeWeight reverse_weight;
EdgeWeight forward_weight_offset; // TODO: try to remove -> requires path unpacking changes
@@ -174,24 +162,21 @@ struct PhantomNode
EdgeWeight reverse_duration;
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
unsigned packed_geometry_id;
struct ComponentType
{
std::uint32_t id : 31;
std::uint32_t is_tiny : 1;
} component;
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to be 4 bytes big");
ComponentID component;
util::Coordinate location;
util::Coordinate input_location;
unsigned short fwd_segment_position;
// note 4 bits would suffice for each,
// but the saved byte would be padding anyway
extractor::TravelMode forward_travel_mode;
extractor::TravelMode backward_travel_mode;
// is phantom node valid to be used as source or target
private:
unsigned short is_valid_forward_source : 1;
unsigned short is_valid_forward_target : 1;
unsigned short is_valid_reverse_source : 1;
unsigned short is_valid_reverse_target : 1;
unsigned short : 12; // Unused padding out to 16 bits (2 bytes)
};
static_assert(sizeof(PhantomNode) == 72, "PhantomNode has more padding then expected");
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
@@ -218,7 +203,6 @@ inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
{
out << "node1: " << pn.forward_segment_id.id << ", "
<< "node2: " << pn.reverse_segment_id.id << ", "
<< "name: " << pn.name_id << ", "
<< "fwd-w: " << pn.forward_weight << ", "
<< "rev-w: " << pn.reverse_weight << ", "
<< "fwd-o: " << pn.forward_weight_offset << ", "
@@ -227,7 +211,6 @@ inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
<< "rev-d: " << pn.reverse_duration << ", "
<< "fwd-do: " << pn.forward_duration_offset << ", "
<< "rev-do: " << pn.reverse_duration_offset << ", "
<< "geom: " << pn.packed_geometry_id << ", "
<< "comp: " << pn.component.is_tiny << " / " << pn.component.id << ", "
<< "pos: " << pn.fwd_segment_position << ", "
<< "loc: " << pn.location;
+37 -13
View File
@@ -16,6 +16,8 @@
#include <string>
#include <vector>
#include <util/log.hpp>
namespace osrm
{
namespace engine
@@ -118,9 +120,14 @@ class BasePlugin
const bool use_hints = !parameters.hints.empty();
const bool use_bearings = !parameters.bearings.empty();
const bool use_approaches = !parameters.approaches.empty();
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
{
Approach approach = engine::Approach::UNRESTRICTED;
if (use_approaches && parameters.approaches[i])
approach = parameters.approaches[i].get();
if (use_hints && parameters.hints[i] &&
parameters.hints[i]->IsValid(parameters.coordinates[i], facade))
{
@@ -137,12 +144,13 @@ class BasePlugin
facade.NearestPhantomNodesInRange(parameters.coordinates[i],
radiuses[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range);
parameters.bearings[i]->range,
approach);
}
else
{
phantom_nodes[i] =
facade.NearestPhantomNodesInRange(parameters.coordinates[i], radiuses[i]);
phantom_nodes[i] = facade.NearestPhantomNodesInRange(
parameters.coordinates[i], radiuses[i], approach);
}
}
@@ -160,10 +168,15 @@ class BasePlugin
const bool use_hints = !parameters.hints.empty();
const bool use_bearings = !parameters.bearings.empty();
const bool use_radiuses = !parameters.radiuses.empty();
const bool use_approaches = !parameters.approaches.empty();
BOOST_ASSERT(parameters.IsValid());
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
{
Approach approach = engine::Approach::UNRESTRICTED;
if (use_approaches && parameters.approaches[i])
approach = parameters.approaches[i].get();
if (use_hints && parameters.hints[i] &&
parameters.hints[i]->IsValid(parameters.coordinates[i], facade))
{
@@ -183,27 +196,31 @@ class BasePlugin
number_of_results,
*parameters.radiuses[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range);
parameters.bearings[i]->range,
approach);
}
else
{
phantom_nodes[i] = facade.NearestPhantomNodes(parameters.coordinates[i],
number_of_results,
parameters.bearings[i]->bearing,
parameters.bearings[i]->range);
parameters.bearings[i]->range,
approach);
}
}
else
{
if (use_radiuses && parameters.radiuses[i])
{
phantom_nodes[i] = facade.NearestPhantomNodes(
parameters.coordinates[i], number_of_results, *parameters.radiuses[i]);
phantom_nodes[i] = facade.NearestPhantomNodes(parameters.coordinates[i],
number_of_results,
*parameters.radiuses[i],
approach);
}
else
{
phantom_nodes[i] =
facade.NearestPhantomNodes(parameters.coordinates[i], number_of_results);
phantom_nodes[i] = facade.NearestPhantomNodes(
parameters.coordinates[i], number_of_results, approach);
}
}
@@ -224,10 +241,15 @@ class BasePlugin
const bool use_hints = !parameters.hints.empty();
const bool use_bearings = !parameters.bearings.empty();
const bool use_radiuses = !parameters.radiuses.empty();
const bool use_approaches = !parameters.approaches.empty();
BOOST_ASSERT(parameters.IsValid());
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
{
Approach approach = engine::Approach::UNRESTRICTED;
if (use_approaches && parameters.approaches[i])
approach = parameters.approaches[i].get();
if (use_hints && parameters.hints[i] &&
parameters.hints[i]->IsValid(parameters.coordinates[i], facade))
{
@@ -245,7 +267,8 @@ class BasePlugin
parameters.coordinates[i],
*parameters.radiuses[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range);
parameters.bearings[i]->range,
approach);
}
else
{
@@ -253,7 +276,8 @@ class BasePlugin
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
parameters.coordinates[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range);
parameters.bearings[i]->range,
approach);
}
}
else
@@ -262,13 +286,13 @@ class BasePlugin
{
phantom_node_pairs[i] =
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
parameters.coordinates[i], *parameters.radiuses[i]);
parameters.coordinates[i], *parameters.radiuses[i], approach);
}
else
{
phantom_node_pairs[i] =
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
parameters.coordinates[i]);
parameters.coordinates[i], approach);
}
}
+26 -4
View File
@@ -14,10 +14,9 @@ namespace engine
{
namespace detail
{
constexpr double POLYLINE_DECODING_PRECISION = 1e5;
constexpr double POLYLINE_TO_COORDINATE = COORDINATE_PRECISION / POLYLINE_DECODING_PRECISION;
std::string encode(std::vector<int> &numbers);
std::int32_t decode_polyline_integer(std::string::const_iterator &first,
std::string::const_iterator last);
}
using CoordVectorForwardIter = std::vector<util::Coordinate>::const_iterator;
// Encodes geometry into polyline format.
@@ -57,7 +56,30 @@ std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter
// Decodes geometry from polyline format
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
std::vector<util::Coordinate> decodePolyline(const std::string &polyline);
template <unsigned POLYLINE_PRECISION = 100000>
std::vector<util::Coordinate> decodePolyline(const std::string &polyline)
{
double polyline_to_coordinate = COORDINATE_PRECISION / POLYLINE_PRECISION;
std::vector<util::Coordinate> coordinates;
std::int32_t latitude = 0, longitude = 0;
std::string::const_iterator first = polyline.begin();
const std::string::const_iterator last = polyline.end();
while (first != last)
{
const auto dlat = detail::decode_polyline_integer(first, last);
const auto dlon = detail::decode_polyline_integer(first, last);
latitude += dlat;
longitude += dlon;
coordinates.emplace_back(util::Coordinate{
util::FixedLongitude{static_cast<std::int32_t>(longitude * polyline_to_coordinate)},
util::FixedLatitude{static_cast<std::int32_t>(latitude * polyline_to_coordinate)}});
}
return coordinates;
}
}
}
+56 -63
View File
@@ -19,7 +19,7 @@ namespace engine
class RoutingAlgorithmsInterface
{
public:
virtual InternalRouteResult
virtual InternalManyRoutesResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual InternalRouteResult
@@ -54,18 +54,18 @@ class RoutingAlgorithmsInterface
};
// Short-lived object passed to each plugin in request to wrap routing algorithms
template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
{
public:
RoutingAlgorithms(SearchEngineData &heaps,
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade)
RoutingAlgorithms(SearchEngineData<Algorithm> &heaps,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade)
: heaps(heaps), facade(facade)
{
}
virtual ~RoutingAlgorithms() = default;
InternalRouteResult
InternalManyRoutesResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
InternalRouteResult ShortestPathSearch(
@@ -93,49 +93,50 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
bool HasAlternativePathSearch() const final override
{
return algorithm_trais::HasAlternativePathSearch<AlgorithmT>::value;
return routing_algorithms::HasAlternativePathSearch<Algorithm>::value;
}
bool HasShortestPathSearch() const final override
{
return algorithm_trais::HasShortestPathSearch<AlgorithmT>::value;
return routing_algorithms::HasShortestPathSearch<Algorithm>::value;
}
bool HasDirectShortestPathSearch() const final override
{
return algorithm_trais::HasDirectShortestPathSearch<AlgorithmT>::value;
return routing_algorithms::HasDirectShortestPathSearch<Algorithm>::value;
}
bool HasMapMatching() const final override
{
return algorithm_trais::HasMapMatching<AlgorithmT>::value;
return routing_algorithms::HasMapMatching<Algorithm>::value;
}
bool HasManyToManySearch() const final override
{
return algorithm_trais::HasManyToManySearch<AlgorithmT>::value;
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
}
bool HasGetTileTurns() const final override
{
return algorithm_trais::HasGetTileTurns<AlgorithmT>::value;
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
}
private:
SearchEngineData &heaps;
SearchEngineData<Algorithm> &heaps;
// Owned by shared-ptr passed to the query
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade;
};
template <typename AlgorithmT>
InternalRouteResult
RoutingAlgorithms<AlgorithmT>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
template <typename Algorithm>
InternalManyRoutesResult
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
{
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
}
template <typename AlgorithmT>
InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
template <typename Algorithm>
InternalRouteResult RoutingAlgorithms<Algorithm>::ShortestPathSearch(
const std::vector<PhantomNodes> &phantom_node_pair,
const boost::optional<bool> continue_straight_at_waypoint) const
{
@@ -143,25 +144,25 @@ InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
}
template <typename AlgorithmT>
template <typename Algorithm>
InternalRouteResult
RoutingAlgorithms<AlgorithmT>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
{
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
}
template <typename AlgorithmT>
std::vector<EdgeWeight> RoutingAlgorithms<AlgorithmT>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
template <typename Algorithm>
std::vector<EdgeWeight>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::manyToManySearch(
return routing_algorithms::ch::manyToManySearch(
heaps, facade, phantom_nodes, source_indices, target_indices);
}
template <typename AlgorithmT>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMatching(
template <typename Algorithm>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
const routing_algorithms::CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
@@ -177,56 +178,48 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMat
allow_splitting);
}
template <typename AlgorithmT>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<AlgorithmT>::GetTileTurns(
template <typename Algorithm>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::GetTileTurns(
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes) const
{
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
}
// CoreCH overrides
template <>
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
{
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
}
template <>
inline std::vector<EdgeWeight>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
{
throw util::exception("ManyToManySearch is disabled due to performance reasons");
}
// MLD overrides for not implemented
template <>
InternalRouteResult inline RoutingAlgorithms<algorithm::MLD>::AlternativePathSearch(
const PhantomNodes &) const
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
{
throw util::exception("AlternativePathSearch is not implemented");
}
template <>
inline InternalRouteResult
RoutingAlgorithms<algorithm::MLD>::ShortestPathSearch(const std::vector<PhantomNodes> &,
const boost::optional<bool>) const
{
throw util::exception("ShortestPathSearch is not implemented");
}
template <>
inline std::vector<EdgeWeight>
RoutingAlgorithms<algorithm::MLD>::ManyToManySearch(const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
{
throw util::exception("ManyToManySearch is not implemented");
}
template <>
inline routing_algorithms::SubMatchingList
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
const std::vector<util::Coordinate> &,
const std::vector<unsigned> &,
const std::vector<boost::optional<double>> &,
const bool) const
{
throw util::exception("MapMatching is not implemented");
}
template <>
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<algorithm::MLD>::GetTileTurns(
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &,
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
const std::vector<std::size_t> &) const
{
throw util::exception("GetTileTurns is not implemented");
throw util::exception("ManyToManySearch is not implemented");
}
}
}
@@ -15,12 +15,13 @@ namespace engine
{
namespace routing_algorithms
{
InternalRouteResult
alternativePathSearch(SearchEngineData &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
namespace ch
{
InternalManyRoutesResult
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const PhantomNodes &phantom_node_pair);
} // namespace ch
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -21,11 +21,20 @@ namespace routing_algorithms
/// by the previous route.
/// This variation is only an optimazation for graphs with slow queries, for example
/// not fully contracted graphs.
template <typename AlgorithmT>
InternalRouteResult
directShortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
const PhantomNodes &phantom_nodes);
InternalRouteResult directShortestPathSearch(
SearchEngineData<ch::Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
const PhantomNodes &phantom_nodes);
InternalRouteResult directShortestPathSearch(
SearchEngineData<corech::Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
const PhantomNodes &phantom_nodes);
InternalRouteResult directShortestPathSearch(
SearchEngineData<mld::Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
const PhantomNodes &phantom_nodes);
} // namespace routing_algorithms
} // namespace engine
@@ -13,16 +13,18 @@ namespace osrm
{
namespace engine
{
namespace routing_algorithms
{
namespace ch
{
std::vector<EdgeWeight>
manyToManySearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
} // namespace ch
} // namespace routing_algorithms
} // namespace engine
@@ -22,25 +22,17 @@ static const constexpr double DEFAULT_GPS_PRECISION = 5;
//[1] "Hidden Markov Map Matching Through Noise and Sparseness";
// P. Newson and J. Krumm; 2009; ACM GIS
SubMatchingList
mapMatching(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision,
const bool allow_splitting);
template <typename Algorithm>
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision,
const bool allow_splitting);
SubMatchingList
mapMatching(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
const std::vector<boost::optional<double>> &trace_gps_precision,
const bool allow_splitting);
}
}
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
#endif /* MAP_MATCHING_HPP */
+133 -100
View File
@@ -37,88 +37,83 @@ static constexpr bool FORWARD_DIRECTION = true;
static constexpr bool REVERSE_DIRECTION = false;
static constexpr bool DO_NOT_FORCE_LOOPS = false;
template <bool DIRECTION, typename Heap>
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
{
BOOST_ASSERT(phantom_node.IsValid());
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
if (phantom_node.forward_segment_id.enabled)
{
heap.Insert(phantom_node.forward_segment_id.id,
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_segment_id.id);
}
if (phantom_node.reverse_segment_id.enabled)
{
heap.Insert(phantom_node.reverse_segment_id.id,
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
phantom_node.reverse_segment_id.id);
}
}
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
template <bool DIRECTION>
void insertNodesInHeap(SearchEngineData::ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
{
BOOST_ASSERT(phantom_node.IsValid());
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
const auto weight_sign = DIRECTION == FORWARD_DIRECTION ? -1 : 1;
if (phantom_node.forward_segment_id.enabled)
{
heap.Insert(
phantom_node.forward_segment_id.id,
weight_sign * phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, weight_sign * phantom_node.GetForwardDuration()});
}
if (phantom_node.reverse_segment_id.enabled)
{
heap.Insert(
phantom_node.reverse_segment_id.id,
weight_sign * phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, weight_sign * phantom_node.GetReverseDuration()});
}
}
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node);
template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
{
insertNodesInHeap<FORWARD_DIRECTION>(forward_heap, nodes.source_phantom);
insertNodesInHeap<REVERSE_DIRECTION>(reverse_heap, nodes.target_phantom);
const auto &source = nodes.source_phantom;
if (source.IsValidForwardSource())
{
forward_heap.Insert(source.forward_segment_id.id,
-source.GetForwardWeightPlusOffset(),
source.forward_segment_id.id);
}
if (source.IsValidReverseSource())
{
forward_heap.Insert(source.reverse_segment_id.id,
-source.GetReverseWeightPlusOffset(),
source.reverse_segment_id.id);
}
const auto &target = nodes.target_phantom;
if (target.IsValidForwardTarget())
{
reverse_heap.Insert(target.forward_segment_id.id,
target.GetForwardWeightPlusOffset(),
target.forward_segment_id.id);
}
if (target.IsValidReverseTarget())
{
reverse_heap.Insert(target.reverse_segment_id.id,
target.GetReverseWeightPlusOffset(),
target.reverse_segment_id.id);
}
}
template <typename FacadeT>
void annotatePath(const FacadeT &facade,
const NodeID source_node,
const NodeID target_node,
const std::vector<EdgeID> &unpacked_edges,
const PhantomNodes &phantom_node_pair,
const std::vector<NodeID> &unpacked_nodes,
const std::vector<EdgeID> &unpacked_edges,
std::vector<PathData> &unpacked_path)
{
BOOST_ASSERT(source_node != SPECIAL_NODEID && target_node != SPECIAL_NODEID);
BOOST_ASSERT(!unpacked_edges.empty() || source_node == target_node);
BOOST_ASSERT(!unpacked_nodes.empty());
BOOST_ASSERT(unpacked_nodes.size() == unpacked_edges.size() + 1);
const auto source_node_id = unpacked_nodes.front();
const auto target_node_id = unpacked_nodes.back();
const bool start_traversed_in_reverse =
phantom_node_pair.source_phantom.forward_segment_id.id != source_node;
phantom_node_pair.source_phantom.forward_segment_id.id != source_node_id;
const bool target_traversed_in_reverse =
phantom_node_pair.target_phantom.forward_segment_id.id != target_node;
phantom_node_pair.target_phantom.forward_segment_id.id != target_node_id;
BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id == source_node ||
phantom_node_pair.source_phantom.reverse_segment_id.id == source_node);
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node ||
phantom_node_pair.target_phantom.reverse_segment_id.id == target_node);
BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id == source_node_id ||
phantom_node_pair.source_phantom.reverse_segment_id.id == source_node_id);
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node_id ||
phantom_node_pair.target_phantom.reverse_segment_id.id == target_node_id);
for (auto edge_id : unpacked_edges)
auto node_from = unpacked_nodes.begin(), node_last = std::prev(unpacked_nodes.end());
for (auto edge = unpacked_edges.begin(); node_from != node_last; ++node_from, ++edge)
{
const auto &edge_data = facade.GetEdgeData(edge_id);
const auto turn_id = edge_data.turn_id; // edge-based node ID
const auto name_index = facade.GetNameIndexFromEdgeID(turn_id);
const auto &edge_data = facade.GetEdgeData(*edge);
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
const auto node_id = *node_from; // edge-based graph node index
const auto name_index = facade.GetNameIndex(node_id);
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
const extractor::TravelMode travel_mode =
(unpacked_path.empty() && start_traversed_in_reverse)
? phantom_node_pair.source_phantom.backward_travel_mode
: facade.GetTravelModeForEdgeID(turn_id);
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
const auto geometry_index = facade.GetGeometryIndexForEdgeID(turn_id);
const auto geometry_index = facade.GetGeometryIndex(node_id);
std::vector<NodeID> id_vector;
std::vector<EdgeWeight> weight_vector;
@@ -169,7 +164,7 @@ void annotatePath(const FacadeT &facade,
util::guidance::TurnBearing(0)});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.hasLaneData(turn_id))
if (facade.HasLaneData(turn_id))
unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
@@ -185,23 +180,16 @@ void annotatePath(const FacadeT &facade,
std::vector<EdgeWeight> weight_vector;
std::vector<EdgeWeight> duration_vector;
std::vector<DatasourceID> datasource_vector;
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
phantom_node_pair.target_phantom.packed_geometry_id) &&
unpacked_path.empty();
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
const auto is_local_path = source_geometry_id == target_geometry_id && unpacked_path.empty();
if (target_traversed_in_reverse)
{
id_vector = facade.GetUncompressedReverseGeometry(
phantom_node_pair.target_phantom.packed_geometry_id);
weight_vector = facade.GetUncompressedReverseWeights(
phantom_node_pair.target_phantom.packed_geometry_id);
duration_vector = facade.GetUncompressedReverseDurations(
phantom_node_pair.target_phantom.packed_geometry_id);
datasource_vector = facade.GetUncompressedReverseDatasources(
phantom_node_pair.target_phantom.packed_geometry_id);
id_vector = facade.GetUncompressedReverseGeometry(target_geometry_id);
weight_vector = facade.GetUncompressedReverseWeights(target_geometry_id);
duration_vector = facade.GetUncompressedReverseDurations(target_geometry_id);
datasource_vector = facade.GetUncompressedReverseDatasources(target_geometry_id);
if (is_local_path)
{
@@ -219,17 +207,10 @@ void annotatePath(const FacadeT &facade,
}
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
id_vector = facade.GetUncompressedForwardGeometry(
phantom_node_pair.target_phantom.packed_geometry_id);
weight_vector = facade.GetUncompressedForwardWeights(
phantom_node_pair.target_phantom.packed_geometry_id);
duration_vector = facade.GetUncompressedForwardDurations(
phantom_node_pair.target_phantom.packed_geometry_id);
datasource_vector = facade.GetUncompressedForwardDatasources(
phantom_node_pair.target_phantom.packed_geometry_id);
id_vector = facade.GetUncompressedForwardGeometry(target_geometry_id);
weight_vector = facade.GetUncompressedForwardWeights(target_geometry_id);
duration_vector = facade.GetUncompressedForwardDurations(target_geometry_id);
datasource_vector = facade.GetUncompressedForwardDatasources(target_geometry_id);
}
// Given the following compressed geometry:
@@ -243,20 +224,19 @@ void annotatePath(const FacadeT &facade,
(start_index < end_index ? ++segment_idx : --segment_idx))
{
BOOST_ASSERT(segment_idx < id_vector.size() - 1);
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
unpacked_path.push_back(PathData{
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
phantom_node_pair.target_phantom.name_id,
weight_vector[segment_idx],
duration_vector[segment_idx],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0);
unpacked_path.push_back(
PathData{id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
facade.GetNameIndex(target_node_id),
weight_vector[segment_idx],
duration_vector[segment_idx],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
facade.GetTravelMode(target_node_id),
INVALID_ENTRY_CLASSID,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
}
if (unpacked_path.size() > 0)
@@ -305,6 +285,59 @@ void annotatePath(const FacadeT &facade,
}
}
template <typename Algorithm>
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const std::vector<PathData> unpacked_path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom)
{
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
using util::coordinate_calculation::detail::EARTH_RADIUS;
double distance = 0;
double prev_lat =
static_cast<double>(util::toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
double prev_lon =
static_cast<double>(util::toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
double prev_cos = std::cos(prev_lat);
for (const auto &p : unpacked_path)
{
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
const double current_lat =
static_cast<double>(util::toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(util::toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
prev_lat = current_lat;
prev_lon = current_lon;
prev_cos = current_cos;
}
const double current_lat =
static_cast<double>(util::toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(util::toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
return distance;
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -23,7 +23,7 @@ namespace ch
// Stalling
template <bool DIRECTION, typename HeapT>
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID node,
const EdgeWeight weight,
const HeapT &query_heap)
@@ -49,10 +49,10 @@ bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
}
template <bool DIRECTION>
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID node,
const EdgeWeight weight,
SearchEngineData::QueryHeap &heap)
SearchEngineData<Algorithm>::QueryHeap &heap)
{
for (const auto edge : facade.GetAdjacentEdgeRange(node))
{
@@ -113,9 +113,9 @@ we need to add an offset to the termination criterion.
static constexpr bool ENABLE_STALLING = true;
static constexpr bool DISABLE_STALLING = false;
template <bool DIRECTION, bool STALLING = ENABLE_STALLING>
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node_id,
EdgeWeight &upper_bound,
EdgeWeight min_edge_offset,
@@ -186,9 +186,8 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
}
template <bool UseDuration>
EdgeWeight
getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
NodeID node)
EdgeWeight getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
NodeID node)
{
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
for (auto edge : facade.GetAdjacentEdgeRange(node))
@@ -228,7 +227,7 @@ getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH
* original edge found.
*/
template <typename BidirectionalIterator, typename Callback>
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
Callback &&callback)
@@ -300,22 +299,25 @@ void unpackPath(const FacadeT &facade,
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
BOOST_ASSERT(nodes_number > 0);
std::vector<NodeID> unpacked_nodes;
std::vector<EdgeID> unpacked_edges;
unpacked_nodes.reserve(nodes_number);
unpacked_edges.reserve(nodes_number);
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
unpacked_nodes.push_back(*packed_path_begin);
if (nodes_number > 1)
{
target_node = *std::prev(packed_path_end);
unpacked_edges.reserve(std::distance(packed_path_begin, packed_path_end));
unpackPath(
facade,
packed_path_begin,
packed_path_end,
[&facade, &unpacked_edges](std::pair<NodeID, NodeID> & /* edge */,
const auto &edge_id) { unpacked_edges.push_back(edge_id); });
unpackPath(facade,
packed_path_begin,
packed_path_end,
[&](std::pair<NodeID, NodeID> &edge, const auto &edge_id) {
BOOST_ASSERT(edge.first == unpacked_nodes.back());
unpacked_nodes.push_back(edge.second);
unpacked_edges.push_back(edge_id);
});
}
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
}
/**
@@ -325,17 +327,17 @@ void unpackPath(const FacadeT &facade,
* @param to the node the CH edge finishes at
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
*/
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const NodeID from,
const NodeID to,
std::vector<NodeID> &unpacked_path);
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
const SearchEngineData::QueryHeap &reverse_heap,
void retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const NodeID middle_node_id,
std::vector<NodeID> &packed_path);
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &search_heap,
const NodeID middle_node_id,
std::vector<NodeID> &packed_path);
@@ -351,37 +353,33 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
std::int32_t &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &,
SearchEngineData::QueryHeap &,
std::int32_t &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
{
search(facade,
forward_heap,
reverse_heap,
weight,
packed_leg,
force_loop_forward,
force_loop_reverse,
duration_upper_bound);
}
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
} // namespace ch
namespace corech
{
// assumes that heaps are already setup correctly.
// A forced loop might be necessary, if source and target are on the same segment.
// If this is the case and the offsets of the respective direction are larger for the source
@@ -391,66 +389,41 @@ inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorith
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
int &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const std::vector<NodeID> &packed_path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom);
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT);
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
inline double
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &,
SearchEngineData::QueryHeap &,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
int duration_upper_bound = INVALID_EDGE_WEIGHT)
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const PhantomNodes &phantom_nodes,
std::vector<PathData> &unpacked_path)
{
return getNetworkDistance(
facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
return ch::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
}
} // namespace ch
} // namespace corech
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -24,9 +24,9 @@ namespace
// Unrestricted search (Args is const PhantomNodes &):
// * use partition.GetQueryLevel to find the node query level based on source and target phantoms
// * allow to traverse all cells
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
NodeID node,
const PhantomNodes &phantom_nodes)
inline LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
NodeID node,
const PhantomNodes &phantom_nodes)
{
auto level = [&partition, node](const SegmentID &source, const SegmentID &target) {
if (source.enabled && target.enabled)
@@ -43,25 +43,31 @@ LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
phantom_nodes.target_phantom.reverse_segment_id)));
}
bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
// Restricted search (Args is LevelID, CellID):
// * use the fixed level for queries
// * check if the node cell is the same as the specified parent onr
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
inline LevelID
getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
{
return level;
}
bool checkParentCellRestriction(CellID cell, LevelID, CellID parent) { return cell == parent; }
inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
{
return cell == parent;
}
}
template <bool DIRECTION, typename... Args>
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
const bool force_loop_forward,
const bool force_loop_reverse,
Args... args)
{
const auto &partition = facade.GetMultiLevelPartition();
@@ -79,7 +85,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
if (path_weight >= 0 && path_weight < path_upper_bound)
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
{
middle_node = node;
path_upper_bound = path_weight;
@@ -170,12 +180,20 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
}
template <typename... Args>
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
std::tuple<EdgeWeight, std::vector<NodeID>, std::vector<EdgeID>>
search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool force_loop_forward,
const bool force_loop_reverse,
EdgeWeight weight_upper_bound,
Args... args)
{
if (forward_heap.Empty() || reverse_heap.Empty())
{
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
}
const auto &partition = facade.GetMultiLevelPartition();
@@ -184,7 +202,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
// run two-Target Dijkstra routing step.
NodeID middle = SPECIAL_NODEID;
EdgeWeight weight = INVALID_EDGE_WEIGHT;
EdgeWeight weight = weight_upper_bound;
EdgeWeight forward_heap_min = forward_heap.MinKey();
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
@@ -192,25 +210,36 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
{
if (!forward_heap.Empty())
{
routingStep<FORWARD_DIRECTION>(
facade, forward_heap, reverse_heap, middle, weight, args...);
routingStep<FORWARD_DIRECTION>(facade,
forward_heap,
reverse_heap,
middle,
weight,
force_loop_forward,
force_loop_reverse,
args...);
if (!forward_heap.Empty())
forward_heap_min = forward_heap.MinKey();
}
if (!reverse_heap.Empty())
{
routingStep<REVERSE_DIRECTION>(
facade, reverse_heap, forward_heap, middle, weight, args...);
routingStep<REVERSE_DIRECTION>(facade,
reverse_heap,
forward_heap,
middle,
weight,
force_loop_reverse,
force_loop_forward,
args...);
if (!reverse_heap.Empty())
reverse_heap_min = reverse_heap.MinKey();
}
};
// No path found for both target nodes?
if (weight == INVALID_EDGE_WEIGHT || SPECIAL_NODEID == middle)
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
{
return std::make_tuple(
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
}
// Get packed path as edges {from node ID, to node ID, edge ID}
@@ -234,11 +263,14 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
current_node = parent_node;
parent_node = reverse_heap.GetData(parent_node).parent;
}
const NodeID target_node = current_node;
// Unpack path
std::vector<EdgeID> unpacked_path;
unpacked_path.reserve(packed_path.size());
std::vector<NodeID> unpacked_nodes;
std::vector<EdgeID> unpacked_edges;
unpacked_nodes.reserve(packed_path.size());
unpacked_edges.reserve(packed_path.size());
unpacked_nodes.push_back(source_node);
for (auto const &packed_edge : packed_path)
{
NodeID source, target;
@@ -246,7 +278,8 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
std::tie(source, target, overlay_edge) = packed_edge;
if (!overlay_edge)
{ // a base graph edge
unpacked_path.push_back(facade.FindEdge(source, target));
unpacked_nodes.push_back(target);
unpacked_edges.push_back(facade.FindEdge(source, target));
}
else
{ // an overlay graph edge
@@ -265,18 +298,121 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
// TODO: when structured bindings will be allowed change to
// auto [subpath_weight, subpath_source, subpath_target, subpath] = ...
EdgeWeight subpath_weight;
NodeID subpath_source, subpath_target;
std::vector<EdgeID> subpath;
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
search(facade, forward_heap, reverse_heap, sublevel, parent_cell_id);
BOOST_ASSERT(!subpath.empty());
BOOST_ASSERT(subpath_source == source);
BOOST_ASSERT(subpath_target == target);
unpacked_path.insert(unpacked_path.end(), subpath.begin(), subpath.end());
std::vector<NodeID> subpath_nodes;
std::vector<EdgeID> subpath_edges;
std::tie(subpath_weight, subpath_nodes, subpath_edges) = search(engine_working_data,
facade,
forward_heap,
reverse_heap,
force_loop_forward,
force_loop_reverse,
INVALID_EDGE_WEIGHT,
sublevel,
parent_cell_id);
BOOST_ASSERT(!subpath_edges.empty());
BOOST_ASSERT(subpath_nodes.size() > 1);
BOOST_ASSERT(subpath_nodes.front() == source);
BOOST_ASSERT(subpath_nodes.back() == target);
unpacked_nodes.insert(
unpacked_nodes.end(), std::next(subpath_nodes.begin()), subpath_nodes.end());
unpacked_edges.insert(unpacked_edges.end(), subpath_edges.begin(), subpath_edges.end());
}
}
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
}
// Alias to be compatible with the CH-based search
inline void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &unpacked_nodes,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{
// TODO: change search calling interface to use unpacked_edges result
std::tie(weight, unpacked_nodes, std::ignore) = search(engine_working_data,
facade,
forward_heap,
reverse_heap,
force_loop_forward,
force_loop_reverse,
weight_upper_bound,
phantom_nodes);
}
// TODO: refactor CH-related stub to use unpacked_edges
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const PhantomNodes &phantom_nodes,
std::vector<PathData> &unpacked_path)
{
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
BOOST_ASSERT(nodes_number > 0);
std::vector<NodeID> unpacked_nodes;
std::vector<EdgeID> unpacked_edges;
unpacked_nodes.reserve(nodes_number);
unpacked_edges.reserve(nodes_number);
unpacked_nodes.push_back(*packed_path_begin);
if (nodes_number > 1)
{
util::for_each_pair(
packed_path_begin,
packed_path_end,
[&facade, &unpacked_nodes, &unpacked_edges](const auto from, const auto to) {
unpacked_nodes.push_back(to);
unpacked_edges.push_back(facade.FindEdge(from, to));
});
}
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
}
inline double
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{
forward_heap.Clear();
reverse_heap.Clear();
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
EdgeWeight weight = INVALID_EDGE_WEIGHT;
std::vector<NodeID> unpacked_nodes;
std::vector<EdgeID> unpacked_edges;
std::tie(weight, unpacked_nodes, unpacked_edges) = search(engine_working_data,
facade,
forward_heap,
reverse_heap,
DO_NOT_FORCE_LOOPS,
DO_NOT_FORCE_LOOPS,
weight_upper_bound,
phantom_nodes);
if (weight == INVALID_EDGE_WEIGHT)
{
return std::numeric_limits<double>::max();
}
std::vector<PathData> unpacked_path;
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
}
} // namespace mld
@@ -13,15 +13,10 @@ namespace engine
namespace routing_algorithms
{
template <typename Algorithm>
InternalRouteResult
shortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint);
InternalRouteResult
shortestPathSearch(SearchEngineData &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint);
@@ -29,7 +29,12 @@ struct TurnData final
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
std::vector<TurnData>
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
const std::vector<RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes);
std::vector<TurnData>
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
const std::vector<RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes);
+51 -31
View File
@@ -3,8 +3,8 @@
#include <boost/thread/tss.hpp>
#include "partition/multi_level_partition.hpp"
#include "util/binary_heap.hpp"
#include "engine/algorithm.hpp"
#include "util/query_heap.hpp"
#include "util/typedefs.hpp"
namespace osrm
@@ -12,6 +12,15 @@ namespace osrm
namespace engine
{
// Algorithm-dependent heaps
// - CH algorithms use CH heaps
// - CoreCH algorithms use CH
// - MLD algorithms use MLD heaps
template <typename Algorithm> struct SearchEngineData
{
};
struct HeapData
{
NodeID parent;
@@ -24,35 +33,20 @@ struct ManyToManyHeapData : HeapData
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
};
struct MultiLayerDijkstraHeapData : HeapData
{
bool from_clique_arc;
MultiLayerDijkstraHeapData(NodeID p) : HeapData(p), from_clique_arc(false) {}
MultiLayerDijkstraHeapData(NodeID p, bool from) : HeapData(p), from_clique_arc(from) {}
};
struct SearchEngineData
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
{
using QueryHeap = util::
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyQueryHeap = util::BinaryHeap<NodeID,
NodeID,
EdgeWeight,
ManyToManyHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using ManyToManyQueryHeap = util::QueryHeap<NodeID,
NodeID,
EdgeWeight,
ManyToManyHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
using MultiLayerDijkstraHeap = util::BinaryHeap<NodeID,
NodeID,
EdgeWeight,
MultiLayerDijkstraHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using MultiLayerDijkstraHeapPtr = boost::thread_specific_ptr<MultiLayerDijkstraHeap>;
static SearchEngineHeapPtr forward_heap_1;
static SearchEngineHeapPtr reverse_heap_1;
static SearchEngineHeapPtr forward_heap_2;
@@ -60,18 +54,44 @@ struct SearchEngineData
static SearchEngineHeapPtr forward_heap_3;
static SearchEngineHeapPtr reverse_heap_3;
static ManyToManyHeapPtr many_to_many_heap;
static MultiLayerDijkstraHeapPtr mld_forward_heap;
static MultiLayerDijkstraHeapPtr mld_reverse_heap;
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
void InitializeOrClearManyToManyThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
};
void InitializeOrClearMultiLayerDijkstraThreadLocalStorage(const unsigned number_of_nodes);
template <>
struct SearchEngineData<routing_algorithms::corech::Algorithm>
: public SearchEngineData<routing_algorithms::ch::Algorithm>
{
};
struct MultiLayerDijkstraHeapData
{
NodeID parent;
bool from_clique_arc;
MultiLayerDijkstraHeapData(NodeID p) : parent(p), from_clique_arc(false) {}
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
};
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
{
using QueryHeap = util::QueryHeap<NodeID,
NodeID,
EdgeWeight,
MultiLayerDijkstraHeapData,
util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
static SearchEngineHeapPtr forward_heap_1;
static SearchEngineHeapPtr reverse_heap_1;
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
};
}
}
@@ -21,9 +21,9 @@ class CompressedEdgeContainer
struct OnewayCompressedEdge
{
public:
NodeID node_id; // refers to an internal node-based-node
EdgeWeight weight; // the weight of the edge leading to this node
EdgeWeight duration; // the duration of the edge leading to this node
NodeID node_id; // refers to an internal node-based-node
SegmentWeight weight; // the weight of the edge leading to this node
SegmentDuration duration; // the duration of the edge leading to this node
};
using OnewayEdgeBucket = std::vector<OnewayCompressedEdge>;
@@ -35,13 +35,13 @@ class CompressedEdgeContainer
const NodeID target_node,
const EdgeWeight weight1,
const EdgeWeight weight2,
const EdgeWeight duration1,
const EdgeWeight duration2);
const EdgeDuration duration1,
const EdgeDuration duration2);
void AddUncompressedEdge(const EdgeID edge_id,
const NodeID target_node,
const EdgeWeight weight,
const EdgeWeight duration);
const SegmentWeight weight,
const SegmentWeight duration);
void InitializeBothwayVector();
unsigned ZipEdges(const unsigned f_edge_pos, const unsigned r_edge_pos);
@@ -63,7 +63,12 @@ class CompressedEdgeContainer
std::unique_ptr<SegmentDataContainer> ToSegmentData();
private:
SegmentWeight ClipWeight(const SegmentWeight weight);
SegmentDuration ClipDuration(const SegmentDuration duration);
int free_list_maximum = 0;
std::atomic_size_t clipped_weights{0};
std::atomic_size_t clipped_durations{0};
void IncreaseFreeList();
std::vector<OnewayEdgeBucket> m_compressed_oneway_geometries;
+25 -18
View File
@@ -13,23 +13,6 @@ namespace extractor
struct EdgeBasedEdge
{
public:
EdgeBasedEdge();
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &other);
EdgeBasedEdge(const NodeID source,
const NodeID target,
const NodeID edge_id,
const EdgeWeight weight,
const EdgeWeight duration,
const bool forward,
const bool backward);
bool operator<(const EdgeBasedEdge &other) const;
NodeID source;
NodeID target;
struct EdgeData
{
EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {}
@@ -51,7 +34,24 @@ struct EdgeBasedEdge
std::uint32_t backward : 1;
auto is_unidirectional() const { return !forward || !backward; }
} data;
};
EdgeBasedEdge();
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &other);
EdgeBasedEdge(const NodeID source,
const NodeID target,
const NodeID edge_id,
const EdgeWeight weight,
const EdgeWeight duration,
const bool forward,
const bool backward);
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
bool operator<(const EdgeBasedEdge &other) const;
NodeID source;
NodeID target;
EdgeData data;
};
static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
"Size of extractor::EdgeBasedEdge type is "
@@ -73,6 +73,13 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
{
}
inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID target,
const EdgeBasedEdge::EdgeData &data)
: source(source), target(target), data{data}
{
}
inline bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
{
const auto unidirectional = data.is_unidirectional();
+23 -15
View File
@@ -5,22 +5,26 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/edge_based_node_segment.hpp"
#include "extractor/extraction_turn.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "util/concurrent_id_map.hpp"
#include "util/deallocating_vector.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/packed_vector.hpp"
#include "util/typedefs.hpp"
#include "storage/io.hpp"
@@ -38,6 +42,9 @@
#include <boost/filesystem/fstream.hpp>
#include <tbb/concurrent_unordered_map.h>
#include <tbb/concurrent_vector.h>
namespace osrm
{
namespace extractor
@@ -50,13 +57,13 @@ namespace lookup
#pragma pack(push, 1)
struct TurnIndexBlock
{
OSMNodeID from_id;
OSMNodeID via_id;
OSMNodeID to_id;
NodeID from_id;
NodeID via_id;
NodeID to_id;
};
#pragma pack(pop)
static_assert(std::is_trivial<TurnIndexBlock>::value, "TurnIndexBlock is not trivial");
static_assert(sizeof(TurnIndexBlock) == 24, "TurnIndexBlock is not packed correctly");
static_assert(sizeof(TurnIndexBlock) == 12, "TurnIndexBlock is not packed correctly");
} // ns lookup
struct NodeBasedGraphToEdgeBasedGraphMappingWriter; // fwd. decl
@@ -72,7 +79,8 @@ class EdgeBasedGraphFactory
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
const std::vector<util::Coordinate> &coordinates,
const extractor::PackedOSMIDs &osm_node_ids,
ProfileProperties profile_properties,
const util::NameTable &name_table,
std::vector<std::uint32_t> &turn_lane_offsets,
@@ -80,7 +88,7 @@ class EdgeBasedGraphFactory
guidance::LaneDescriptionMap &lane_description_map);
void Run(ScriptingEnvironment &scripting_environment,
const std::string &original_edge_data_filename,
const std::string &turn_data_filename,
const std::string &turn_lane_data_filename,
const std::string &turn_weight_penalties_filename,
const std::string &turn_duration_penalties_filename,
@@ -89,7 +97,8 @@ class EdgeBasedGraphFactory
// The following get access functions destroy the content in the factory
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
void GetEdgeBasedNodes(EdgeBasedNodeDataContainer &data_container);
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
@@ -124,11 +133,13 @@ class EdgeBasedGraphFactory
std::vector<EdgeWeight> m_edge_based_node_weights;
//! list of edge based nodes (compressed segments)
std::vector<EdgeBasedNode> m_edge_based_node_list;
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
EdgeBasedNodeDataContainer m_edge_based_node_container;
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
EdgeID m_max_edge_id;
const std::vector<QueryNode> &m_node_info_list;
const std::vector<util::Coordinate> &m_coordinates;
const extractor::PackedOSMIDs &m_osm_node_ids;
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
std::shared_ptr<RestrictionMap const> m_restriction_map;
@@ -156,16 +167,13 @@ class EdgeBasedGraphFactory
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
void FlushVectorToStream(storage::io::FileWriter &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
std::size_t restricted_turns_counter;
std::size_t skipped_uturns_counter;
std::size_t skipped_barrier_turns_counter;
std::unordered_map<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
util::ConcurrentIDMap<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
std::vector<BearingClassID> bearing_class_by_node_based_node;
std::unordered_map<util::guidance::EntryClass, EntryClassID> entry_class_hash;
util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID> entry_class_hash;
};
} // namespace extractor
} // namespace osrm
-70
View File
@@ -1,70 +0,0 @@
#ifndef EDGE_BASED_NODE_HPP
#define EDGE_BASED_NODE_HPP
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include "osrm/coordinate.hpp"
#include <limits>
namespace osrm
{
namespace extractor
{
/// This is what util::StaticRTree serialized and stores on disk
/// It is generated in EdgeBasedGraphFactory.
struct EdgeBasedNode
{
EdgeBasedNode()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
name_id(0), packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
fwd_segment_position(std::numeric_limits<unsigned short>::max()),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
explicit EdgeBasedNode(const SegmentID forward_segment_id_,
const SegmentID reverse_segment_id_,
NodeID u,
NodeID v,
unsigned name_id,
unsigned packed_geometry_id_,
bool is_tiny_component,
unsigned component_id,
unsigned short fwd_segment_position,
TravelMode forward_travel_mode,
TravelMode backward_travel_mode)
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
v(v), name_id(name_id), packed_geometry_id(packed_geometry_id_),
component{component_id, is_tiny_component}, fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
{
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
}
SegmentID forward_segment_id; // needed for edge-expanded graph
SegmentID reverse_segment_id; // needed for edge-expanded graph
NodeID u; // indices into the coordinates array
NodeID v; // indices into the coordinates array
unsigned name_id; // id of the edge name
unsigned packed_geometry_id;
struct
{
unsigned id : 31;
bool is_tiny : 1;
} component;
unsigned short fwd_segment_position; // segment id in a compressed geometry
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
};
}
}
#endif // EDGE_BASED_NODE_HPP
@@ -0,0 +1,49 @@
#ifndef OSRM_EXTRACT_EDGE_BASED_NODE_SEGMENT_HPP
#define OSRM_EXTRACT_EDGE_BASED_NODE_SEGMENT_HPP
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include "osrm/coordinate.hpp"
#include <limits>
namespace osrm
{
namespace extractor
{
/// This is what util::StaticRTree serialized and stores on disk
/// It is generated in EdgeBasedGraphFactory.
struct EdgeBasedNodeSegment
{
EdgeBasedNodeSegment()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
fwd_segment_position(std::numeric_limits<unsigned short>::max())
{
}
explicit EdgeBasedNodeSegment(const SegmentID forward_segment_id_,
const SegmentID reverse_segment_id_,
NodeID u,
NodeID v,
unsigned short fwd_segment_position)
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
v(v), fwd_segment_position(fwd_segment_position)
{
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
}
SegmentID forward_segment_id; // edge-based graph node ID in forward direction (u->v)
SegmentID reverse_segment_id; // edge-based graph node ID in reverse direction (v->u if exists)
NodeID u; // node-based graph node ID of the start node
NodeID v; // node-based graph node ID of the target node
unsigned short fwd_segment_position; // segment id in a compressed geometry
};
}
}
#endif // OSRM_EXTRACT_EDGE_BASED_NODE_SEGMENT_HPP
+4 -3
View File
@@ -40,7 +40,7 @@ class ExtractionContainers
void PrepareEdges(ScriptingEnvironment &scripting_environment);
void WriteNodes(storage::io::FileWriter &file_out) const;
void WriteRestrictions(const std::string &restrictions_file_name) const;
void WriteRestrictions(const std::string &restrictions_file_name);
void WriteEdges(storage::io::FileWriter &file_out) const;
void WriteCharData(const std::string &file_name);
@@ -48,7 +48,7 @@ class ExtractionContainers
using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
using RestrictionsVector = std::vector<InputRestrictionContainer>;
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
using STXXLNameCharData = stxxl::vector<unsigned char>;
using STXXLNameOffsets = stxxl::vector<unsigned>;
@@ -59,10 +59,11 @@ class ExtractionContainers
STXXLNameCharData name_char_data;
STXXLNameOffsets name_offsets;
// an adjacency array containing all turn lane masks
STXXLRestrictionsVector restrictions_list;
RestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;
unsigned max_internal_node_id;
std::vector<TurnRestriction> unconditional_turn_restrictions;
ExtractionContainers();
+17 -14
View File
@@ -56,32 +56,35 @@ class Extractor
private:
ExtractorConfig config;
std::vector<TurnRestriction> ParseOSMData(ScriptingEnvironment &scripting_environment,
const unsigned number_of_threads);
std::pair<std::size_t, EdgeID>
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<util::Coordinate> &coordinates,
extractor::PackedOSMIDs &osm_node_ids,
EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file);
const std::string &intersection_class_output_file,
std::vector<TurnRestriction> &turn_restrictions);
void WriteProfileProperties(const std::string &output_path,
const ProfileProperties &properties) const;
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &edges,
std::vector<EdgeBasedNode> &nodes) const;
void BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
const std::vector<EdgeBasedNodeSegment> &input_node_segments,
EdgeBasedNodeDataContainer &nodes_container) const;
void BuildRTree(std::vector<EdgeBasedNodeSegment> edge_based_node_segments,
std::vector<bool> node_is_startpoint,
const std::vector<QueryNode> &internal_to_external_node_map);
const std::vector<util::Coordinate> &coordinates);
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
std::shared_ptr<util::NodeBasedDynamicGraph>
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
std::unordered_set<NodeID> &traffic_lights,
std::vector<QueryNode> &internal_to_external_node_map);
void WriteEdgeBasedGraph(const std::string &output_file_filename,
const EdgeID max_edge_id,
util::DeallocatingVector<EdgeBasedEdge> const &edge_based_edge_list);
std::vector<util::Coordinate> &coordinates,
extractor::PackedOSMIDs &osm_node_ids);
void WriteIntersectionClassificationData(
const std::string &output_file_name,
@@ -94,7 +97,7 @@ class Extractor
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
static void WriteCompressedNodeBasedGraph(const std::string &path,
const util::NodeBasedDynamicGraph &graph,
const std::vector<QueryNode> &externals);
const std::vector<util::Coordinate> &coordiantes);
// globals persisting during the extraction process and the graph generation process

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