Compare commits

...

171 Commits

Author SHA1 Message Date
Daniel Patterson c49fd202d0 Disable MLD tests so we can get a macOS build completed. 2019-02-10 02:37:29 -08:00
Daniel Patterson 49e40ee621 Bump version again. 2019-02-10 02:36:27 -08:00
Daniel Patterson a89d0e616f Fix node bindings and test cases that would've caught it. 2019-02-10 02:36:16 -08:00
Daniel Patterson 986252c4f9 Quick fix for negative distances bug. 2019-02-10 02:09:30 -08:00
Daniel Patterson aed7df6173 New build with fixed tests. 2019-02-10 01:07:33 -08:00
Daniel Patterson e3b09875c6 Fix nodejs tests. 2019-02-10 01:06:54 -08:00
Daniel Patterson 52ceea429b Bump version. 2019-02-10 00:54:35 -08:00
Kevin Kreiser 3d4d51d6b7 Consider acceleration profile of vehicle travelling - particularly affects very short routes. 2019-02-10 00:53:40 -08:00
Daniel Patterson 23c69f4c3d Revert "Add stoppage penalty - consider acceleration and braking time, which can dominate short route ETAs."
This reverts commit 05647adcc6.
2019-02-10 00:42:47 -08:00
Daniel Patterson 9d044bf388 Revert "Fix swapped variables, new version."
This reverts commit 67e99c9809.
2019-02-10 00:42:46 -08:00
Daniel Patterson 823d7e45e7 Revert "change phantom node to store an appx speed regardless of direction. use this speed to estimate an accel/decel penalty and scale the penalty based on the distance traveled up to a cutoff. only used in the table plugin at the moment. TODO still lives in the guidance assemble_leg area"
This reverts commit ca55521c87.
2019-02-10 00:42:10 -08:00
Daniel Patterson 6b961dccfc Revert "Add a bunch of tests at different scales. Switch to using linear acceleration estimates to add penalties to start/end of trips."
This reverts commit 6b9006f6e7.
2019-02-10 00:42:08 -08:00
Daniel Patterson 44d4903985 Bump another test release. 2019-02-09 02:55:39 -08:00
Daniel Patterson 55e05b70ac Revert accidental change. 2019-02-09 02:55:18 -08:00
Daniel Patterson 210908dbe6 Bump new test release. 2019-02-09 02:42:38 -08:00
Daniel Patterson 6b9006f6e7 Add a bunch of tests at different scales. Switch to using linear acceleration estimates to add penalties to start/end of trips. 2019-02-09 02:31:36 -08:00
Kevin Kreiser ca55521c87 change phantom node to store an appx speed regardless of direction. use this speed to estimate an accel/decel penalty and scale the penalty based on the distance traveled up to a cutoff. only used in the table plugin at the moment. TODO still lives in the guidance assemble_leg area 2019-02-09 02:31:26 -08:00
Daniel Patterson 67e99c9809 Fix swapped variables, new version. 2019-02-08 15:50:33 -08:00
Kevin Kreiser 05647adcc6 Add stoppage penalty - consider acceleration and braking time, which can dominate short route ETAs. 2019-02-08 15:32:26 -08:00
Daniel Patterson 6c37b71046 Actually expose snapping in node bindings. 2019-02-03 12:09:24 -08:00
Daniel Patterson cb2a46b8d9 Merge changes from c1eda57c13 - add snapping=any|default parameter. 2019-02-03 10:40:26 -08:00
Daniel Patterson b1451a7421 Release 5.21.0 2018-12-18 16:17:34 -07:00
Daniel Patterson da1c251144 Prep 5.21.0-rc.1 2018-12-15 21:43:10 -07:00
Daniel Patterson 1eab7b41d1 Update CHANGELOG. 2018-12-15 21:07:06 -07:00
Daniel Patterson 1dca8ae76a Correct invalid tests - these captured the incorrect behaviour, the matrices should've been symmetrical (a->o == o->a for these cases) 2018-12-15 21:07:06 -07:00
Daniel Patterson 002e86863d Add test to ensure forward/reverse snapping distances are correct, and fix some tests that were incorrect due to the bug. 2018-12-15 21:07:06 -07:00
Daniel Patterson 1d82b01816 Count reverse offset from the back of the geometry, not the front. 2018-12-15 21:07:06 -07:00
Frédéric Rodrigo 714719c377 Lua maxspeed parsing refactoring (#5144)
* Lua maxspeed parsing refactoring
2018-12-14 21:58:07 -07:00
Huyen Chau Nguyen 77b4fbb69c Fix maxspeed to consider source:maxspeed tags (#5217)
* In Belgium the maximum speed in rural areas is 70 in the region Flanders
* parse maxspeed using source:maxspeed and maxspeed:type tags
* add changelog
* make maxspeed:advisory more important than maxspeed
* add test for source:maxspeed
2018-12-14 21:42:44 -07:00
Matt Riggott 11fde865f7 Document switch to Debian base images (#5281)
* Document switch to Debian base images
2018-12-14 21:36:09 -07:00
Salim KAYABASI 717406043a Remove unused Node binary publishing, and upgrade build environment.
Upgrades the build environment to Node 10, which let's us pull down some security fixes in package dependencies that were unfixed in Node 4.

Also removes Node 4 and 6 binary publishing which were almost never used (20 downloads out of 50,000).

Fixes https://github.com/Project-OSRM/osrm-backend/issues/5312
2018-12-14 21:34:48 -07:00
Daniel Patterson 1ef85c57cc Upgrade CI environment to Node 10, remove builds for < Node 8
Remove yarn, npm is fast now, and comes with node.
Synchronize package-lock.json and package.json
2018-12-14 14:56:21 -07:00
Daniel Patterson d0180517a8 Merge branch 'master' of github.com:Project-OSRM/osrm-backend 2018-12-14 11:54:00 -07:00
Daniel Patterson 520b7ebbb6 Remove 5.20 build trigger from master branch - should only exist on release branches. 2018-12-14 11:53:48 -07:00
Dinesh Weerapurage 2caba96076 using libboost 1.67 in both build and run stages (#5311)
* using libboost 1.67 in both build and run stages, added execution permision for /opt
2018-12-14 11:51:05 -07:00
Daniel Patterson 81bc2f41a6 When matching, ignore 'is_startpoint' propert, snap to any edge (#5297)
Includes all edges in the rtree, but adds an `is_startpoint` flag to each.  Most plugin behaviour remains unchanged (non-startpoint edges aren't used as snapping candidates), but for map matching, we allow snapping to any edge.  This fixes map-matching across previously non-is_startpoint edges, like ferries, private service roads, and a few others.
2018-12-13 17:10:32 -07:00
Daniel Patterson 06e010b4d0 Include information on estimates in table response (#5259)
* Revert "Remove estimated_cells value in the response."

This reverts commit 364e35af06.

* Update changelog.

* fix linting

* adjust fallback_speed check

* change [].includes to [].indexOf !== -1 for compatibility with node 4

* change param name

* more cuke tests

* fix formatting
2018-12-11 12:21:57 -05:00
Kajari Ghosh 92d3ce789b Fix scale_factor bug (#5303)
* check for scale_factor != 1

* changelog
2018-12-10 17:11:08 -05:00
Kajari Ghosh 01ca32c81c Fix fallback speed validity checks (#5300)
* fix fallback_speeds check to only accept values > 0

* add invalid_fallback_speed
2018-12-10 14:53:30 -05:00
Kajari Ghosh 2e17f3010a Add a multiplier to the matrix (#5298)
* add a multiplier to the matrix

* add rounding

* remove scale_factor restrictions

* clamp for overflow error

* update check to match error message

* enforce clamping on < 0 and increase test coverage

* add an invalid scale_factor value to node tests

* increase test coverage

* changelog
2018-12-10 13:41:44 -05:00
Kajari Ghosh c4238c4ed6 Backport-v5.20.0 (#5301)
* Prepare RC.1

* Bump version.

* remove destination/sources length <= coordinates length check (#5289)

* Add node 10 builds to travis (#5246)

* Add node 10 builds to travis

* Add changelog

* bump version to rc5

* Fix fallback_speed vector access (#5291)

* add failing cuke test

* correctly access durations vector

* changelog

* one more cuke test

* bump rc version

* 5.20.0

* remove line from changelog about commit that isn't actually in here

* update CHANGELOG and osrm version in package.json for v5.20.0

* bump to restart appveyor
2018-12-10 11:27:13 -05:00
Kajari Ghosh 3d781e6f28 Fix fallback_speed vector access (#5291)
* add failing cuke test

* correctly access durations vector

* changelog

* one more cuke test
2018-12-05 00:41:06 -05:00
Daniel Paz-Soldan 4976233cff Add node 10 builds to travis (#5246)
* Add node 10 builds to travis

* Add changelog
2018-12-04 14:13:49 -05:00
Kajari Ghosh 98ea2a0b09 remove destination/sources length <= coordinates length check (#5289) 2018-12-04 13:35:26 -05:00
Dinesh Weerapurage f978900ab0 adding a debian based docker image 2018-11-08 12:03:35 +01:00
Daniel Patterson 8b6580128b Merge pull request #5255 from Project-OSRM/danpat_snapped_distance_everywhere
Return 'distance' in all waypoints for all APIs
2018-11-02 15:36:27 -07:00
Daniel Patterson 4dde9c7bbe Include distance from input to snapped for all waypoints, not just on the nearest service. 2018-11-02 15:30:52 -07:00
Daniel Patterson 973837207b Merge pull request #5257 from Project-OSRM/danpat_table_noroute_estimate
Use estimates for NoRoute in table requests
2018-11-02 01:41:50 -07:00
Daniel Patterson 364e35af06 Remove estimated_cells value in the response. 2018-11-02 01:08:59 -07:00
Daniel Patterson 985ab58f45 Add feature to fill null table entries with as-the-crow-flies estimates. 2018-11-02 01:07:24 -07:00
Daniel Patterson cb1db646f2 Merge pull request #5251 from Project-OSRM/danpat_cache_distances
Pre-calculate distance values
2018-10-30 16:14:47 -07:00
Daniel Patterson a67c4bf84d Calculating durations is unavoidable due to tie-breaking minimums, but we can avoid accumulating distances if they're not requested. 2018-10-30 15:41:06 -07:00
Daniel Patterson 498259b220 Replace dynamic distance calculation for table plugin with pre-calculated distances on shortcuts, avoiding unpacking cost.
Adds approx 10% to total data size.  Speeds up large table requests by 2 orders of magnitude.

Co-authored-by: Kajari Ghosh <ghoshkaj@gmail.com>
2018-10-30 15:41:06 -07:00
Daniel Patterson 5327f8da4e Timer script should error properly if something goes wrong, and print out what happened. 2018-10-30 15:41:06 -07:00
Daniel Patterson 802ccfb497 Merge pull request #5252 from Project-OSRM/danpat_pin_yarn
Pin Yarn to 1.11.1 so it works with Node4
2018-10-30 15:40:19 -07:00
Daniel Patterson ec369d560a Pin Yarn to 1.11.1 so it works with Node4 (https://github.com/yarnpkg/yarn/pull/6409#issuecomment-429181371) 2018-10-30 15:38:55 -07:00
Daniel Patterson 535647e439 Merge pull request #5242 from Project-OSRM/ghoshkaj_mmaperize
Support directly mmap-ing datafiles
2018-10-29 11:58:26 -07:00
Daniel Patterson 954121634f Merge branch 'master' into ghoshkaj_mmaperize 2018-10-29 09:52:50 -07:00
Daniel Patterson 594a45e7e0 Re-use msinttypes bundled with RapidJSON when compiling on Windows. (#5249) 2018-10-29 09:51:56 -07:00
Daniel Patterson 96c7b47afe Document new mmap_memory option in NodeJS API 2018-10-27 00:12:17 -07:00
Daniel Patterson b7e7d32361 Expose new --mmap switch (mmap_memory: true in NodeJS), and run test suite in this mode, as well as shared memory mode. 2018-10-26 23:54:00 -07:00
Daniel Patterson 2f9cb44368 mmap tarfiles directly when mmapping is enabled, instead of copying data into separate mmapped block
Co-authored-by: Kajari Ghosh <ghoshkaj@gmail.com>
2018-10-26 23:53:59 -07:00
Daniel Patterson d80318f8ea Match serialized bit-packing for vector<bool> to match in-memory layout for vector_view<bool> so that data can be directly mmapped. 2018-10-26 23:53:50 -07:00
Daniel Paz-Soldan b1791d1ab3 Fix anchor links in api docs (#5235) 2018-10-16 09:23:29 -07:00
Yota Toyama a53da9095a Fix table node API docs (#5204) 2018-10-01 16:45:05 +03:00
Kajari Ghosh 72e03f9af9 update changelog after 5.19 release (#5203) 2018-09-11 00:34:40 -04:00
Kajari Ghosh 5597415f28 Revert "Improve speed of Map Matching" (#5196)
* Revert "Update changelog"

This reverts commit 9b779c704f.

* Revert "Fix formating"

This reverts commit 5bd7d04fe3.

* Revert "Fix bug in computation of distance offset for phantom node"

This reverts commit 0f78f7b2cc.

* Revert "Adjust text cases for flightly different matching due to rounding"

This reverts commit 8473be69d2.

* Revert "Round network distance to deci-meter to retain previous behavior"

This reverts commit c0124f7d77.

* Revert "Preserve heap state in map matching"

This reverts commit b630b4e32a.

* Revert "Use distance functions from many to many"

This reverts commit 89fabc1b9c.

* Revert "Use FCC algorithm for map matching distance calculation"

This reverts commit a649a8a5cf.
2018-09-06 12:05:28 -04:00
Jie 5476f6ab27 Fix GDB not work for osrm-routed on Linux (#5157)
As I mentioned in the issue #5156, I met below issue on my Win10+WSL(Ubuntu) env:
The remote debugger (VSCode on Win10, gdb on Ubuntu 18.04 LTS) works well from the beginning of the main() function. But when I step over the code pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); (src/tools/routed.cpp(289)), below breakpoints can not work and displayed unverified breakpoint.

Then I found that gdb breakpoint need at least SIGTRAP, SIGSTOP to work (Please refer to [how debugger works](http://www.alexonlinux.com/how-debugger-works) for more details), but all signals are blocked in the source code until server initialized done.

In my understanding, block all signals DO NOT make sense for this osrm-routed process. Only several signals (SIGINT, SIGQUIT, SIGTERM) are expected to wait. So I made the change and it works well for me then.
2018-09-05 16:23:48 -07:00
Daniel Patterson 0971f06193 Add option to node bindings to return result as a pre-generated JSON string (this avoids a lot of overhead, and moves JSON string rendering out of the main event loop). 2018-09-05 15:09:13 -07:00
Daniel Patterson 85515f063a Render floating point numbers to string using Grisu2 algorithmt instead of stdlib to speed up JSON generation. 2018-09-05 14:20:47 -07:00
Daniel Patterson 69d7825542 Increase allowed shared memory regions to 512 from ~120 2018-09-05 11:48:02 -07:00
Patrick Niklaus 9b779c704f Update changelog 2018-08-02 12:19:24 +02:00
Patrick Niklaus 5bd7d04fe3 Fix formating 2018-08-02 12:19:24 +02:00
Patrick Niklaus 0f78f7b2cc Fix bug in computation of distance offset for phantom node 2018-08-02 12:19:24 +02:00
Patrick Niklaus 8473be69d2 Adjust text cases for flightly different matching due to rounding 2018-08-02 12:19:24 +02:00
Patrick Niklaus c0124f7d77 Round network distance to deci-meter to retain previous behavior 2018-08-02 12:19:24 +02:00
Patrick Niklaus b630b4e32a Preserve heap state in map matching 2018-08-02 12:19:24 +02:00
Patrick Niklaus 89fabc1b9c Use distance functions from many to many 2018-08-02 12:19:24 +02:00
Patrick Niklaus a649a8a5cf Use FCC algorithm for map matching distance calculation 2018-08-02 12:19:24 +02:00
Frédéric Rodrigo f928956584 Support maxlength and maxweight in car profile 2018-07-11 18:33:30 +02:00
Frédéric Rodrigo 7ff68792d7 Add helper for maxlength into measure.lua 2018-07-11 18:33:30 +02:00
Frédéric Rodrigo 3088dd0342 Better and flexible weight parsing in measure.lua 2018-07-11 18:33:30 +02:00
Frédéric Rodrigo d2590989f5 Default maxspeed for fr:rural is now 80km/h 2018-07-11 17:54:46 +02:00
Antoine Giret 3a7b377586 Update profiles.md 2018-06-27 14:27:17 +02:00
Michael Krasnyk 82b5648c97 Don't collapse segregated intersections at roundabout exits, #5114 2018-06-21 15:24:03 +02:00
Antoine Giret 1628a3c4d5 Update profiles.md 2018-06-07 15:43:06 +02:00
Matthias Gilch e5d8319c43 Removed unused variable
The variable name_data_mutex is declared in a block but never used
within this block. So I've removed the variable.
2018-06-02 22:49:30 +02:00
MichalPP 06699132eb allow routing over barrier=some_tag 2018-05-29 16:56:15 +02:00
MichalPP 918e794d6a change barrier_whitelist to barrier blacklist
change barrier_whitelist to barrier blacklist  in foot profile
fix #5067 and #3890 and #4823
2018-05-29 16:56:15 +02:00
MichalPP 8dd8ee1fc2 blacklisting barriers allow routing
blacklisting barriers allow routing over barrier=some_tag
2018-05-28 17:21:08 +02:00
MichalPP c3d0efda93 change barrier_whitelist to barrier_blacklist 2018-05-28 17:21:08 +02:00
Patrick Niklaus 3b4e2e83ef Fix excluding nodes for one to all query 2018-05-08 15:50:25 +00:00
Patrick Niklaus c459530cb6 Address PR comments 2018-05-08 15:50:25 +00:00
Kajari Ghosh 2a15e6dec8 Add support for annotations=distances in MLD
This commit brings feature parity with CH for the `table` pluging.
2018-05-08 15:50:25 +00:00
Huyen Chau Nguyen 1a1293608d fix example requests for distance tables 2018-05-02 17:25:01 +02:00
Michael Krasnyk 318df9deaa Adjust ebn_weight assertion to new node weights 2018-05-01 18:53:04 +02:00
Michael Krasnyk cacb162520 Review and rebase updates 2018-04-28 08:59:18 +02:00
Michael Krasnyk 105709cb43 Don't handle response errors separately in osrm-runner 2018-04-28 08:59:18 +02:00
Michael Krasnyk 9695fa7941 Remove weight and duration from customizer::EdgeBasedGraphEdgeData 2018-04-28 08:59:18 +02:00
Michael Krasnyk fd9bebbfa7 Add EBG node durations 2018-04-28 08:59:18 +02:00
Michael Krasnyk db18e8669f Always read .osrm.enw file in updater 2018-04-28 08:59:18 +02:00
Michael Krasnyk 9b4a4fdd82 Add customizer::MultiLevelGraph 2018-04-28 08:59:18 +02:00
Michael Krasnyk cdc7e5f021 Fix for updating node weights in contraction hierarchy 2018-04-28 08:59:18 +02:00
Michael Krasnyk adc87149e2 List dataset blocks 2018-04-28 08:59:18 +02:00
Michael Krasnyk 8adbfe06ed Throw an exception if a shared region is not found 2018-04-28 08:59:18 +02:00
Patrick Niklaus ae805f9ec8 Make cheap rulers static 2018-04-27 05:21:08 +02:00
Patrick Niklaus be24689b0f Optimize distance calculation by getting rid of rounding 2018-04-27 05:21:08 +02:00
Michael Krasnyk 41c31a2388 Use mapbox::util::optional instead of std::experimental::optional 2018-04-27 05:21:08 +02:00
Huyen Chau Nguyen 8b866502d1 make eslint happy 2018-04-27 05:21:08 +02:00
Huyen Chau Nguyen 7837cd61df clang format 2018-04-27 05:21:08 +02:00
Huyen Chau Nguyen b573485c31 only use half of rulers because earth is symmetric 2018-04-27 05:21:08 +02:00
Huyen Chau Nguyen 4e68f3a7e1 change haversine computation to cheap ruler in distance tables 2018-04-27 05:21:08 +02:00
Huyen Chau Nguyen 5ba26d3d6d refactor cheap ruler cache 2018-04-27 05:21:08 +02:00
Daniel Patterson a6cf2eee7e Use faster method for calculating distances.
fix cmakelist
2018-04-27 05:21:08 +02:00
Patrick Niklaus 6843eb1479 Add changelog entries for profile changtes 2018-04-26 21:46:20 +02:00
Patrick Niklaus b331885d3c Add test fo excluding ferries on bikes 2018-04-26 21:46:20 +02:00
Patrick Niklaus 73716bd651 Add support for classes on bicycle profile 2018-04-26 21:46:20 +02:00
Michael Krasnyk 9edd161da3 Test for "No turn issued for right turn on un-named roads", #4414
The issue is fixed by d166fc6a75
2018-04-26 18:53:47 +02:00
Kajari Ghosh 1bc3ff6491 fix the ascii art to make sense 2018-04-25 23:51:27 +02:00
Kajari Ghosh b0f2ef287e fix the offset case when there is no packed path to unpack 2018-04-25 23:51:27 +02:00
Patrick Niklaus 16f53ff81a Sort unpacked paths by sharing 2018-04-25 16:07:31 +02:00
Patrick Niklaus 7a260dc2ba More parameter tuning 2018-04-25 16:07:31 +02:00
Patrick Niklaus 1c0d951f5e Adjust to PR comments 2018-04-25 16:07:31 +02:00
Patrick Niklaus 77a740c0fb Parameter tuning for different route lengths 2018-04-25 16:07:31 +02:00
Patrick Niklaus 61101db8cf Use duration and not weight for sharing 2018-04-25 16:07:31 +02:00
Patrick Niklaus b51632a2fb Chose alternatives parameters based on coordinate distance 2018-04-25 16:07:31 +02:00
Patrick Niklaus 9d10503a9c Replace step function with contious scaling 2018-04-25 16:07:31 +02:00
Patrick Niklaus 7d50e5afe0 Refactor parameters to be selected at runtime 2018-04-25 16:07:31 +02:00
Patrick Niklaus 549216c792 Compute sharing weighted by edge weight
This ensures that small insignificat turns don't affect the overall
sharing metric too much.
2018-04-25 16:07:31 +02:00
Patrick Niklaus 1990de7dcc Fix inserting edges of shortest path for sharing check
This caused very sub-optimal routes to be selected.
2018-04-25 16:07:31 +02:00
Kajari Ghosh 89f6e2d55b Parse table annotations param correctly (#5050)
* fix incorrect parameter parsing for node osrm and add tests

* fix boost spirit grammar parsing for annotations

* return NotImplemented when distance annotation is requested for MLD in table plugin

* update docs
2018-04-24 11:05:35 -04:00
Michael Krasnyk c628ecbf24 Update tile unit tests 2018-04-24 15:40:57 +02:00
Jochen Topf b6f19cd544 Use vtzero in tile plugin.
This uses the new vtzero library (https://github.com/mapbox/vtzero)
instead of using protozero directly.
2018-04-24 15:40:57 +02:00
Kajari Ghosh 14860b62e9 Unpack paths and return total distance in matrix plugin for CH (#4990) 2018-04-20 18:18:55 -04:00
Patrick Niklaus 9970b7d580 Merge pull request #5037 from Project-OSRM/subtrees-protozero-vtzero
Update libosmium and add protozero and vtzero libraries
2018-04-20 20:44:36 +02:00
Patrick Niklaus 7feb79ef91 Merge branch 'master' into subtrees-protozero-vtzero 2018-04-20 13:32:49 +00:00
Antoine Giret 6f84812903 Update profiles.md 2018-04-20 15:29:16 +02:00
Karen Shea 8085e86170 Change emoji 2018-04-20 13:19:48 +02:00
Karen Shea 35973576d9 Update releasing.md 2018-04-20 13:19:06 +02:00
Duane Gearhart 7740d5d7c0 Do not combine a segregated edge with a roundabout (#5040)
* Do not combine a segregated edge with a roundabout, add test
2018-04-20 11:41:53 +02:00
Patrick Niklaus c4eff6cd65 Add option to osrm-runner to limit the distance 2018-04-20 08:14:03 +03:00
Michael Krasnyk 5c4353b46e Removing submodules 2018-04-19 22:13:07 +03:00
Michael Krasnyk 05a5918909 Update CMakeLists.txt file 2018-04-19 22:13:06 +03:00
Michael Krasnyk 80ad38bbc6 Merge commit '6bee8866de99a602039feef463c22c972f0f86aa' as 'third_party/vtzero' 2018-04-19 22:03:52 +03:00
Michael Krasnyk 6bee8866de Squashed 'third_party/vtzero/' content from commit 2b43c8f5c
git-subtree-dir: third_party/vtzero
git-subtree-split: 2b43c8f5c7cc461a874a657673dfc15f8fb21d1d
2018-04-19 22:03:52 +03:00
Michael Krasnyk ba92674c6e Merge commit '68019a1fb20928beaa7b0cb2d8310af29ffe789e' as 'third_party/protozero' 2018-04-19 22:03:49 +03:00
Michael Krasnyk 68019a1fb2 Squashed 'third_party/protozero/' content from commit d5d8debf1
git-subtree-dir: third_party/protozero
git-subtree-split: d5d8debf1b17c6bb652395957b76cde7787e5377
2018-04-19 22:03:49 +03:00
Michael Krasnyk 3a9acde2c3 Merge commit 'a3a7a822e136d2357660d85124d8e7bb26ea6f7c' into subtrees-protozero-vtzero 2018-04-19 22:03:25 +03:00
Michael Krasnyk a3a7a822e1 Squashed 'third_party/libosmium/' changes from ce865381f..d2c1d872b
d2c1d872b Release v2.14.0
9c9aedd50 Update embedded catch.hpp to version 1.12.1.
f94e70d32 Change comment on namespace closing brace to make clang-tidy happy.
ad9f03afc Prefer prefix increment operator.
a141b9c0c Update change log.
363fc7a15 Add more XML tests.
303a3090f Refactor XML tests.
a1ee5dd56 Make util namespace inline.
6f1709a83 Cleanup progress bar code.
1b02b65e0 Use Location setters taking a string in osmium_tiles example.
7ffdc7618 Disable clang-tidy warning.
882631085 Better implementation of str_to_int.
4cbf53725 Fix another bitwise op on signed integer.
903bfac9d Disable clang-tidy warning.
01de3f518 Don't change location if set_lon() or set_lat() functions throw.
9a27e899d Fix bitwise operation on signed integer.
61650224f Disable some clang-tidy warnings.
9dfa8437e Provide a way to better mock the getenv function in tests.
ae2c172a2 Explicitly set integer type for integers in test code.
878850068 Simpler implementation. We don't need to look at errno at all.
8f9b886f5 Formatting
cf4760cb0 Use bit operations on unsigned where possible.
c7cb4cde8 No conversion needed later if we declare it this way.
01357a540 Add missing inline for free function.
3feef81ee Disable clang-tidy warning in place we can't do anything about.
bf083b8ee Avoid binary bitwise operations on signed integers.
f70b1c803 Move content of osmium::util::detail namespace into osmium::detail.
caf2f0033 Remove use of atoi and atol from code.
f564cef07 Formatting.
f0885fc73 Disable travis build with sanitizers.
858c58444 Use explicit asserts and then casts, not static_cast_with_assert.
a613b1b0a Disable clang-tidy warning.
50e327677 Always build and run data tests on travis.
20d7a09b0 Update submodule to add more XML tests.
6c8f652bf Merge pull request #250 from Nakaner/object-comparison-without-timestamp
38ea437c0 Make XML parser more strict.
7788f5108 Remove object_order_type_id_reverse_version_without_timestamp
fe2223d25 Ignore timestamps if only one object has a valid timestamp
a4515161a Code cleanup.
eb5ea1a0e Use explicit conversions.
105905c45 Only disable warning on non-MSVC compilers.
80fc1b35d Change the way IDs are parsed from strings.
78aedf91e More tests for StringMatcher and disable a clang-tidy warning.
644a00752 Move catch.hpp into its own directory.
19842756c Update to newest osm-testdata submodule.
0402f64d7 Fix the problem with "git submodule" in appveyor.
ec4095d32 Cleanup metadata_options code.
d7390741e Add static_cast to avoid conversion warning.
dd16be1c3 Remove else after throw.
ef4d618de Remove unused variable.
0fdb58d13 Check out submodule in appveyor builds.
6406282d3 Merge pull request #248 from Nakaner/metadata-options-more
eb138a902 make clang < 3.9 work
e703b0d1d make sections their own independent test cases
f68888006 detect_available_metadata must be inline
b53224588 move metadata_options into osmium namespace
edd363cfa make const what could be const
302a485e5 remove unnecessary include, add missing include
93a76e07e give osmium::io::metadata_from_object a better name
91dfbc427 update documentation
453cd6395 replace REQUIRE(!foo) by REQUIRE_FALSE(foo)
247c3b021 replace friend function by setter methods
0a62e589c performance improvement: check first character instead using std::strlen()
73568bbff move ctor of metadata_options which taks an OSMObject out of class
1879c9e47 restore metadata_options::to_string
71a303608 add more unit tests for osmium::io::metadata_options
843cdc89c replace osmium::io::metdata_options::to_string fully by operator<<
6402a8793 Fix bug in code which determines if an OSM object has a valid user.
a6d8143ae Move metadata_options out of "detail" subnamespace
61e32df10 add metadata_options::operator|=
d5f7cc0ab Use newest osm-testdata submodule.
31e34f10c add operator&=, operator<< and a to_string method to metadata_options
77d507172 Formatting fixes.
1c38b2a61 Update some URLs. Use https where possible.
10066cb3e Merge pull request #247 from Nakaner/issue-245
3c938ce82 Allow version=-1 and changeset=-1 for PBF input.
9a542c133 Add ReaderWithProgressBar class.
49839a1ce Replace strftime by our own implementation.
b32b90942 Update osm-testdata version used.
f88b6e548 Add more tests.
cb7e778f6 Handle NULL geometries in test cases.
1961a9c95 Clean up some test cases.
d7f45e071 Update osm-testdata submodule.
73a2ef18f Remove check for lost ways in multipolygon assembler.
1244e498a Update submodule also in msys2 build.
229fc2453 Revert "Make util namespace inline."
9f942d2e9 Revert "Add inline declaration to one util namespace we forgot."
40d4835ea Really fix appveyor build (I hope).
5ae071135 Add inline declaration to one util namespace we forgot.
e0916257c Clean up debug message.
2ddc474cc Make util namespace inline.
4b4e25f87 Travis config: Do not install clang-tidy, we are not using it.
5a608fba1 Fix travis build.
a075cc323 Fix appveyor build.
41ee9920b Add submodule with osm-testdata repository.
4d42245c0 Revert "Add clang-tidy build to travis."
9df355b64 Fix issue on some compilers.
c8a3c00d6 Add clang-tidy build to travis.
2fc80ad17 Fixed clang-tidy config file order.
2adf05267 Fix various clang-tidy warnings
1dca92459 Use the right syntax to override clang-tidy settings in the code.
25baecb46 Fix some issues found by clang-tidy.
54a8de6c0 Disable more clang-tidy tests.
de46d562e Also look for clang-tidy-6.0 in CMake config.
2172553d8 Add build with sanitizers on travis.
7e4e45562 Add object comparators ignoring the timestamp.
92fb231a1 Fix test code.
e541df0fc Cleanup test code.
5640269da Add comment in appveyor script about unusual parameter.
acb872376 Workaround for failing appveyor MSYS2 build.
0634bcf70 Set default value for m_file_size member.
3a2fe5781 Set default values on output options.
43d289fda Make metadata_options constructor explicit.
6e54992b4 Update change log.
e54b955cf Update included `catch.hpp` to version 1.12.0.
e50b40d53 Update copyright date.
0d8b401b6 Merge branch 'metadata'
c7da3a3b6 Remove superfluous has_visibles boolean.
7f74d33d3 Some cleanups of metadata code and fixes test.
5b3c34990 Output XML attributes uid and user independently of each other.
384167334 Merge pull request #243 from Nakaner/metadata_other
733f1916c Change path of nuget installs in appveyor config.
e48672999 Debug output from FindOsmium.cmake script is better formatted now.
79663be5d Change appveyor scripts to work without deprecated prebuilt libs.
443f7a9e4 Remove dependency on (win)getopt completely.
c133b8b14 Fix osmium_convert: Long options with = syntax.
b55daf00a Remove dependency on (win)getopt from area_test and convert examples.
92f7275a9 output visibility directly after the object ID in debug format
a771279f0 deprecate format option pbf_add_metadata
18e3f6005 The value "no" should be treated as "none" by metadata_options
c8b0b2e28 re-assign metadata_options instead of calling a public method of it
15bc4a200 Add more flexible metadata handling to PBF output
b085632b7 add more flexible metadata handling to OPL and debug output
a12c65974 Remove now wrong check.
767ad883a Allow PBF DenseNodes with only some attributes to be read.
fd5a7eb6c More flexible metadata encoding in OSM files.
d16c18581 Add instructions for bug reporting.
db52591ab Use __COUNTER__ instead of name for internal dummy name.
89e634dfc Cleanup.
931ec30ca Marks some false positives for clang-tidy google-runtime-int warning.
b59ef02a2 More rule of zero/rule of five fixes.
1b72b3386 Pass by value and use std::move.
b7d7017cc Handle some clang-tidy google-runtime-int warnings.
c043ca016 Fix special functions.
41d9f0795 Use fixed sized ints where possible.
0899a66a7 Revert some changes older compilers don't like.
41e05989a Fix several rule of zero/rule of five issues.
4e78a828f Various fixes based on clang-tidy reports.
636bda372 Default initialize arrays.
466e5aa6a Handle various clang-tidy warnings.
9f47aa07d Disable clang-tidy misc-forwarding-reference-overload warning.
5e97bf29f Mark Reader and Writer non-movable.
3a2221b27 Add minimal tests for thread-safe queue class.
affdeed6f Add some tests.
5ed055d50 Handle some warnings regarding "explicit".
b9d4c9bf5 Disable clang-tidy cert-err58-cpp warning.
254c25349 Make ADL work for begin()/end() of InputIterator<Reader>.
b64cb32ae Disable clang-tidy android-cloexec-* warnings.
6d6934ffc Fix various warnings reported by clang-tidy.
30dcabaed Another travis build fix.
88c59e669 Fix travis build.
2facb461f Fix travis and appveyor builds.
bba631a51 Remove protozero from repository.
aebe4a914 Use pass by value and std::move in some constructors.
c8c24c8fd Name unused parameters in comments.
9c2e321f9 Make deleted special functions public.
265c16284 Fix some problems with older compilers.
174e95211 Modernize class initialization code for some classes.
4e3e584f8 Disable more clang-tidy warnings.
6b53981bb Fix some class initializations.
fe1405ef8 Add/remove special functions for some classes.
c6dd930d9 Disable cppcoreguidelines-pro-type-static-cast-downcast warning.
0d09210ec Disable misc-unused-parameters warning in clang-tidy.
1dbc43112 Refactor to avoid misc-suspicious-string-compare clang-tidy warning.
91262cc86 Merge pull request #232 from worace/wkt-geojson-polygons
438076b09 Cleanup: Avoid else after return/break.
e0368e92c Disable modernize-raw-string-literal and hicpp-no-assembler check.
c822888fc Mark C style cast in macro from a library as NOLINT.
662d4a641 Moving a TypedMemoryMapping is noexcept.
aec1c4526 Use auto (clang-tidy check modernize-use-auto).
64857589d Consistent include order.
d1ce8de00 Disable hicpp-invalid-access-moved clang-tidy check.
0d3902420 Refactor test without SECTION.
32e9e9e1e Rewrite test avoiding nested sections.
eeb532902 Reorder includes according to best practice.
249e7b553 Revert "Add build with sanitizers to travis."
362cb419a Set CC env var in travis config.
9f520eca3 Add build with sanitizers to travis.
cfc18fef0 Travis config cleanup.
212c6cd42 Remove tests that triggers undefined behaviour in the std lib.
f30985884 Bugfix: Avoid undefined behaviour.
90191619a Make test work even if unused memory isn't returned to OS.
876867e68 Make older compilers happy.
925d1a797 Add names for unused parameters.
014b3a056 Avoid repeating the return type from the declaration
c4e705f92 Disable hicpp-invalid-access-moved clang-tidy warnings.
8c03b3827 Disable some warnings.
c49962ffe Refactor test to avoid spurious use-after-move warning.
04a0afbba Sort includes.
2aaab9a89 Use auto where possible.
e2d84109b More changes for old compilers.
5364ca2a8 Changes for old compilers.
098fc1fa2 Move initializations of class members to the declaration.
eea463026 Fix buffer overflow in o5m parser.
5dc74f2d5 Remove check from static cast (and document why).
7a2dfdcdc Add NOLINT for using namespace osmium::builder::attr.
01fa05f1e Clang-tidy config cleanup.
5e8f8df3f Order includes.
6b78d9b24 Various small fixes for problems detected by clang-tidy.
b815f71b7 Fix gdal check in CMake config.
d47487093 Fix integer type error.
dec9de9ec Bugfix: Throw if elemens in XML file are nested too deep.
85e37723b Various small cleanups.
5f40d726a Additional checks in o5m parser.
b59b4b6a6 Check before static cast and throw.
e57b15700 Disable compiling some header files if gdal lib is not available.
1d3056646 Better checking that PBF data is in range.
c586521d3 Add some consts to the code.
df17e8189 Trying to get the types right...
8e9b759e0 Check read and write system call for EINTR.
28c676054 Rename license file so that Github finds it.
be29e9a52 Remove duplicate space character.
36c14136f Update protozero to newest version (1.6.0).
a19181998 Make libosmium work with different protozero versions.
5c5d9fb36 Use tag and type from protozero to make PBF parser more robust.
03f894400 Add repology.org badge to README.md.
1840739dd Merge pull request #234 from AMDmi3/patch-1
d8e737196 Add support for DragonFly BSD
8de181c8d Revert "Return const object from postfix ++ operator."
0dfb1d649 Add polygon implementation for WKT and GeoJSON Geometry Factories
150e05aea Fix indentation.
6fdee974a Merge pull request #229 from alex85k/no-winsock
f302f08ce Merge pull request #228 from alex85k/fix-test-win
bfb60c888 remove ws2_32 from needed libraries
ef187851c no winsock2 on windows: replace htonl with protozero::detail::byteswap_inplace
9343f8453 Fix testdata-multipolygon test on Windows (executable path differs)
381cf9272 Do not return const from postfix increment operator.
46ec985e9 Add const version of OutputIterator::operator*.
c67de374f Disable clang-tidy test for const params.
f5eda165f Make functions noexcept and return const value from post increment op.
1e4e3160f Use {} when calling constructors. Use .empty() to check empty strings.
8893d16be Mark some tests using size() with NOLINT.
f8a74a8aa Make functions noexcept.
45c1e072c Use REQUIRE_FALSE(...) instead of REQUIRE(!...) for readability.
fc173dae7 Merge pull request #227 from alex85k/msys2-appveor
0a281c064 Add MSYS2 building to Appveyor
c93f73120 fix FindGem for Windows Ruby distributions
8bf6702b3 Merge pull request #226 from alex85k/master
e8dad731d gmtime_s should be used on both MSVC and GCC from MinGW64
d0d98e9c1 remove "osmium::util::MemoryMapping::" from class body
6830ee9bd ftruncate is not available only on MSVC (MinGW has it)
c0597584f Disable some clang-tidy checks.
578db8e4a Use empty() instead of size() or == "" to check for empty collections.
53c8f3a21 Return const object from postfix ++ operator.
bd5e4d109 Use emplace_back() instead of push_back().
0a0a4f24c Use correct C++ header.
35226ea86 Remove unused move.
df843a9cf Fix header guard.
759e76131 Avoid default argument on virtual function.
db4f1bdb9 Update included catch.hpp to version 1.10.0.
59e70e5c6 Pass constructor arguments by value and std::move() into members.
ee9b598ed Add tests for thread_handler.
ac661209a CMake config: Update list of clang-tidy versions we look for.
d7281215c Add comment to unusual code.
cbb4c09fb Split up some overlong test functions.
9870a6b90 Fix noexcept specification.
5e27c37d0 Use array instead of map to store input/output format creators.
987d12922 Mark some constructors noexcept.
17f4d8b7e Avoid static variable only needed as constant value.
fe705cef0 Avoid else after return in several cases.
d4a85878e Beautifying travis config.
f07d1e375 Make some special functions noexcept.
4bb0f7f22 Do not declare special functions on some classes.
bc6c5943d Disable some clang-tidy checks that produce false positives.
6b6598a5b Remove superfluous std::move() of POD type.
71c3f5e16 Make some special functions noexcept.
1cb32778c Remove explicit true/false in tests.
929ba89cf Always catch by const ref.
a9a255820 Code readability: No else clause after return.
f14364bd3 Code formatting fixes.
f41feb6a5 Simplify code.
727f6eff4 Mark dummy includes for IWYU.
72d20f835 Switch travis build to 'trusty'.
c480e6808 Do not run gcov from codecov script.
d16c6e90a Clean up lambda captures in xml_input_format.hpp.

git-subtree-dir: third_party/libosmium
git-subtree-split: d2c1d872bc915d9579350007383ce1ebfea3665f
2018-04-19 22:03:25 +03:00
Michael Krasnyk c7d22c2b92 Update dependencies script 2018-04-19 22:03:20 +03:00
Michael Krasnyk b2aeb47630 Remove dummy edges before inplace permutation 2018-04-19 12:18:48 +02:00
Patrick Niklaus 0a1d1901cc Fix help text and banner 2018-04-17 18:02:28 +02:00
Patrick Niklaus 29db0c80d9 Use CSV stringify to properly escape data in CSV 2018-04-17 18:02:28 +02:00
Huyen Chau Nguyen 4654751872 add dev dependencies for osrm runner 2018-04-17 18:02:28 +02:00
Marcel Radischat b5b18d8afc Update profiles.md
Add api-version 4 for lua profiles as latest api-version
2018-04-17 17:23:08 +02:00
Huyen Chau Nguyen 15139c934f add changelog entry 2018-04-16 11:39:44 +02:00
Huyen Chau Nguyen 7b8619e37c adjust tests to changes 2018-04-16 11:39:44 +02:00
Huyen Chau Nguyen f52b5c31b6 refactor bike profile 2018-04-16 11:39:44 +02:00
Huyen Chau Nguyen e98859e4c0 make primaries and secondaries more dangerous
only apply oneway safety considerations on primaries

re-adjust primary and secondary safeties
2018-04-16 11:39:44 +02:00
Patrick Niklaus c5cc4c5a74 Remove double log printing 2018-04-13 10:13:57 +00:00
karenzshea e3b831364f empty list of shmem regions if none found 2018-04-13 12:07:10 +02:00
karenzshea 730d2b5ef2 log err instead of throwing when no shmem regions found 2018-04-13 12:07:10 +02:00
Michael Krasnyk 16abee1022 Avoid using signed integers for edge IDs 2018-04-12 10:03:37 +02:00
Patrick Niklaus 69fa52a010 Use byte based tar size encoding above 8GB 2018-04-10 21:12:39 +02:00
Patrick Niklaus e1efa4c6ab Add test case for writing and reading huge tar file
This test case is disabled by default because it needs too much storage,
but serves as documentation for the future.
2018-04-10 21:12:39 +02:00
Michael Krasnyk 17cd1575f6 Use base-256 encoding for files larger 68G
Reference:
http://lists.busybox.net/pipermail/busybox/2011-May/075596.html
2018-04-10 21:12:39 +02:00
Michael Krasnyk 3cd8e0fef8 Use 12 octal digits in mtar_raw_header_t::size 2018-04-10 21:12:39 +02:00
Michael Krasnyk 397bb694fd Fix mtar file size truncation to 4G 2018-04-10 21:12:39 +02:00
Patrick Niklaus 473ebfcbf6 Fix debug printing for coordinates 2018-04-10 18:08:18 +02:00
Patrick Niklaus a06171438e Fix hard-coded hint strings in unit-tests 2018-04-10 18:08:18 +02:00
Patrick Niklaus ea0881553e [skip ci] Bump master to 5.18 2018-04-09 13:14:43 +00:00
955 changed files with 76911 additions and 17684 deletions
+4
View File
@@ -68,6 +68,10 @@ Thumbs.db
/*.local.bat
/CMakeSettings.json
# Jetbrains related files #
###########################
.idea/
# stxxl related files #
#######################
.stxxl
+59 -64
View File
@@ -13,11 +13,12 @@ notifications:
branches:
only:
- master
- 5.21
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
cache:
yarn: true
npm: true
ccache: true
apt: true
directories:
@@ -34,7 +35,7 @@ env:
- CMAKE_VERSION=3.7.2
- MASON="$(pwd)/scripts/mason.sh"
- ENABLE_NODE_BINDINGS=On
- NODE="4"
- NODE="10"
matrix:
fast_finish: true
@@ -45,7 +46,7 @@ matrix:
# Debug Builds
- os: linux
compiler: "format-taginfo-docs"
env: NODE=6
env: NODE=10
sudo: false
before_install:
install:
@@ -53,8 +54,7 @@ matrix:
- nvm install $NODE
- nvm use $NODE
- npm --version
- npm install --ignore-scripts
- npm link --ignore-scripts
- npm ci --ignore-scripts
script:
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
- ${MASON} install clang-format 3.8.1
@@ -156,17 +156,17 @@ matrix:
- os: osx
osx_image: xcode9.2
compiler: "mason-osx-release-node-8"
compiler: "mason-osx-release-node-10"
# 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 NODE="8"
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="10"
after_success:
- ./scripts/travis/publish.sh
- os: osx
osx_image: xcode9.2
compiler: "mason-osx-release-node-4"
compiler: "mason-osx-release-node-8"
# 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 NODE="4"
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="8"
after_success:
- ./scripts/travis/publish.sh
@@ -180,54 +180,6 @@ matrix:
env: CCOMPILER='gcc-7' CXXCOMPILER='g++-7' 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++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="4"
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} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-4-mason-linux-debug"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="4"
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} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-8-mason-linux-release"
@@ -276,6 +228,54 @@ matrix:
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-10-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
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} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-10-mason-linux-debug"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
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} \
-DENABLE_GLIBC_WORKAROUND=ON
- 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
@@ -294,15 +294,10 @@ before_install:
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
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
- npm ci --ignore-scripts
# 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}"
@@ -381,4 +376,4 @@ script:
fi
- |
- popd
- yarn test
- npm test
+71 -1
View File
@@ -1,4 +1,72 @@
# UNRELEASED
# 5.21.0
- Changes from 5.20.0
- Features:
- ADDED: all waypoints in responses now contain a distance property between the original coordinate and the snapped location. [#5255](https://github.com/Project-OSRM/osrm-backend/pull/5255)
- ADDED: if `fallback_speed` is used, a new structure `fallback_speed_cells` will describe which cells contain estimated values [#5259](https://github.com/Project-OSRM/osrm-backend/pull/5259)
- REMOVED: we no longer publish Node 4 or 6 binary modules (they are still buildable from source) [#5314](https://github.com/Project-OSRM/osrm-backend/pull/5314)
- Table:
- ADDED: new parameter `scale_factor` which will scale the cell `duration` values by this factor. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5298)
- FIXED: only trigger `scale_factor` code to scan matrix when necessary. [#5303](https://github.com/Project-OSRM/osrm-backend/pull/5303)
- FIXED: fix bug in reverse offset calculation that sometimes lead to negative (and other incorrect) values in distance table results [#5315](https://github.com/Project-OSRM/osrm-backend/pull/5315)
- Docker:
- FIXED: use consistent boost version between build and runtime [#5311](https://github.com/Project-OSRM/osrm-backend/pull/5311)
- FIXED: don't override default permissions on /opt [#5311](https://github.com/Project-OSRM/osrm-backend/pull/5311)
- Matching:
- CHANGED: matching will now consider edges marked with is_startpoint=false, allowing matching over ferries and other previously non-matchable edge types. [#5297](https://github.com/Project-OSRM/osrm-backend/pull/5297)
- Profile:
- ADDED: Parse `source:maxspeed` and `maxspeed:type` tags to apply maxspeeds and add belgian flanders rural speed limit. [#5217](https://github.com/Project-OSRM/osrm-backend/pull/5217)
- CHANGED: Refactor maxspeed parsing to use common library. [#5144](https://github.com/Project-OSRM/osrm-backend/pull/5144)
# 5.20.0
- Changes from 5.19.0:
- Table:
- CHANGED: switch to pre-calculated distances for table responses for large speedup and 10% memory increase. [#5251](https://github.com/Project-OSRM/osrm-backend/pull/5251)
- ADDED: new parameter `fallback_speed` which will fill `null` cells with estimated value [#5257](https://github.com/Project-OSRM/osrm-backend/pull/5257)
- CHANGED: Remove API check for matrix sources/destination length to be less than or equal to coordinates length. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5289)
- FIXED: Fix crashing bug when using fallback_speed parameter with more sources than destinations. [#5291](https://github.com/Project-OSRM/osrm-backend/pull/5291)
- Features:
- ADDED: direct mmapping of datafiles is now supported via the `--mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- ADDED: Now publishing Node 10.x LTS binary modules [#5246](https://github.com/Project-OSRM/osrm-backend/pull/5246)
- Windows:
- FIXED: Windows builds again. [#5249](https://github.com/Project-OSRM/osrm-backend/pull/5249)
- Docker:
- CHANGED: switch from Alpine Linux to Debian Buster base images [#5281](https://github.com/Project-OSRM/osrm-backend/pull/5281)
# 5.19.0
- Changes from 5.18.0:
- Optimizations:
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
- ADDED: Node bindings can return pre-rendered JSON buffer. [#5189](https://github.com/Project-OSRM/osrm-backend/pull/5189)
- Profiles:
- CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [#5076
](https://github.com/Project-OSRM/osrm-backend/pull/5076/)
- CHANGED: Foot profile now blacklists barriers instead of whitelisting them [#5077
](https://github.com/Project-OSRM/osrm-backend/pull/5077/)
- CHANGED: Support maxlength and maxweight in car profile [#5101](https://github.com/Project-OSRM/osrm-backend/pull/5101]
- Bugfixes:
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
- Misc:
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)
# 5.18.0
- Changes from 5.17.0:
- Features:
- ADDED: `table` plugin now optionally returns `distance` matrix as part of response [#4990](https://github.com/Project-OSRM/osrm-backend/pull/4990)
- ADDED: New optional parameter `annotations` for `table` that accepts `distance`, `duration`, or both `distance,duration` as values [#4990](https://github.com/Project-OSRM/osrm-backend/pull/4990)
- Infrastructure:
- ADDED: Updated libosmium and added protozero and vtzero libraries [#5037](https://github.com/Project-OSRM/osrm-backend/pull/5037)
- CHANGED: Use vtzero library in tile plugin [#4686](https://github.com/Project-OSRM/osrm-backend/pull/4686)
- Profile:
- ADDED: Bicycle profile now returns classes for ferry and tunnel routes. [#5054](https://github.com/Project-OSRM/osrm-backend/pull/5054)
- ADDED: Bicycle profile allows to exclude ferry routes (default to not enabled) [#5054](https://github.com/Project-OSRM/osrm-backend/pull/5054)
# 5.17.1
- Changes from 5.17.0:
- Bugfixes:
- FIXED: Do not combine a segregated edge with a roundabout [#5039](https://github.com/Project-OSRM/osrm-backend/issues/5039)
# 5.17.0
- Changes from 5.16.0:
- Bugfixes:
- FIXED: deduplication of route steps when waypoints are used [#4909](https://github.com/Project-OSRM/osrm-backend/issues/4909)
@@ -6,9 +74,11 @@
- FIXED: Remove the last short annotation segment in `trimShortSegments` [#4946](https://github.com/Project-OSRM/osrm-backend/pull/4946)
- FIXED: Properly calculate annotations for speeds, durations and distances when waypoints are used with mapmatching [#4949](https://github.com/Project-OSRM/osrm-backend/pull/4949)
- FIXED: Don't apply unimplemented SH and PH conditions in OpeningHours and add inversed date ranges [#4992](https://github.com/Project-OSRM/osrm-backend/issues/4992)
- FIXED: integer overflow in `DynamicGraph::Renumber` [#5021](https://github.com/Project-OSRM/osrm-backend/pull/5021)
- Profile:
- CHANGED: Handle oneways in get_forward_backward_by_key [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- FIXED: Do not route against oneway road if there is a cycleway in the wrong direction; also review bike profile [#4943](https://github.com/Project-OSRM/osrm-backend/issues/4943)
- CHANGED: Make cyclability weighting of the bike profile prefer safer routes more strongly [#5015](https://github.com/Project-OSRM/osrm-backend/issues/5015)
- Guidance:
- CHANGED: Don't use obviousness for links bifurcations [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- FIXED: Adjust Straight direction modifiers of side roads in driveway handler [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
+24 -13
View File
@@ -167,7 +167,7 @@ add_executable(osrm-customize src/tools/customize.cpp)
add_executable(osrm-contract src/tools/contract.cpp)
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL> )
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_contract src/osrm/contractor.cpp $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_extract src/osrm/extractor.cpp $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_guidance $<TARGET_OBJECTS:GUIDANCE> $<TARGET_OBJECTS:UTIL>)
@@ -416,11 +416,30 @@ if(UNIX AND NOT APPLE)
set(MAYBE_RT_LIBRARY -lrt)
endif()
# Disallow deprecated protozero APIs
add_definitions(-DPROTOZERO_STRICT_API)
find_package(Threads REQUIRED)
# Third-party libraries
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
set(MICROTAR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src")
include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR})
set(MBXGEOM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/geometry.hpp-0.9.2/include")
include_directories(SYSTEM ${MBXGEOM_INCLUDE_DIR})
set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2.5.4/include")
include_directories(SYSTEM ${CHEAPRULER_INCLUDE_DIR})
add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c")
set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON)
set(PROTOZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/protozero/include")
include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR})
set(VTZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vtzero/include")
include_directories(SYSTEM ${VTZERO_INCLUDE_DIR})
# if mason is enabled no find_package calls are made
# to ensure that we are only compiling and linking against
# fully portable mason packages
@@ -554,14 +573,6 @@ else()
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
endif()
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
set(MICROTAR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src")
include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR})
add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c")
set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON)
# prefix compilation with ccache by default if available and on clang or gcc
if(ENABLE_CCACHE AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
find_program(CCACHE_FOUND ccache)
@@ -862,4 +873,4 @@ if (ENABLE_NODE_BINDINGS)
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
endif()
endif()
+2 -2
View File
@@ -9,7 +9,7 @@ High performance routing engine written in C++14 designed to run on OpenStreetMa
The following services are available via HTTP API, C++ library interface and NodeJs wrapper:
- Nearest - Snaps coordinates to the street network and returns the nearest matches
- Route - Finds the fastest route between coordinates
- Table - Computes the duration of the fastest route between all pairs of supplied coordinates
- Table - Computes the duration or distances of the fastest route between all pairs of supplied coordinates
- Match - Snaps noisy GPS traces to the road network in the most plausible way
- Trip - Solves the Traveling Salesman Problem using a greedy heuristic
- Tile - Generates Mapbox Vector Tiles with internal routing metadata
@@ -50,7 +50,7 @@ If you want to use the CH pipeline instead replace `osrm-partition` and `osrm-cu
### Using Docker
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Debian and make sure they are as lightweight as possible.
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
+1 -1
View File
@@ -3,5 +3,5 @@ module.exports = {
verify: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only -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 --require features/support --require features/step_definitions -f progress'
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@ch --require features/support --require features/step_definitions -f progress'
};
+12 -13
View File
@@ -1,15 +1,13 @@
FROM alpine:3.6 as buildstage
FROM debian:buster-slim as builder
ARG DOCKER_TAG
RUN mkdir -p /src && mkdir -p /opt
COPY . /src
WORKDIR /src
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk upgrade && \
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.2-dev libtbb@testing libtbb-dev@testing && \
apt-get update && \
apt-get -y --no-install-recommends install cmake make git gcc g++ libbz2-dev libstxxl-dev libstxxl1v5 libxml2-dev \
libzip-dev libboost1.67-all-dev lua5.2 liblua5.2-dev libtbb-dev -o APT::Install-Suggests=0 -o APT::Install-Recommends=0 && \
NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "Building OSRM ${DOCKER_TAG}" && \
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
@@ -26,20 +24,21 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
make -j${NPROC} install && \
cd ../profiles && \
cp -r * /opt && \
\
strip /usr/local/bin/* && \
rm -rf /src /usr/local/lib/libosrm*
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
FROM alpine:3.6 as runstage
FROM debian:buster-slim as runstage
RUN mkdir -p /src && mkdir -p /opt
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat libtbb@testing
COPY --from=buildstage /usr/local /usr/local
COPY --from=buildstage /opt /opt
RUN apt-get update && \
apt-get install -y --no-install-recommends libboost-program-options1.67.0 libboost-regex1.67.0 \
libboost-date-time1.67.0 libboost-chrono1.67.0 libboost-filesystem1.67.0 \
libboost-iostreams1.67.0 libboost-thread1.67.0 expat liblua5.2-0 libtbb2 &&\
rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local /usr/local
COPY --from=builder /opt /opt
WORKDIR /opt
EXPOSE 5000
+126 -9
View File
@@ -119,7 +119,6 @@ In addition to the [general options](#general-options) the following options are
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
- `distance`: Distance in meters to the supplied input coordinate.
- `nodes`: Array of OpenStreetMap node ids.
#### Example Requests
@@ -222,13 +221,13 @@ curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397
### Table service
Computes the duration of the fastest route between all pairs of supplied coordinates.
Computes the duration of the fastest route between all pairs of supplied coordinates. Returns the durations or distances or both between the coordinate pairs. Note that the distances are not the shortest distance between two coordinates, but rather the distances of the fastest routes. Duration is in seconds and distances is in meters.
```endpoint
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&{destinations}=[{elem}...]&annotations={duration|distance|duration,distance}
```
**Coordinates**
**Options**
In addition to the [general options](#general-options) the following options are supported for this service:
@@ -236,6 +235,10 @@ In addition to the [general options](#general-options) the following options are
|------------|--------------------------------------------------|---------------------------------------------|
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|annotations |`duration` (default), `distance`, or `duration,distance`|Return the requested table or tables in response. |
|fallback_speed|`double > 0`| If no route found between a source/destination pair, calculate the as-the-crow-flies distance, then use this speed to estimate duration.|
|fallback_coordinate|`input` (default), or `snapped`| When using a `fallback_speed`, use the user-supplied coordinate (`input`), or the snapped location (`snapped`) for calculating distances.|
|scale_factor|`double > 0`| Use in conjunction with `annotations=durations`. Scales the table `duration` values by this number.|
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
to number of input locations;
@@ -253,14 +256,23 @@ sources=0;5;7&destinations=5;1;4;2;3;6
#### Example Request
```curl
# Returns a 3x3 matrix:
# Returns a 3x3 duration matrix:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219'
# Returns a 1x3 matrix
# Returns a 1x3 duration matrix
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0'
# Returns a asymmetric 3x2 matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
# Returns a asymmetric 3x2 duration matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHulFzeMe`EuvKpnCglA)?sources=0;1;3&destinations=2;4'
# Returns a 3x3 duration matrix:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=duration'
# Returns a 3x3 distance matrix for CH:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=distance'
# Returns a 3x3 duration matrix and a 3x3 distance matrix for CH:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=distance,duration'
```
**Response**
@@ -268,17 +280,120 @@ curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHu
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
the i-th waypoint to the j-th waypoint. Values are given in seconds. Can be `null` if no route between `i` and `j` can be found.
- `distances` array of arrays that stores the matrix in row-major order. `distances[i][j]` gives the travel distance from
the i-th waypoint to the j-th waypoint. Values are given in meters. Can be `null` if no route between `i` and `j` can be found. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned.
- `sources` array of `Waypoint` objects describing all sources in order
- `destinations` array of `Waypoint` objects describing all destinations in order
- `fallback_speed_cells` (optional) array of arrays containing `i,j` pairs indicating which cells contain estimated values based on `fallback_speed`. Will be absent if `fallback_speed` is not used.
In case of error the following `code`s are supported in addition to the general ones:
| Type | Description |
|-------------------|-----------------|
| Type | Description |
|------------------|-----------------|
| `NoTable` | No route found. |
| `NotImplemented` | This request is not supported |
All other properties might be undefined.
#### Example Response
```json
{
"sources": [
{
"location": [
13.3888,
52.517033
],
"hint": "PAMAgEVJAoAUAAAAIAAAAAcAAAAAAAAArss0Qa7LNEHiVIRA4lSEQAoAAAAQAAAABAAAAAAAAADMAAAAAEzMAKlYIQM8TMwArVghAwEA3wps52D3",
"name": "Friedrichstraße"
},
{
"location": [
13.397631,
52.529432
],
"hint": "WIQBgL6mAoAEAAAABgAAAAAAAAA7AAAAhU6PQHvHj0IAAAAAQbyYQgQAAAAGAAAAAAAAADsAAADMAAAAf27MABiJIQOCbswA_4ghAwAAXwVs52D3",
"name": "Torstraße"
},
{
"location": [
13.428554,
52.523239
],
"hint": "7UcAgP___38fAAAAUQAAACYAAABTAAAAhSQKQrXq5kKRbiZCWJo_Qx8AAABRAAAAJgAAAFMAAADMAAAASufMAOdwIQNL58wA03AhAwMAvxBs52D3",
"name": "Platz der Vereinten Nationen"
}
],
"durations": [
[
0,
192.6,
382.8
],
[
199,
0,
283.9
],
[
344.7,
222.3,
0
]
],
"destinations": [
{
"location": [
13.3888,
52.517033
],
"hint": "PAMAgEVJAoAUAAAAIAAAAAcAAAAAAAAArss0Qa7LNEHiVIRA4lSEQAoAAAAQAAAABAAAAAAAAADMAAAAAEzMAKlYIQM8TMwArVghAwEA3wps52D3",
"name": "Friedrichstraße"
},
{
"location": [
13.397631,
52.529432
],
"hint": "WIQBgL6mAoAEAAAABgAAAAAAAAA7AAAAhU6PQHvHj0IAAAAAQbyYQgQAAAAGAAAAAAAAADsAAADMAAAAf27MABiJIQOCbswA_4ghAwAAXwVs52D3",
"name": "Torstraße"
},
{
"location": [
13.428554,
52.523239
],
"hint": "7UcAgP___38fAAAAUQAAACYAAABTAAAAhSQKQrXq5kKRbiZCWJo_Qx8AAABRAAAAJgAAAFMAAADMAAAASufMAOdwIQNL58wA03AhAwMAvxBs52D3",
"name": "Platz der Vereinten Nationen"
}
],
"code": "Ok",
"distances": [
[
0,
1886.89,
3791.3
],
[
1824,
0,
2838.09
],
[
3275.36,
2361.73,
0
]
],
"fallback_speed_cells": [
[ 0, 1 ],
[ 1, 0 ]
]
}
```
### Match service
Map matching matches/snaps given GPS points to the road network in the most plausible way.
@@ -442,6 +557,7 @@ Vector tiles contain two layers:
| `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 |
| `is_startpoint` | `boolean` | whether this segment can be used as a start/endpoint for routes |
`turns` layer:
@@ -796,6 +912,7 @@ Object used to describe waypoint on a route.
- `name` Name of the street the coordinate snapped to
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
- `distance` The distance, in metres, from the input coordinate to the snapped coordinate
- `hint` Unique internal identifier of the segment (ephemeral, not constant over data updates)
This can be used on subsequent request to significantly speed up the query and to connect multiple services.
E.g. you can use the `hint` value obtained by the `nearest` query as `hint` values for `route` inputs.
+48 -21
View File
@@ -25,7 +25,9 @@ var osrm = new OSRM('network.osrm');
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.memory_file` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Path to a file on disk to store the memory using mmap.
- `options.memory_file` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** *DEPRECATED*
Old behaviour: Path to a file on disk to store the memory using mmap. Current behaviour: setting this value is the same as setting `mmap_memory: true`.
- `options.mmap_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Map on-disk files to virtual memory addresses (mmap), rather than loading into RAM.
- `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.
- `options.max_locations_trip` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in trip query (default: unlimited).
- `options.max_locations_viaroute` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in viaroute query (default: unlimited).
@@ -56,7 +58,7 @@ Returns the fastest route between two or more coordinates while visiting the way
- `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.
- `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`.
`null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -88,7 +90,7 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
- `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)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -110,8 +112,8 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
### table
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
tables.
Computes duration table for the given locations. Allows for both symmetric and asymmetric
tables. Optionally returns distance table.
**Parameters**
@@ -127,7 +129,10 @@ tables.
- `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)**
- `options.fallback_speed` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Replace `null` responses in result with as-the-crow-flies estimates based on `fallback_speed`. Value is in metres/second.
- `options.fallback_coordinate` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Either `input` (default) or `snapped`. If using a `fallback_speed`, use either the user-supplied coordinate (`input`), or the snapped coordinate (`snapped`) for calculating the as-the-crow-flies diestance between two points.
- `options.scale_factor` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Multiply the table duration values in the table by this number for more controlled input into a route optimization solver.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -152,6 +157,7 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
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.
**`fallback_speed_cells`**: (optional) if `fallback_speed` is used, will be an array of arrays of `row,column` values, indicating which cells contain estimated values.
### tile
@@ -167,7 +173,7 @@ and what weights they have applied.
- `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/).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -204,7 +210,7 @@ if they can not be matched successfully.
- `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)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -268,7 +274,7 @@ Right now, the following combinations are possible:
- `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)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -297,9 +303,30 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
## Responses
## Plugin behaviour
Responses
All plugins support a second additional object that is available to configure some NodeJS specific behaviours.
- `plugin_config` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `plugin_config.format` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The format of the result object to various API calls. Valid options are `object` (default), which returns a standard Javascript object, as described above, and `json_buffer`, which will return a NodeJS **[Buffer](https://nodejs.org/api/buffer.html)** object, containing a JSON string. The latter has the advantage that it can be immediately serialized to disk/sent over the network, and the generation of the string is performed outside the main NodeJS event loop. This option is ignored by the `tile` plugin.
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
};
osrm.route(options, { format: "json_buffer" }, function(err, response) {
if (err) throw err;
console.log(response.toString("utf-8"));
});
```
## Responses
### Route
@@ -307,8 +334,8 @@ Represents a route through (potentially multiple) waypoints.
**Parameters**
- `exteral` **documentation** in
[`osrm-backend`](../http.md#route)
- **documentation** in
[`osrm-backend`](../http.md#route-object)
### RouteLeg
@@ -316,8 +343,8 @@ Represents a route between two waypoints.
**Parameters**
- `exteral` **documentation** in
[`osrm-backend`](../http.md#routeleg)
- **documentation** in
[`osrm-backend`](../http.md#routeleg-object)
### RouteStep
@@ -326,15 +353,15 @@ 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)
- **documentation** in
[`osrm-backend`](../http.md#routestep-object)
### StepManeuver
**Parameters**
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
- **documentation** in
[`osrm-backend`](../http.md#stepmaneuver-object)
### Waypoint
@@ -342,5 +369,5 @@ 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)
- **documentation** in
[`osrm-backend`](../http.md#waypoint-object)
+5 -5
View File
@@ -68,7 +68,7 @@ If you want to prioritize certain streets, increase the rate on these.
## Elements
### api_version
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 2.
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 4.
### Library files
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
@@ -138,7 +138,7 @@ Given an OpenStreetMap way, the `process_way` function will either return nothin
Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
node | The input way to process (read-only).
way | The input way to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `way` is a member.
@@ -199,7 +199,7 @@ source.lon | Read | Float | Co-ordinates of segment start
source.lat | Read | Float | ""
target.lon | Read | Float | Co-ordinates of segment end
target.lat | Read | Float | ""
target.distance | Read | Float | Length of segment
distance | Read | Float | Length of segment
weight | Read/write | Float | Routing weight for this segment
duration | Read/write | Float | Duration for this segment
@@ -224,8 +224,8 @@ source_highway_turn_classification | Read | Integer |
source_access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15))
source_speed | Read | Integer | Speed on this source road in km/h
source_priority_class | Read | Enum | The type of road priority class of the source. Defined in `include/extractor/guidance/road_classification.hpp`
target_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
target_mode | Read | Enum | Travel mode before the turn. Defined in `include/extractor/travel_mode.hpp`
target_restricted | Read | Boolean | Is the target a restricted access road? (See definition in `process_way`)
target_mode | Read | Enum | Travel mode after the turn. Defined in `include/extractor/travel_mode.hpp`
target_is_motorway | Read | Boolean | Is the target road a motorway?
target_is_link | Read | Boolean | Is the target road a link?
target_number_of_lanes | Read | Integer | How many lanes does the target road have? (default when not tagged: 0)
+3 -3
View File
@@ -43,9 +43,9 @@ We may introduce forward-compatible changes: query parameters and response prope
1. Check out the appropriate release branch `x.y`
2. Make sure `CHANGELOG.md` is up to date.
3. Make sure the `package.json` is up to date.
4. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
3. Make sure the `package.json` on branch `x.y` has been committed.
4. Make sure all tests are passing (e.g. Travis CI gives you a :green_apple:)
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries. Commit should be one in which the `package.json` version matches the version you want to release.
6. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
7. Push tags and commits: `git push; git push --tags`
8. On https://github.com/Project-OSRM/osrm-backend/releases press `Draft a new release`,
+1 -1
View File
@@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x |
| wall | |
| fence | |
| some_tag | |
| some_tag | x |
| block | x |
Scenario: Bike - Access tag trumphs barriers
+92
View File
@@ -0,0 +1,92 @@
@routing @bicycle @mode
Feature: Bicycle - Mode flag
Background:
Given the profile "bicycle"
Scenario: Bicycle - We tag ferries with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | route |
| ab | primary | |
| bc | | ferry |
| cd | primary | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,bc,cd,cd | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
| d | a | cd,bc,ab,ab | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
| c | a | bc,ab,ab | depart,notification left,arrive | [(ferry)],[()],[()] |
| d | b | cd,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
| a | c | ab,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
| b | d | bc,cd,cd | depart,notification left,arrive | [(ferry)],[()],[()] |
Scenario: Bicycle - We tag tunnel with a class
Background:
Given a grid size of 200 meters
Given the node map
"""
a b
c d
"""
And the ways
| nodes | tunnel |
| ab | no |
| bc | yes |
| cd | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,bc,cd,cd | depart,new name right,new name left,arrive | [()],[(tunnel)],[()],[()] |
Scenario: Bicycle - We tag classes without intersections
Background:
Given a grid size of 200 meters
Given the node map
"""
a b c d
"""
And the ways
| nodes | name | tunnel |
| ab | road | |
| bc | road | yes |
| cd | road | |
When I route I should get
| from | to | route | turns | classes |
| a | d | road,road | depart,arrive | [(),(tunnel),()],[()] |
Scenario: Bicycle - From roundabout on ferry
Given the node map
"""
c
/ \
a---b d---f--h
\ /
e
|
g
"""
And the ways
| nodes | oneway | highway | junction | route |
| ab | yes | service | | |
| cb | yes | service | roundabout | |
| dc | yes | service | roundabout | |
| be | yes | service | roundabout | |
| ed | yes | service | roundabout | |
| eg | yes | service | | |
| df | | | | ferry |
| fh | yes | service | | |
When I route I should get
| from | to | route | turns | classes |
| a | h | ab,df,df,fh,fh | depart,roundabout-exit-2,exit roundabout slight right,notification straight,arrive | [()],[(),()],[(ferry)],[()],[()] |
+55
View File
@@ -0,0 +1,55 @@
@routing @bicycle @exclude
Feature: Bicycle - Exclude flags
Background:
Given the profile file "bicycle" initialized with
"""
profile.excludable = Sequence { Set { 'ferry' } }
"""
Given the node map
"""
a....b~~~~~c...f
: :
d.....e
"""
And the ways
| nodes | highway | route | duration | # |
| ab | service | | | always drivable |
| bc | | ferry | 00:00:01 | not drivable for exclude=ferry, but fast. |
| bd | service | | | always drivable |
| de | service | | | always drivable |
| ec | service | | | always drivable |
| cf | service | | | always drivable |
Scenario: Bicycle - exclude nothing
When I route I should get
| from | to | route |
| a | f | ab,bc,cf,cf |
When I match I should get
| trace | matchings | duration |
| abcf | abcf | 109 |
When I request a travel time matrix I should get
| | a | f |
| a | 0 | 109 |
| f | 109 | 0 |
Scenario: Bicycle - exclude ferry
Given the query options
| exclude | ferry |
When I route I should get
| from | to | route |
| a | f | ab,bd,de,ec,cf,cf |
When I match I should get
| trace | matchings | duration |
| abcf | abcf | 301.2 |
When I request a travel time matrix I should get
| | a | f |
| a | 0 | 301 +- 1 |
| f | 301.2 +- 1 | 0 |
+22 -22
View File
@@ -11,11 +11,11 @@ Feature: Bicycle - Adds penalties to unsafe roads
Then routability should be
| highway | cycleway | forw | backw | forw_rate | backw_rate |
| motorway | | | | | |
| primary | | 15 km/h | 15 km/h | 2.9 | 2.9 |
| secondary | | 15 km/h | 15 km/h | 3.1 | 3.1 |
| primary | | 15 km/h | 15 km/h | 2.1 | 2.1 |
| secondary | | 15 km/h | 15 km/h | 2.7 | 2.7 |
| tertiary | | 15 km/h | 15 km/h | 3.3 | 3.3 |
| primary_link | | 15 km/h | 15 km/h | 2.9 | 2.9 |
| secondary_link | | 15 km/h | 15 km/h | 3.1 | 3.1 |
| primary_link | | 15 km/h | 15 km/h | 2.1 | 2.1 |
| secondary_link | | 15 km/h | 15 km/h | 2.7 | 2.7 |
| tertiary_link | | 15 km/h | 15 km/h | 3.3 | 3.3 |
| residential | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | 15 km/h | 15 km/h | 4.2 | 4.2 |
@@ -51,49 +51,49 @@ Feature: Bicycle - Adds penalties to unsafe roads
Then routability should be
| highway | cycleway:right | cycleway:left | forw | backw | forw_rate | backw_rate |
| motorway | track | | 15 km/h | | 4.2 | |
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| tertiary | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | track | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 |
| motorway | | track | 15 km/h | | 4.2 | |
| primary | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
| primary | | track | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary | | track | 15 km/h | 15 km/h | 2.7 | 4.2 |
| tertiary | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
| primary_link | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary_link | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
| primary_link | | track | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary_link | | track | 15 km/h | 15 km/h | 2.7 | 4.2 |
| tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
| residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | track | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 |
| motorway | lane | | 15 km/h | | 4.2 | |
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| tertiary | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 |
| cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | lane | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 |
| motorway | | lane | 15 km/h | | 4.2 | |
| primary | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 3.1 | 4.2 |
| primary | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 2.7 | 4.2 |
| tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
| primary_link | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary_link | | lane | 15 km/h | 15 km/h | 3.1 | 4.2 |
| primary_link | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary_link | | lane | 15 km/h | 15 km/h | 2.7 | 4.2 |
| tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
| residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | lane | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 |
| motorway | shared_lane | | 15 km/h | | 4.2 | |
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| motorway | | shared_lane | 15 km/h | | 4.2 | |
| primary | | shared_lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| primary | | shared_lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
Scenario: Bike - Don't apply penalties for all kind of cycleways
+9
View File
@@ -109,3 +109,12 @@ Feature: Car - Handle ferry routes
When I route I should get
| from | to | route | modes | time |
| c | d | bcde,bcde | ferry,ferry | 600s |
Given the query options
| geometries | geojson |
| overview | full |
# Note that matching *should* work across unsnappable ferries
When I match I should get
| trace | geometry | duration |
| abcdef| 1,1,1.000899,1,1.000899,1,1.002697,1,1.002697,1,1.003596,1,1.003596,1,1.005394,1,1.005394,1,1.006293,1 | 610.9 |
+25
View File
@@ -137,3 +137,28 @@ OSRM will use 4/5 of the projected free-flow speed.
| primary | | | 30 | -1 | | 23 km/h | | 6.7 |
| primary | 20 | 30 | | -1 | | 15 km/h | | 4.4 |
| primary | 20 | | 30 | -1 | | 23 km/h | | 6.7 |
Scenario: Car - Respect source:maxspeed
Given the node map
"""
a b c d e f g
"""
And the ways
| nodes | highway | source:maxspeed | maxspeed |
| ab | trunk | | |
| bc | trunk | | 60 |
| cd | trunk | FR:urban | |
| de | trunk | CH:rural | |
| ef | trunk | CH:trunk | |
| fg | trunk | CH:motorway | |
When I route I should get
| from | to | route | speed |
| a | b | ab,ab | 85 km/h |
| b | c | bc,bc | 48 km/h |
| c | d | cd,cd | 40 km/h |
| d | e | de,de | 64 km/h |
| e | f | ef,ef | 80 km/h |
| f | g | fg,fg | 96 km/h |
+19
View File
@@ -48,3 +48,22 @@ Feature: Car - Handle physical limitation
| primary | | none | x |
| primary | | no-sign | x |
| primary | | unsigned | x |
Scenario: Car - Limited by length
Then routability should be
| highway | maxlength | bothw |
| primary | | x |
| primary | 1 | |
| primary | 5 | x |
| primary | unsigned | x |
Scenario: Car - Limited by weight
Then routability should be
| highway | maxweight | bothw |
| primary | | x |
| primary | 1 | |
| primary | 3.5 | x |
| primary | 35000 kg | x |
| primary | 8.9t | x |
| primary | 0.1 lbs | |
| primary | unsigned | x |
+25
View File
@@ -35,3 +35,28 @@ Feature: Car - Allowed start/end modes
| from | to | route | modes |
| 1 | 2 | ab,ab | driving,driving |
| 2 | 1 | ab,ab | driving,driving |
Scenario: Car - URL override of non-startpoints
Given the node map
"""
a 1 b c 2 d
"""
Given the query options
| snapping | any |
And the ways
| nodes | highway | access |
| ab | service | private |
| bc | primary | |
| cd | service | private |
When I request a travel time matrix I should get
| | 2 | c |
| 1 | 59.1 | 35.1 |
| b | 35.1 | 11.1 |
When I route I should get
| from | to | route |
| 1 | 2 | ab,bc,cd |
| 2 | 1 | cd,bc,ab |
+1 -1
View File
@@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x |
| wall | |
| fence | |
| some_tag | |
| some_tag | x |
| block | x |
Scenario: Foot - Access tag trumphs barriers
@@ -1209,3 +1209,33 @@ Feature: Simple Turns
| a | c | knob,knob | depart,arrive |
| d | e | soph,soph | depart,arrive |
| d | a | soph,knob,knob | depart,turn left,arrive |
# https://www.openstreetmap.org/node/30797565
Scenario: No turn instruction when turning from unnamed onto unnamed
Given the node map
"""
a
|
|
|
|
b----------------c
|
|
|
|
|
|
d
"""
And the ways
| nodes | highway | name | ref |
| ab | trunk_link | | |
| db | secondary | | L 460 |
| bc | secondary | | |
When I route I should get
| from | to | route | turns |
| d | c | ,, | depart,turn right,arrive |
+53 -3
View File
@@ -84,7 +84,47 @@ class OSRMDirectLoader extends OSRMBaseLoader {
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
}
});
callback();
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
}
};
class OSRMmmapLoader extends OSRMBaseLoader {
constructor (scope) {
super(scope);
}
load (inputFile, callback) {
this.inputFile = inputFile;
this.shutdown(() => {
this.launch(callback);
});
}
osrmUp (callback) {
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
const command_arguments = util.format('%s -p %d -i %s -a %s --mmap', this.inputFile, this.scope.OSRM_PORT, this.scope.OSRM_IP, this.scope.ROUTING_ALGORITHM);
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
if (err && err.signal !== 'SIGINT') {
this.child = null;
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
}
});
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
}
};
@@ -135,22 +175,32 @@ class OSRMLoader {
this.scope = scope;
this.sharedLoader = new OSRMDatastoreLoader(this.scope);
this.directLoader = new OSRMDirectLoader(this.scope);
this.mmapLoader = new OSRMmmapLoader(this.scope);
this.method = scope.DEFAULT_LOAD_METHOD;
}
load (inputFile, callback) {
if (!this.loader) {
this.loader = {shutdown: (cb) => cb() };
}
if (this.method === 'datastore') {
this.directLoader.shutdown((err) => {
this.loader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.sharedLoader;
this.sharedLoader.load(inputFile, callback);
});
} else if (this.method === 'directly') {
this.sharedLoader.shutdown((err) => {
this.loader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.directLoader;
this.directLoader.load(inputFile, callback);
});
} else if (this.method === 'mmap') {
this.loader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.mmapLoader;
this.mmapLoader.load(inputFile, callback);
});
} else {
callback(new Error('*** Unknown load method ' + method));
}
+1 -1
View File
@@ -295,7 +295,7 @@ module.exports = function () {
this.reprocess(callback);
});
this.Given(/^osrm\-routed is stopped$/, (callback) => {
this.Given(/^osrm-routed is stopped$/, (callback) => {
this.OSRMLoader.shutdown(callback);
});
+85 -53
View File
@@ -1,74 +1,106 @@
var util = require('util');
module.exports = function () {
this.When(/^I request a travel time matrix I should get$/, (table, callback) => {
var NO_ROUTE = 2147483647; // MAX_INT
const durationsRegex = new RegExp(/^I request a travel time matrix I should get$/);
const distancesRegex = new RegExp(/^I request a travel distance matrix I should get$/);
const estimatesRegex = new RegExp(/^I request a travel time matrix I should get estimates for$/);
var tableRows = table.raw();
const DURATIONS_NO_ROUTE = 2147483647; // MAX_INT
const DISTANCES_NO_ROUTE = 3.40282e+38; // MAX_FLOAT
if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', callback);}.bind(this));
this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', callback);}.bind(this));
this.When(estimatesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'fallback_speed_cells', callback);}.bind(this));
};
var waypoints = [],
columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
const durationsParse = function(v) { return isNaN(parseInt(v)); };
const distancesParse = function(v) { return isNaN(parseFloat(v)); };
const estimatesParse = function(v) { return isNaN(parseFloat(v)); };
if (symmetric) {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'loc' });
});
} else {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'dst' });
});
rowHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'src' });
});
}
function tableParse(table, noRoute, annotation, callback) {
var actual = [];
actual.push(table.headers);
const parse = annotation == 'distances' ? distancesParse : (annotation == 'durations' ? durationsParse : estimatesParse);
const params = this.queryParams;
params.annotations = ['durations','fallback_speed_cells'].indexOf(annotation) !== -1 ? 'duration' : 'distance';
this.reprocessAndLoadData((e) => {
if (e) return callback(e);
// compute matrix
var params = this.queryParams;
var tableRows = table.raw();
this.requestTable(waypoints, params, (err, response) => {
if (err) return callback(err);
if (!response.body.length) return callback(new Error('Invalid response body'));
if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
var json = JSON.parse(response.body);
var waypoints = [],
columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
var result = json['durations'].map(row => {
if (symmetric) {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'loc' });
});
} else {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'dst' });
});
rowHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'src' });
});
}
var actual = [];
actual.push(table.headers);
this.reprocessAndLoadData((e) => {
if (e) return callback(e);
// compute matrix
this.requestTable(waypoints, params, (err, response) => {
if (err) return callback(err);
if (!response.body.length) return callback(new Error('Invalid response body'));
var json = JSON.parse(response.body);
var result = {};
if (annotation === 'fallback_speed_cells') {
result = table.raw().map(row => row.map(() => ''));
json[annotation].forEach(pair => {
result[pair[0]+1][pair[1]+1] = 'Y';
});
result = result.slice(1).map(row => {
var hashes = {};
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = isNaN(parseInt(v)) ? '' : v; });
row.slice(1).forEach((v,i) => {
hashes[tableRows[0][i+1]] = v;
});
return hashes;
});
} else {
result = json[annotation].map(row => {
var hashes = {};
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; });
return hashes;
});
}
var testRow = (row, ri, cb) => {
for (var k in result[ri]) {
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
result[ri][k] = row[k];
} else if (row[k] === '' && result[ri][k] === NO_ROUTE) {
result[ri][k] = '';
} else {
result[ri][k] = result[ri][k].toString();
}
var testRow = (row, ri, cb) => {
for (var k in result[ri]) {
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
result[ri][k] = row[k];
} else if (row[k] === '' && result[ri][k] === noRoute) {
result[ri][k] = '';
} else {
result[ri][k] = result[ri][k].toString();
}
}
result[ri][''] = row[''];
cb(null, result[ri]);
};
result[ri][''] = row[''];
cb(null, result[ri]);
};
this.processRowsAndDiff(table, testRow, callback);
});
this.processRowsAndDiff(table, testRow, callback);
});
});
};
}
+6 -6
View File
@@ -21,11 +21,11 @@ module.exports = function () {
});
};
this.When(/^I run "osrm\-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
this.When(/^I run "osrm-routed\s?(.*?)"$/, { timeout: this.TIMEOUT }, (options, callback) => {
this.runAndSafeOutput('osrm-routed', options, callback);
});
this.When(/^I run "osrm\-(extract|contract|partition|customize)\s?(.*?)"$/, (binary, options, callback) => {
this.When(/^I run "osrm-(extract|contract|partition|customize)\s?(.*?)"$/, (binary, options, callback) => {
const stamp = this.processedCacheFile + '.stamp_' + binary;
this.runAndSafeOutput('osrm-' + binary, options, (err) => {
if (err) return callback(err);
@@ -33,11 +33,11 @@ module.exports = function () {
});
});
this.When(/^I try to run "(osrm\-[a-z]+)\s?(.*?)"$/, (binary, options, callback) => {
this.When(/^I try to run "(osrm-[a-z]+)\s?(.*?)"$/, (binary, options, callback) => {
this.runAndSafeOutput(binary, options, () => { callback(); });
});
this.When(/^I run "osrm\-datastore\s?(.*?)"(?: with input "([^"]*)")?$/, (options, input, callback) => {
this.When(/^I run "osrm-datastore\s?(.*?)"(?: with input "([^"]*)")?$/, (options, input, callback) => {
let child = this.runAndSafeOutput('osrm-datastore', options, callback);
if (input !== undefined)
child.stdin.write(input);
@@ -55,13 +55,13 @@ module.exports = function () {
this.Then(/^stdout should( not)? contain "(.*?)"$/, (not, str) => {
const contains = this.stdout.indexOf(str) > -1;
assert.ok(typeof not === 'undefined' ? contains : !contains,
'stdout ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
'stdout ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
});
this.Then(/^stderr should( not)? contain "(.*?)"$/, (not, str) => {
const contains = this.stderr.indexOf(str) > -1;
assert.ok(typeof not === 'undefined' ? contains : !contains,
'stderr ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
'stderr ' + (typeof not === 'undefined' ? 'does not contain' : 'contains') + ' "' + str + '"');
});
this.Then(/^stdout should contain \/(.*)\/$/, (regexStr) => {
+1 -1
View File
@@ -69,7 +69,7 @@ module.exports = function () {
outputRow[direction] = result[direction].status ?
'x' : '';
break;
case /^[\d\.]+ s/.test(want):
case /^[\d.]+ s/.test(want):
// the result here can come back as a non-number value like
// `diff`, but we only want to apply the unit when it comes
// back as a number, for tableDiff's literal comparison
+7 -7
View File
@@ -29,7 +29,7 @@ module.exports = function() {
// setup cache for feature data
// if OSRM_PROFILE is set to force a specific profile, then
// include the profile name in the hash of the profile file
// include the profile name in the hash of the profile file
hash.hashOfFile(uri, this.OSRM_PROFILE, (err, hash) => {
if (err) return callback(err);
@@ -45,10 +45,10 @@ module.exports = function() {
this.featureProcessedCacheDirectories[uri] = featureProcessedCacheDirectory;
d3.queue(1)
.defer(mkdirp, featureProcessedCacheDirectory)
.defer(this.cleanupFeatureCache.bind(this), featureCacheDirectory, hash)
.defer(this.cleanupProcessedFeatureCache.bind(this), featureProcessedCacheDirectory, this.osrmHash)
.awaitAll(callback);
.defer(mkdirp, featureProcessedCacheDirectory)
.defer(this.cleanupFeatureCache.bind(this), featureCacheDirectory, hash)
.defer(this.cleanupProcessedFeatureCache.bind(this), featureProcessedCacheDirectory, this.osrmHash)
.awaitAll(callback);
});
}
@@ -87,7 +87,7 @@ module.exports = function() {
fs.readdir(parentPath, (err, files) => {
let q = d3.queue();
files.filter(name => { return name !== featureHash;})
.map((f) => { q.defer(rimraf, path.join(parentPath, f)); });
.map((f) => { q.defer(rimraf, path.join(parentPath, f)); });
q.awaitAll(callback);
});
};
@@ -145,7 +145,7 @@ module.exports = function() {
// converts the scenario titles in file prefixes
this.getScenarioID = (scenario) => {
let name = scenario.getName().toLowerCase().replace(/[\/\-'=,\(\):\*#]/g, '')
let name = scenario.getName().toLowerCase().replace(/[/\-'=,():*#]/g, '')
.replace(/\s/g, '_').replace(/__/g, '_').replace(/\.\./g, '.')
.substring(0, 64);
return util.format('%d_%s', scenario.getLine(), name);
+15 -9
View File
@@ -17,11 +17,12 @@ module.exports = {
return true;
var matchPercent = want.match(/(.*)\s+~(.+)%$/),
matchAbs = want.match(/(.*)\s+\+\-(.+)$/),
matchAbs = want.match(/(.*)\s+\+-(.+)$/),
matchRe = want.match(/^\/(.*)\/$/),
// we use this for matching before/after bearing
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/);
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+-(.+)$/),
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+-(.+)$/),
matchRangeNumbers = want.match(/\d+\+-\d+/);
function inRange(margin, got, want) {
var fromR = parseFloat(want) - margin,
@@ -30,12 +31,12 @@ module.exports = {
}
function parseIntersectionString(str) {
return str.split(';')
.map((turn_intersections) => turn_intersections
.split(',')
.map((intersection) => intersection
.split(' ')
.map((entry_bearing_pair) => entry_bearing_pair
.split(':'))));
.map((turn_intersections) => turn_intersections
.split(',')
.map((intersection) => intersection
.split(' ')
.map((entry_bearing_pair) => entry_bearing_pair
.split(':'))));
}
if (got === want) {
@@ -105,6 +106,11 @@ module.exports = {
return inRange(margin, got, matchAbs[1]);
} else if (matchRe) { // regex: /a,b,.*/
return got.match(matchRe[1]);
} else if (matchRangeNumbers) {
let real_want_and_margin = want.split('+-'),
margin = parseFloat(real_want_and_margin[1].trim()),
real_want = parseFloat(real_want_and_margin[0].trim());
return inRange(margin, got, real_want);
} else {
return false;
}
+2 -2
View File
@@ -32,7 +32,7 @@ module.exports = function () {
this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env);
this.DEFAULT_PROFILE = 'bicycle';
this.DEFAULT_INPUT_FORMAT = 'osm';
this.DEFAULT_LOAD_METHOD = 'datastore';
this.DEFAULT_LOAD_METHOD = process.argv[process.argv.indexOf('-m') +1].match('mmap') ? 'mmap' : 'datastore';
this.DEFAULT_ORIGIN = [1,1];
this.OSM_USER = 'osrm';
this.OSM_UID = 1;
@@ -80,7 +80,7 @@ module.exports = function () {
// eslint-disable-next-line no-console
console.info(util.format('Node Version', process.version));
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
if (parseInt(process.version.match(/v(\d+)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
fs.exists(this.TEST_PATH, (exists) => {
if (exists)
+1 -1
View File
@@ -51,7 +51,7 @@ module.exports = function () {
.defer(rimraf, this.scenarioLogFile)
.awaitAll(callback);
// uncomment to get path to logfile
// console.log(" Writing logging output to " + this.scenarioLogFile)
// console.log(' Writing logging output to ' + this.scenarioLogFile);
});
this.After((scenario, callback) => {
+2 -2
View File
@@ -115,7 +115,7 @@ module.exports = function () {
if (headers.has('weight')) {
if (row.weight.length) {
if (!row.weight.match(/[\d\.]+/))
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 {
@@ -151,7 +151,7 @@ module.exports = function () {
if (headers.has('locations')){
got.locations = (locations || '').trim();
}
/*
/*
if (headers.has('approaches')){
got.approaches = (approaches || '').trim();
}*/
+19
View File
@@ -226,3 +226,22 @@ Feature: Distance calculation
| x | v | xv,xv | 424m +-1 |
| x | w | xw,xw | 360m +-1 |
| x | y | xy,xy | 316m +-1 |
# Check rounding errors
Scenario: Distances Long distances
Given a grid size of 1000 meters
Given the node map
"""
a b c d
"""
And the ways
| nodes |
| abcd |
When I route I should get
| from | to | distance |
| a | b | 1000m +-3 |
| a | c | 2000m +-3 |
| a | d | 3000m +-3 |
+516 -202
View File
@@ -1,74 +1,11 @@
@matrix @testbot
Feature: Basic Distance Matrix
# note that results are travel time, specified in 1/10th of seconds
# since testbot uses a default speed of 100m/10s, the result matches
# the number of meters as long as the way type is the default 'primary'
# note that results of travel distance are in metres
Background:
Given the profile "testbot"
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
Scenario: Testbot - Travel time matrix of minimal network
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
Scenario: Testbot - Travel time matrix with different way speeds
Given the node map
"""
a b c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | secondary |
| cd | tertiary |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
| b | 10 | 0 | 20 | 50 |
| c | 30 | 20 | 0 | 30 |
| d | 60 | 50 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| c | 30 |
| d | 60 |
Scenario: Testbot - Travel time matrix with fuzzy match
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
Scenario: Testbot - Travel time matrix of small grid
Scenario: Testbot - Travel distance matrix of small grid
Given the node map
"""
a b c
@@ -83,14 +20,175 @@ Feature: Basic Distance Matrix
| be |
| cf |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
Scenario: Testbot - Travel time matrix of network with unroutable parts
Scenario: Testbot - Travel distance matrix of minimal network exact distances
Given the node map
"""
a z
b
c
d
"""
And the ways
| nodes |
| az |
| zbcd |
When I request a travel distance matrix I should get
| | a | z | b | c | d |
| a | 0 | 100.1 | 199.5 | 298.9 | 398.3 |
| z | 100.1 | 0 | 99.4 | 198.8 | 298.2 |
| b | 199.5 | 99.4 | 0 | 99.4 | 198.8 |
| c | 298.9 | 198.8 | 99.4 | 0 | 99.4 |
| d | 398.3 | 298.2 | 198.8 | 99.4 | 0 |
Scenario: Testbot - Travel distance matrix of minimal network with toll exclude
Given the query options
| exclude | toll |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 100.1 | | |
| b | 100.1 | 0 | | |
| c | | | 0 | 100.1 |
| d | | | 100.1 | 0 |
Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude
Given the query options
| exclude | motorway |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | # |
| ab | motorway | not drivable for exclude=motorway |
| cd | residential | |
| ac | residential | |
| bd | residential | |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 298.9 | 99.4 | 199.5 |
Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude
Given the query options
| exclude | motorway |
And the extract extra arguments "--small-component-size 4"
Given the node map
"""
ab efgh
cd
"""
And the ways
| nodes | highway | # |
| be | motorway | not drivable for exclude=motorway |
| abcd | residential | |
| efgh | residential | |
When I request a travel distance matrix I should get
| | a | b | e |
| a | 0 | 50.1 | |
Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes
Given the query options
| exclude | motorway,toll |
Given the node map
"""
a b e f
c d g h
"""
And the ways
| nodes | highway | toll | # |
| be | motorway | | not drivable for exclude=motorway |
| dg | primary | yes | not drivable for exclude=toll |
| abcd | residential | | |
| efgh | residential | | |
When I request a travel distance matrix I should get
| | a | b | e | g |
| a | 0 | 100.1 | | |
Scenario: Testbot - Travel distance matrix with different way speeds
Given the node map
"""
a b c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | secondary |
| cd | tertiary |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 100.1 | 200.1 | 300.2 |
| b | 100.1 | 0 | 100.1 | 200.1 |
| c | 200.1 | 100.1 | 0 | 100.1 |
| d | 300.2 | 200.1 | 100.1 | 0 |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 100.1 | 200.1 | 300.2 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 100.1 |
| c | 200.1 |
| d | 300.2 |
Scenario: Testbot - Travel distance matrix of small grid
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
Scenario: Testbot - Travel distance matrix of network with unroutable parts
Given the node map
"""
a b
@@ -100,12 +198,12 @@ Feature: Basic Distance Matrix
| nodes | oneway |
| ab | yes |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | | 0 |
When I request a travel distance matrix I should get
| | a | b |
| a | 0 | 100.1 |
| b | | 0 |
Scenario: Testbot - Travel time matrix of network with oneways
Scenario: Testbot - Travel distance matrix of network with oneways
Given the node map
"""
x a b y
@@ -118,14 +216,14 @@ Feature: Basic Distance Matrix
| xa | |
| by | |
When I request a travel time matrix I should get
| | x | y | d | e |
| x | 0 | 30 | 40 | 30 |
| y | 50 | 0 | 30 | 20 |
| d | 20 | 30 | 0 | 30 |
| e | 30 | 40 | 10 | 0 |
When I request a travel distance matrix I should get
| | x | y | d | e |
| x | 0 | 300.2 | 399.6 | 299.5 |
| y | 499 | 0 | 299.5 | 199.5 |
| d | 199.5 | 299.5 | 0 | 298.9 |
| e | 299.5 | 399.6 | 100.1 | 0 |
Scenario: Testbot - Rectangular travel time matrix
Scenario: Testbot - Rectangular travel distance matrix
Given the node map
"""
a b c
@@ -140,51 +238,57 @@ Feature: Basic Distance Matrix
| be |
| cf |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
When I route I should get
| from | to | distance |
| e | a | 200m |
| e | b | 100m |
| f | a | 299.9m |
| f | b | 200m |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 100.1 |
| e | 199.5 |
| f | 299.5 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
| e | 20 | 10 |
| f | 30 | 20 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
When I request a travel distance matrix I should get
| | a | b |
| a | 0 | 100.1 |
| b | 100.1 | 0 |
| e | 199.5 | 99.4 |
| f | 299.5 | 199.5 |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 10 | 20 |
| b | 10 | 0 | 10 |
| e | 20 | 10 | 0 |
| f | 30 | 20 | 10 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
When I request a travel distance matrix I should get
| | a | b | e |
| a | 0 | 100.1 | 199.5 |
| b | 100.1 | 0 | 99.4 |
| e | 199.5 | 99.4 | 0 |
| f | 299.5 | 199.5 | 100.1 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
Scenario: Testbot - Travel time 3x2 matrix
Scenario: Testbot - Travel distance 3x2 matrix
Given the node map
"""
a b c
@@ -199,10 +303,11 @@ Feature: Basic Distance Matrix
| be |
| cf |
When I request a travel time matrix I should get
| | b | e | f |
| a | 10 | 20 | 30 |
| b | 0 | 10 | 20 |
When I request a travel distance matrix I should get
| | b | e | f |
| a | 100.1 | 199.5 | 299.5 |
| b | 0 | 99.4 | 199.5 |
Scenario: Testbot - All coordinates are from same small component
Given a grid size of 300 meters
@@ -221,10 +326,10 @@ Feature: Basic Distance Matrix
| da |
| fg |
When I request a travel time matrix I should get
| | f | g |
| f | 0 | 30 |
| g | 30 | 0 |
When I request a travel distance matrix I should get
| | f | g |
| f | 0 | 298.2 |
| g | 298.2 | 0 |
Scenario: Testbot - Coordinates are from different small component and snap to big CC
Given a grid size of 300 meters
@@ -244,14 +349,25 @@ Feature: Basic Distance Matrix
| fg |
| hi |
When I request a travel time matrix I should get
| | f | g | h | i |
| f | 0 | 30 | 0 | 30 |
| g | 30 | 0 | 30 | 0 |
| h | 0 | 30 | 0 | 30 |
| i | 30 | 0 | 30 | 0 |
When I route I should get
| from | to | distance |
| f | g | 300m |
| f | i | 300m |
| g | f | 300m |
| g | h | 300m |
| h | g | 300m |
| h | i | 300m |
| i | f | 300m |
| i | h | 300m |
Scenario: Testbot - Travel time matrix with loops
When I request a travel distance matrix I should get
| | f | g | h | i |
| f | 0 | 298.2 | 0 | 298.2 |
| g | 298.2 | 0 | 298.2 | 0 |
| h | 0 | 298.2 | 0 | 298.2 |
| i | 298.2 | 0 | 298.2 | 0 |
Scenario: Testbot - Travel distance matrix with loops
Given the node map
"""
a 1 2 b
@@ -265,14 +381,15 @@ Feature: Basic Distance Matrix
| cd | yes |
| da | yes |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
| 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
| 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
When I request a travel distance matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 100.1 | 399.6 | 499.7 |
| 2 | 699.1 | 0 | 299.5 | 399.6 |
| 3 | 399.6 | 499.7 | 0 | 100.1 |
| 4 | 299.5 | 399.6 | 699.1 | 0 |
Scenario: Testbot - Travel time matrix based on segment durations
Scenario: Testbot - Travel distance matrix based on segment durations
Given the profile file
"""
local functions = require('testbot')
@@ -301,20 +418,19 @@ Feature: Basic Distance Matrix
"""
And the ways
| nodes |
| abcd |
| ce |
| nodes |
| abcd |
| ce |
When I request a travel time matrix I should get
| | a | b | c | d | e |
| a | 0 | 11 | 22 | 33 | 33 |
| b | 11 | 0 | 11 | 22 | 22 |
| c | 22 | 11 | 0 | 11 | 11 |
| d | 33 | 22 | 11 | 0 | 22 |
| e | 33 | 22 | 11 | 22 | 0 |
When I request a travel distance matrix I should get
| | a | b | c | d | e |
| a | 0 | 100.1 | 200.1 | 300.2 | 398.9 |
| b | 100.1 | 0 | 100.1 | 200.1 | 298.9 |
| c | 200.1 | 100.1 | 0 | 100.1 | 198.8 |
| d | 300.2 | 200.1 | 100.1 | 0 | 298.9 |
| e | 398.9 | 298.9 | 198.8 | 298.9 | 0 |
Scenario: Testbot - Travel time matrix for alternative loop paths
Scenario: Testbot - Travel distance matrix for alternative loop paths
Given the profile file
"""
local functions = require('testbot')
@@ -350,62 +466,260 @@ Feature: Basic Distance Matrix
| dc | yes |
| ca | yes |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
| 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
| 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
| 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
| 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
When I request a travel distance matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 1096.7 | 298.9 | 199.5 | 598.4 | 498.3 | 897.3 | 797.9 |
| 2 | 100.1 | 0 | 398.9 | 299.5 | 698.5 | 598.4 | 997.3 | 897.9 |
| 3 | 897.9 | 797.9 | 0 | 1097.4 | 299.5 | 199.5 | 598.4 | 499 |
| 4 | 997.3 | 897.3 | 99.4 | 0 | 398.9 | 298.9 | 697.8 | 598.4 |
| 5 | 598.4 | 498.3 | 897.3 | 797.9 | 0 | 1096.7 | 298.9 | 199.5 |
| 6 | 698.5 | 598.4 | 997.3 | 897.9 | 100.1 | 0 | 398.9 | 299.5 |
| 7 | 299.5 | 199.5 | 598.4 | 499 | 897.9 | 797.9 | 0 | 1097.4 |
| 8 | 398.9 | 298.9 | 697.8 | 598.4 | 997.3 | 897.3 | 99.4 | 0 |
When I request a travel distance matrix I should get
| | 1 |
| 1 | 0 |
| 2 | 100.1 |
| 3 | 897.9 |
| 4 | 997.3 |
| 5 | 598.4 |
| 6 | 698.5 |
| 7 | 299.5 |
| 8 | 398.9 |
Scenario: Testbot - Travel time matrix with ties
Given the profile file
"""
local functions = require('testbot')
functions.process_segment = function(profile, segment)
segment.weight = 1
segment.duration = 1
end
functions.process_turn = function(profile, turn)
if turn.angle >= 0 then
turn.duration = 16
else
turn.duration = 4
end
turn.weight = 0
end
return functions
"""
And the node map
Scenario: Testbot - Travel distance matrix with ties
Given the node map
"""
a b
a b
c d
"""
And the ways
| nodes |
| ab |
| ac |
| bd |
| dc |
| nodes |
| ab |
| ac |
| bd |
| dc |
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 20s | 20 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 1 | 5 | 10 |
When I route I should get
| from | to | route | distance |
| a | b | ab,ab | 450m |
| a | c | ac,ac | 200m |
| a | d | ac,dc,dc | 499.9m |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 1 |
| c | 15 |
| d | 10 |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 450.3 | 198.8 | 499 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 450.3 |
| c | 198.8 |
| d | 499 |
When I request a travel distance matrix I should get
| | a | c |
| a | 0 | 198.8 |
| c | 198.8 | 0 |
# Check rounding errors
Scenario: Testbot - Long distances in tables
Given a grid size of 1000 meters
Given the node map
"""
a b c d
"""
And the ways
| nodes |
| abcd |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 1000.7 | 2001.4 | 3002.1 |
Scenario: Testbot - OneToMany vs ManyToOne
Given the node map
"""
a b
c
"""
And the ways
| nodes | oneway |
| ab | yes |
| ac | |
| bc | |
When I request a travel distance matrix I should get
| | a | b |
| b | 240.4 | 0 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 240.4 |
Scenario: Testbot - Varying distances between nodes
Given the node map
"""
a b c d
e
f
"""
And the ways
| nodes | oneway |
| feabcd | yes |
| ec | |
| fd | |
When I request a travel distance matrix I should get
| | a | b | c | d | e | f |
| a | 0 | 100.1 | 300.2 | 650.5 | 1930.6 | 1533 |
| b | 759 | 0 | 200.1 | 550.4 | 1830.5 | 1432.9 |
| c | 558.8 | 658.9 | 0 | 350.3 | 1630.4 | 1232.8 |
| d | 1478.9 | 1579 | 1779.1 | 0 | 1280.1 | 882.5 |
| e | 198.8 | 298.9 | 499 | 710.3 | 0 | 1592.8 |
| f | 596.4 | 696.5 | 896.6 | 1107.9 | 397.6 | 0 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
| b | 300.2 | 0 | 600.5 | 1200.9 |
| f | 900.7 | 600.5 | 0 | 300.2 |
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1501.1 |
Scenario: Testbot - Fise input coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | input |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
| b | 300.2 | 0 | 600.5 | 1200.9 |
| f | 900.7 | 600.5 | 0 | 300.2 |
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1501.1 |
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1200.9 |
| b | 300.2 | 0 | 600.5 | 900.7 |
| f | 900.7 | 600.5 | 0 | 300.2 |
| 1 | 1200.9 | 900.7 | 300.2 | 0 |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1200.9 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1200.9 |
Scenario: Ensure consistency with route, and make sure offsets work in both directions
Given a grid size of 100 meters
Given the node map
"""
a b c d e f g h i j
1 2
"""
And the ways
| nodes |
| abcdef |
| fghij |
When I route I should get
| from | to | route | distance |
| 1 | 2 | abcdef,fghij,fghij | 999.9m |
# TODO: this is "correct", but inconsistent with viaroute
When I request a travel distance matrix I should get
| | 1 | 2 |
| 1 | 0 | 1000.7 |
| 2 | 1000.7 | 0 |
+777
View File
@@ -0,0 +1,777 @@
@matrix @testbot
Feature: Basic Duration Matrix
# note that results of travel time are in seconds
Background:
Given the profile "testbot"
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
Scenario: Testbot - Travel time matrix of minimal network
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
@ch
Scenario: Testbot - Travel time matrix of minimal network with toll exclude
Given the query options
| exclude | toll |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 15 | | |
| b | 15 | 0 | | |
| c | | | 0 | 10 |
| d | | | 10 | 0 |
@ch
Scenario: Testbot - Travel time matrix of minimal network with motorway exclude
Given the query options
| exclude | motorway |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | # |
| ab | motorway | not drivable for exclude=motorway |
| cd | residential | |
| ac | residential | |
| bd | residential | |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 45 | 15 | 30 |
@ch
Scenario: Testbot - Travel time matrix of minimal network disconnected motorway exclude
Given the query options
| exclude | motorway |
Given the node map
"""
ab efgh
cd
"""
And the ways
| nodes | highway | # |
| be | motorway | not drivable for exclude=motorway |
| abcd | residential | |
| efgh | residential | |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 7.5 | |
@ch
Scenario: Testbot - Travel time matrix of minimal network with motorway and toll excludes
Given the query options
| exclude | motorway,toll |
Given the node map
"""
a b e f
c d g h
"""
And the ways
| nodes | highway | toll | # |
| be | motorway | | not drivable for exclude=motorway |
| dg | primary | yes | not drivable for exclude=toll |
| abcd | residential | | |
| efgh | residential | | |
When I request a travel time matrix I should get
| | a | b | e | g |
| a | 0 | 15 | | |
Scenario: Testbot - Travel time matrix with different way speeds
Given the node map
"""
a b c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | secondary |
| cd | tertiary |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
| b | 10 | 0 | 20 | 50 |
| c | 30 | 20 | 0 | 30 |
| d | 60 | 50 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| c | 30 |
| d | 60 |
Scenario: Testbot - Travel time matrix of small grid
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel time matrix of network with unroutable parts
Given the node map
"""
a b
"""
And the ways
| nodes | oneway |
| ab | yes |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | | 0 |
Scenario: Testbot - Travel time matrix of network with oneways
Given the node map
"""
x a b y
d e
"""
And the ways
| nodes | oneway |
| abeda | yes |
| xa | |
| by | |
When I request a travel time matrix I should get
| | x | y | d | e |
| x | 0 | 30 | 40 | 30 |
| y | 50 | 0 | 30 | 20 |
| d | 20 | 30 | 0 | 30 |
| e | 30 | 40 | 10 | 0 |
Scenario: Testbot - Rectangular travel time matrix
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
| e | 20 | 10 |
| f | 30 | 20 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 10 | 20 |
| b | 10 | 0 | 10 |
| e | 20 | 10 | 0 |
| f | 30 | 20 | 10 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel time 3x2 matrix
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel time matrix I should get
| | b | e | f |
| a | 10 | 20 | 30 |
| b | 0 | 10 | 20 |
Scenario: Testbot - All coordinates are from same small component
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the node map
"""
a b f
d e g
"""
And the ways
| nodes |
| ab |
| be |
| ed |
| da |
| fg |
When I request a travel time matrix I should get
| | f | g |
| f | 0 | 30 |
| g | 30 | 0 |
Scenario: Testbot - Coordinates are from different small component and snap to big CC
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the node map
"""
a b f h
d e g i
"""
And the ways
| nodes |
| ab |
| be |
| ed |
| da |
| fg |
| hi |
When I request a travel time matrix I should get
| | f | g | h | i |
| f | 0 | 30 | 0 | 30 |
| g | 30 | 0 | 30 | 0 |
| h | 0 | 30 | 0 | 30 |
| i | 30 | 0 | 30 | 0 |
Scenario: Testbot - Travel time matrix with loops
Given the node map
"""
a 1 2 b
d 4 3 c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
| cd | yes |
| da | yes |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
| 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
| 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
Scenario: Testbot - Travel time matrix based on segment durations
Given the profile file
"""
local functions = require('testbot')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.traffic_signal_penalty = 0
profile.u_turn_penalty = 0
return profile
end
functions.process_segment = function(profile, segment)
segment.weight = 2
segment.duration = 11
end
return functions
"""
And the node map
"""
a-b-c-d
.
e
"""
And the ways
| nodes |
| abcd |
| ce |
When I request a travel time matrix I should get
| | a | b | c | d | e |
| a | 0 | 11 | 22 | 33 | 33 |
| b | 11 | 0 | 11 | 22 | 22 |
| c | 22 | 11 | 0 | 11 | 11 |
| d | 33 | 22 | 11 | 0 | 22 |
| e | 33 | 22 | 11 | 22 | 0 |
Scenario: Testbot - Travel time matrix for alternative loop paths
Given the profile file
"""
local functions = require('testbot')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.traffic_signal_penalty = 0
profile.u_turn_penalty = 0
profile.weight_precision = 3
return profile
end
functions.process_segment = function(profile, segment)
segment.weight = 777
segment.duration = 3
end
return functions
"""
And the node map
"""
a 2 1 b
7 4
8 3
c 5 6 d
"""
And the ways
| nodes | oneway |
| ab | yes |
| bd | yes |
| dc | yes |
| ca | yes |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
| 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
| 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
| 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
| 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
Scenario: Testbot - Travel time matrix with ties
Given the profile file
"""
local functions = require('testbot')
functions.process_segment = function(profile, segment)
segment.weight = 1
segment.duration = 1
end
functions.process_turn = function(profile, turn)
if turn.angle >= 0 then
turn.duration = 16
else
turn.duration = 4
end
turn.weight = 0
end
return functions
"""
And the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| ac |
| bd |
| dc |
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 1 | 5 | 10 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 1 |
| c | 15 |
| d | 10 |
Scenario: Testbot - OneToMany vs ManyToOne
Given the node map
"""
a b
c
"""
And the ways
| nodes | oneway |
| ab | yes |
| ac | |
| bc | |
When I request a travel time matrix I should get
| | a | b |
| b | 24.1 | 0 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 24.1 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
| b | 30 | 0 | 12 | 24 |
| f | 18 | 12 | 0 | 30 |
| 1 | 30 | 24 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 30 |
| f | 18 |
| 1 | 30 |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
| b | | | Y | Y |
| f | Y | Y | | |
| 1 | Y | Y | | |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
When I request a travel time matrix I should get estimates for
| | a |
| a | |
| b | |
| f | Y |
| 1 | Y |
Scenario: Testbot - Filling in noroutes with estimates - use input coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | input |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
| b | 30 | 0 | 12 | 24 |
| f | 18 | 12 | 0 | 30 |
| 1 | 30 | 24 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 30 |
| f | 18 |
| 1 | 30 |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
| b | | | Y | Y |
| f | Y | Y | | |
| 1 | Y | Y | | |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
When I request a travel time matrix I should get estimates for
| | a |
| a | |
| b | |
| f | Y |
| 1 | Y |
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 24 |
| b | 30 | 0 | 12 | 18 |
| f | 18 | 12 | 0 | 30 |
| 1 | 24 | 18 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 24 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 30 |
| f | 18 |
| 1 | 24 |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
| b | | | Y | Y |
| f | Y | Y | | |
| 1 | Y | Y | | |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
When I request a travel time matrix I should get estimates for
| | a |
| a | |
| b | |
| f | Y |
| 1 | Y |
Scenario: Testbot - Travel time matrix of minimal network with scale factor
Given the query options
| scale_factor | 2 |
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 20 |
| b | 20 | 0 |
Scenario: Testbot - Test fallback speeds and scale factor
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| scale_factor | 2 |
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 60 | 36 | 48 |
| b | 60 | 0 | 24 | 36 |
| f | 36 | 24 | 0 | 60 |
| 1 | 48 | 36 | 60 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 60 | 36 | 48 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 60 |
| f | 36 |
| 1 | 48 |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
| b | | | Y | Y |
| f | Y | Y | | |
| 1 | Y | Y | | |
When I request a travel time matrix I should get estimates for
| | a | b | f | 1 |
| a | | | Y | Y |
When I request a travel time matrix I should get estimates for
| | a |
| a | |
| b | |
| f | Y |
| 1 | Y |
Scenario: Testbot - Travel time matrix of minimal network with overflow scale factor
Given the query options
| scale_factor | 2147483647 |
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 214748364.6 |
| b | 214748364.6 | 0 |
Scenario: Testbot - Travel time matrix of minimal network with fraction scale factor
Given the query options
| scale_factor | 0.5 |
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 5 |
| b | 5 | 0 |
+61 -2
View File
@@ -39,5 +39,64 @@ Feature: Fixed bugs, kept to check for regressions
| de | yes |
When I route I should get
| from | to | route |
| 1 | 2 | bcd,bcd |
| from | to | route |
| 1 | 2 | bcd,bcd |
#############################
# This test models the OSM map at the location for
# https://github.com/Project-OSRM/osrm-backend/issues/5039
#############################
Scenario: Mixed Entry and Exit and segregated
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
Given the node locations
| node | lon | lat |
| a | 171.12889297029 | -42.58425289548 |
| b | 171.1299357 | -42.5849295 |
| c | 171.1295427 | -42.5849385 |
| d | 171.1297356 | -42.5852029 |
| e | 171.1296909 | -42.5851986 |
| f | 171.1295097 | -42.585007 |
| g | 171.1298225 | -42.5851928 |
| h | 171.1300262 | -42.5859122 |
| i | 171.1292651 | -42.584698 |
| j | 171.1297209 | -42.5848569 |
| k | 171.1297188 | -42.5854056 |
| l | 171.1298326 | -42.5857266 |
| m | 171.1298871 | -42.5848922 |
| n | 171.1296505 | -42.585189 |
| o | 171.1295206 | -42.5850862 |
| p | 171.1296106 | -42.5848862 |
| q | 171.1299784 | -42.5850191 |
| r | 171.1298867 | -42.5851671 |
| s | 171.1306955 | -42.5845812 |
| t | 171.129525 | -42.584807 |
| u | 171.1299705 | -42.584984 |
| v | 171.1299067 | -42.5849073 |
| w | 171.1302061 | -42.5848173 |
| x | 171.12975 | -42.5855753 |
| y | 171.129969 | -42.585079 |
| 1 | 171.131511926651| -42.584306746421966 |
| 2 | 171.128743886947| -42.58414875714669 |
And the ways
| nodes | highway | maxspeed | name | ref | surface | junction | oneway |
| ws | primary | 100 | Taramakau Highway | SH 6 | asphalt | | |
| kxlh | trunk | | Otira Highway | SH 73 | | | |
| ai | primary | 100 | Kumara Junction Highway | SH 6 | asphalt | | |
| qyrgdenof | primary | 100 | Kumara Junction | | | roundabout | yes |
| ke | trunk | | Otira Highway | SH 73 | | | yes |
| itj | primary | 100 | Kumara Junction Highway | SH 6 | | | yes |
| gk | trunk | | Otira Highway | SH 73 | | | yes |
| fi | primary | 100 | Kumara Junction Highway | SH 6 | | | yes |
| wq | primary | 100 | Taramakau Highway | SH 6 | | | yes |
| vw | primary | 100 | Taramakau Highway | SH 6 | | | yes |
| vbuq | primary | 100 | Kumara Junction | | | roundabout | yes |
| jmv | primary | 100 | Kumara Junction | | | roundabout | yes |
| fcpj | primary | 100 | Kumara Junction | | | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| 1,2 | Taramakau Highway,Kumara Junction Highway,Kumara Junction Highway,Kumara Junction Highway | depart,Kumara Junction-exit-2,exit rotary slight left,arrive |
+62 -30
View File
@@ -38,15 +38,15 @@ Feature: Multi level routing
Scenario: Testbot - Multi level routing
Given the node map
"""
ab ef
ab ef
\ /
dc hg
ij mn
lkpo
/ \
lkpo
"""
And the nodes
@@ -67,44 +67,76 @@ Feature: Multi level routing
When I route I should get
| from | to | route | time |
| a | b | abcda,abcda | 20s |
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 229.4s |
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 144.7s |
| a | o | abcda,cm,mnopm,mnopm,mnopm | 124.7s |
| f | l | efghe,hj,ijkli,ijkli,ijkli | 124.7s |
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 144.7s |
| l | o | ijkli,kp,mnopm,mnopm | 60s |
| a | b | abcda,abcda | 25s |
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 239.2s |
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 157.1s |
| a | o | abcda,cm,mnopm,mnopm,mnopm | 137.1s |
| f | l | efghe,hj,ijkli,ijkli | 136.7s |
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 162.1s |
| l | o | ijkli,kp,mnopm,mnopm | 80s |
| c | m | cm,cm | 44.7s |
| f | a | efghe,hj,ijkli,kp,mnopm,cm,abcda,abcda | 239.2s |
| l | a | ijkli,kp,mnopm,cm,abcda,abcda | 157.1s |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| f | 229.4 | 0 | 124.7 | 144.7 |
| l | 144.7 | 124.7 | 0 | 60 |
| o | 124.7 | 144.7 | 60 | 0 |
| | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 |
| f | 239.2 | 0 | 136.7 | 162.1 |
| l | 157.1 | 136.7 | 0 | 80 |
| o | 137.1 | 162.1 | 80 | 0 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| f | 229.4 |
| l | 144.7 |
| o | 124.7 |
| | a |
| a | 0 |
| f | 239.2 |
| l | 157.1 |
| o | 137.1 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| o | 124.7 | 144.7 | 60 | 0 |
| | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 |
| o | 137.1 | 162.1 | 80 | 0 |
When I request a travel time matrix I should get
| | a | o |
| a | 0 | 124.7 |
| f | 229.4 | 144.7 |
| l | 144.7 | 60 |
| o | 124.7 | 0 |
| a | 0 | 137.1 |
| f | 239.2 | 162.1 |
| l | 157.1 | 80 |
| o | 137.1 | 0 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
| f | 2383.7 | 0 | 1293.3 | 1617.3 |
| l | 1566.9 | 1293.3 | 0 | 800.5 |
| o | 1366.8 | 1617.3 | 800.5 | 0 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| f | 2383.7 |
| l | 1566.9 |
| o | 1366.8 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
| f | 2383.7 | 0 | 1293.3 | 1617.3 |
When I request a travel distance matrix I should get
| | a | o |
| a | 0 | 1366.8 |
| f | 2383.7 | 1617.3 |
| l | 1566.9 | 800.5 |
| o | 1366.8 | 0 |
Scenario: Testbot - Multi level routing: horizontal road
Given the node map
+1 -1
View File
@@ -182,4 +182,4 @@ Feature: Snap start/end point to the nearest way
| x | m | xe,xe |
| x | n | xf,xf |
| x | o | xg,xg |
| x | p | xh,xh |
| x | p | xh,xh |
+168
View File
@@ -0,0 +1,168 @@
@routing @maxspeed @testbot
Feature: Testbot - Acceleration profiles
Background: Use specific speeds
Given the profile "testbot"
Scenario: Testbot - No stoppage penalties
Given a grid size of 10 meters
Given the node map
"""
a 1 2 3 4 5 b
"""
And the ways
| nodes | highway | maxspeed:forward | maxspeed:backward |
| ab | trunk | 60 | 45 |
When I route I should get
| from | to | route | time | distance |
| a | b | ab,ab | 3.6s | 59.9m |
| a | 1 | ab,ab | 0.6s | 10m |
| a | 2 | ab,ab | 1.2s | 20m |
| a | 3 | ab,ab | 1.8s | 30m |
| a | 4 | ab,ab | 2.4s | 40m |
| a | 5 | ab,ab | 3s | 50m |
| 5 | b | ab,ab | 0.6s | 9.9m |
| 4 | b | ab,ab | 1.2s | 19.9m |
| 3 | b | ab,ab | 1.8s | 29.9m |
| 2 | b | ab,ab | 2.4s | 39.9m |
| 1 | b | ab,ab | 3s | 49.9m |
| 1 | 2 | ab,ab | 0.6s | 10m |
| 1 | 3 | ab,ab | 1.2s | 20m |
| 1 | 4 | ab,ab | 1.8s | 30m |
| 1 | 5 | ab,ab | 2.4s | 40m |
When I request a travel time matrix I should get
| | a | 1 | 2 | 3 | 4 | 5 | b |
| a | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 | 3.6 |
| 1 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 |
| 2 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 |
| 3 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 |
| 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 |
| 5 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 |
| b | 4.8 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 |
Scenario: Testbot - No stoppage points, tiny grid size
Given a grid size of 1 meters
Given the node map
"""
a 1 2 3 4 5 6 7 8 9 b
"""
And the ways
| nodes | highway | maxspeed:forward | maxspeed:backward |
| ab | trunk | 60 | 45 |
When I request a travel time matrix I should get
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
| a | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
| 1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
| 2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
| 3 | 0.2 | 0.2 | 0.1 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
| 4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 | 0.1 | 0.2 | 0.2 | 0.3 | 0.4 |
| 5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
| 6 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
| 7 | 0.5 | 0.5 | 0.4 | 0.3 | 0.2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 |
| 8 | 0.6 | 0.6 | 0.5 | 0.4 | 0.3 | 0.2 | 0.2 | 0.1 | 0 | 0.1 | 0.2 |
| 9 | 0.7 | 0.7 | 0.6 | 0.5 | 0.4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 |
| b | 0.8 | 0.8 | 0.7 | 0.6 | 0.5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 |
Scenario: Testbot - With stoppage points, tiny grid size
Given a grid size of 1 meters
Given the node map
"""
a 1 2 3 4 5 6 7 8 9 b
"""
And the ways
| nodes | highway | maxspeed:forward | maxspeed:backward |
| ab | trunk | 60 | 45 |
And the query options
| acceleration_profile | car |
When I request a travel time matrix I should get
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
| a | 0 | 1.1 | 1.7 | 2.1 | 2.4 | 2.6 | 2.9 | 3.1 | 3.4 | 3.5 | 3.7 |
| 1 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.3 | 2.6 | 2.8 | 3.1 | 3.3 | 3.5 |
| 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.4 | 2.6 | 2.9 | 3.1 | 3.3 |
| 3 | 2 | 1.5 | 1.1 | 0 | 1.1 | 1.5 | 2 | 2.3 | 2.6 | 2.8 | 3 |
| 4 | 2.3 | 1.9 | 1.5 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.4 | 2.6 | 2.8 |
| 5 | 2.5 | 2.2 | 1.9 | 1.5 | 1.1 | 0 | 1.1 | 1.7 | 2.1 | 2.4 | 2.6 |
| 6 | 2.8 | 2.5 | 2.3 | 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.3 |
| 7 | 3 | 2.8 | 2.5 | 2.3 | 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 |
| 8 | 3.2 | 3 | 2.8 | 2.5 | 2.3 | 2 | 1.5 | 1.1 | 0 | 1.1 | 1.5 |
| 9 | 3.4 | 3.2 | 3 | 2.8 | 2.5 | 2.3 | 1.9 | 1.5 | 1.1 | 0 | 1.1 |
| b | 3.6 | 3.4 | 3.2 | 3 | 2.8 | 2.5 | 2.2 | 1.9 | 1.5 | 1.1 | 0 |
Scenario: Testbot - Use stoppage penalty at waypoints
Given a grid size of 10 meters
Given the node map
"""
a 1 2 3 4 5 b
"""
And the ways
| nodes | highway | maxspeed:forward | maxspeed:backward |
| ab | trunk | 60 | 45 |
And the query options
| acceleration_profile | car |
When I request a travel time matrix I should get
| | a | 1 | 2 | 3 | 4 | 5 | b |
| a | 0 | 3.7 | 5.3 | 6.5 | 7.5 | 8.4 | 9.1 |
| 1 | 3.6 | 0 | 3.7 | 5.3 | 6.5 | 7.5 | 8.3 |
| 2 | 5.1 | 3.6 | 0 | 3.7 | 5.3 | 6.5 | 7.5 |
| 3 | 6.3 | 5.1 | 3.6 | 0 | 3.7 | 5.3 | 6.4 |
| 4 | 7.2 | 6.3 | 5.1 | 3.6 | 0 | 3.7 | 5.2 |
| 5 | 8.1 | 7.2 | 6.3 | 5.1 | 3.6 | 0 | 3.7 |
| b | 8.9 | 8.1 | 7.2 | 6.2 | 5.1 | 3.6 | 0 |
Scenario: Long distance grid with no penalty
Given a grid size of 1000 meters
Given the node map
"""
a 1 2 3 4 5 b
"""
And the ways
| nodes | highway | maxspeed:forward | maxspeed:backward |
| ab | trunk | 60 | 45 |
When I request a travel time matrix I should get
| | a | 1 | 2 | 3 | 4 | 5 | b |
| a | 0 | 59.9 | 119.9 | 179.9 | 239.9 | 299.9 | 359.9 |
| 1 | 79.9 | 0 | 60 | 120 | 180 | 240 | 300 |
| 2 | 159.9 | 80 | 0 | 60 | 120 | 180 | 240 |
| 3 | 239.9 | 160 | 80 | 0 | 60 | 120 | 180 |
| 4 | 319.9 | 240 | 160 | 80 | 0 | 60 | 120 |
| 5 | 399.9 | 320 | 240 | 160 | 80 | 0 | 60 |
| b | 479.9 | 400 | 320 | 240 | 160 | 80 | 0 |
Scenario: Long distance grid
Given a grid size of 1000 meters
Given the node map
"""
a 1 2 3 4 5 b
"""
And the ways
| nodes | highway | maxspeed:forward | maxspeed:backward |
| ab | trunk | 60 | 45 |
And the query options
| acceleration_profile | car |
When I request a travel time matrix I should get
| | a | 1 | 2 | 3 | 4 | 5 | b |
| a | 0 | 65.1 | 125.1 | 185.1 | 245.1 | 305.1 | 365.1 |
| 1 | 83.7 | 0 | 65.2 | 125.2 | 185.2 | 245.2 | 305.2 |
| 2 | 163.7 | 83.8 | 0 | 65.2 | 125.2 | 185.2 | 245.2 |
| 3 | 243.7 | 163.8 | 83.8 | 0 | 65.2 | 125.2 | 185.2 |
| 4 | 323.7 | 243.8 | 163.8 | 83.8 | 0 | 65.2 | 125.2 |
| 5 | 403.7 | 323.8 | 243.8 | 163.8 | 83.8 | 0 | 65.2 |
| b | 483.7 | 403.8 | 323.8 | 243.8 | 163.8 | 83.8 | 0 |
+1 -1
View File
@@ -54,7 +54,7 @@ Feature: Traffic - speeds
| a | d | ad,ad | 27 km/h | 1275.7,0 | 1 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 | 1:0:0 |
| a | g | ad,df,fb,fb | 30 km/h | 1295.7,487.5,304.7,0 | 1:0:0 |
Scenario: Weighting based on speed file weights, ETA based on file durations
+5 -2
View File
@@ -12,23 +12,26 @@ namespace contractor
struct ContractorEdgeData
{
ContractorEdgeData()
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
: weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0),
backward(0)
{
}
ContractorEdgeData(EdgeWeight weight,
EdgeWeight duration,
EdgeDistance distance,
unsigned original_edges,
unsigned id,
bool shortcut,
bool forward,
bool backward)
: weight(weight), duration(duration), id(id),
: weight(weight), duration(duration), distance(distance), id(id),
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
forward(forward), backward(backward)
{
}
EdgeWeight weight;
EdgeWeight duration;
EdgeDistance distance;
unsigned id;
unsigned originalEdges : 29;
bool shortcut : 1;
@@ -41,6 +41,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.target,
std::max(input_edge.data.weight, 1),
input_edge.data.duration,
input_edge.data.distance,
1,
input_edge.data.turn_id,
false,
@@ -51,6 +52,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.source,
std::max(input_edge.data.weight, 1),
input_edge.data.duration,
input_edge.data.distance,
1,
input_edge.data.turn_id,
false,
@@ -82,6 +84,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE;
// remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
{
@@ -90,12 +93,16 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
forward_edge.data.duration =
std::min(edges[i].data.duration, forward_edge.data.duration);
forward_edge.data.distance =
std::min(edges[i].data.distance, forward_edge.data.distance);
}
if (edges[i].data.backward)
{
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
reverse_edge.data.duration =
std::min(edges[i].data.duration, reverse_edge.data.duration);
reverse_edge.data.distance =
std::min(edges[i].data.distance, reverse_edge.data.distance);
}
++i;
}
@@ -151,6 +158,7 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
new_edge.data.weight = data.weight;
new_edge.data.duration = data.duration;
new_edge.data.distance = data.distance;
new_edge.data.shortcut = data.shortcut;
new_edge.data.turn_id = data.id;
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
+8 -3
View File
@@ -17,7 +17,8 @@ struct QueryEdge
struct EdgeData
{
explicit EdgeData()
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false)
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false),
distance(0)
{
}
@@ -25,10 +26,11 @@ struct QueryEdge
const bool shortcut,
const EdgeWeight weight,
const EdgeWeight duration,
const EdgeDistance distance,
const bool forward,
const bool backward)
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
forward(forward), backward(backward)
forward(forward), backward(backward), distance(distance)
{
}
@@ -40,6 +42,7 @@ struct QueryEdge
turn_id = other.id;
forward = other.forward;
backward = other.backward;
distance = other.distance;
}
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
@@ -50,6 +53,7 @@ struct QueryEdge
EdgeWeight duration : 30;
std::uint32_t forward : 1;
std::uint32_t backward : 1;
EdgeDistance distance;
} data;
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
@@ -69,7 +73,8 @@ struct QueryEdge
return (source == right.source && target == right.target &&
data.weight == right.data.weight && data.duration == right.data.duration &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
data.backward == right.data.backward && data.turn_id == right.data.turn_id);
data.backward == right.data.backward && data.turn_id == right.data.turn_id &&
data.distance == right.data.distance);
}
};
}
+37 -11
View File
@@ -22,6 +22,7 @@ class CellCustomizer
{
bool from_clique;
EdgeDuration duration;
EdgeDistance distance;
};
public:
@@ -60,7 +61,7 @@ class CellCustomizer
}
}
heap.Clear();
heap.Insert(source, 0, {false, 0});
heap.Insert(source, 0, {false, 0, 0});
// explore search space
while (!heap.Empty() && !destinations_set.empty())
@@ -68,8 +69,18 @@ class CellCustomizer
const NodeID node = heap.DeleteMin();
const EdgeWeight weight = heap.GetKey(node);
const EdgeDuration duration = heap.GetData(node).duration;
const EdgeDistance distance = heap.GetData(node).distance;
RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration);
RelaxNode(graph,
cells,
allowed_nodes,
metric,
heap,
level,
node,
weight,
duration,
distance);
destinations_set.erase(node);
}
@@ -77,21 +88,27 @@ class CellCustomizer
// fill a map of destination nodes to placeholder pointers
auto weights = cell.GetOutWeight(source);
auto durations = cell.GetOutDuration(source);
auto distances = cell.GetOutDistance(source);
for (auto &destination : destinations)
{
BOOST_ASSERT(!weights.empty());
BOOST_ASSERT(!durations.empty());
BOOST_ASSERT(!distances.empty());
const bool inserted = heap.WasInserted(destination);
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
durations.front() =
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
distances.front() =
inserted ? heap.GetData(destination).distance : INVALID_EDGE_DISTANCE;
weights.advance_begin(1);
durations.advance_begin(1);
distances.advance_begin(1);
}
BOOST_ASSERT(weights.empty());
BOOST_ASSERT(durations.empty());
BOOST_ASSERT(distances.empty());
}
}
@@ -128,7 +145,8 @@ class CellCustomizer
LevelID level,
NodeID node,
EdgeWeight weight,
EdgeDuration duration) const
EdgeDuration duration,
EdgeDistance distance) const
{
auto first_level = level == 1;
BOOST_ASSERT(heap.WasInserted(node));
@@ -149,6 +167,7 @@ class CellCustomizer
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin();
auto subcell_duration = subcell.GetOutDuration(node).begin();
auto subcell_distance = subcell.GetOutDistance(node).begin();
for (auto subcell_weight : subcell.GetOutWeight(node))
{
if (subcell_weight != INVALID_EDGE_WEIGHT)
@@ -161,20 +180,24 @@ class CellCustomizer
const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration;
const EdgeDistance to_distance = distance + *subcell_distance;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true, to_duration});
heap.Insert(to, to_weight, {true, to_duration, to_distance});
}
else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
else if (std::tie(to_weight, to_duration, to_distance) <
std::tie(heap.GetKey(to),
heap.GetData(to).duration,
heap.GetData(to).distance))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {true, to_duration};
heap.GetData(to) = {true, to_duration, to_distance};
}
}
++subcell_destination;
++subcell_duration;
++subcell_distance;
}
}
}
@@ -195,15 +218,18 @@ class CellCustomizer
{
const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration;
const EdgeDistance to_distance = distance + data.distance;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {false, duration + data.duration});
heap.Insert(
to, to_weight, {false, duration + data.duration, distance + data.distance});
}
else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
else if (std::tie(to_weight, to_duration, to_distance) <
std::tie(
heap.GetKey(to), heap.GetData(to).duration, heap.GetData(to).distance))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {false, to_duration};
heap.GetData(to) = {false, to_duration, to_distance};
}
}
}
+1
View File
@@ -20,6 +20,7 @@ template <storage::Ownership Ownership> struct CellMetricImpl
Vector<EdgeWeight> weights;
Vector<EdgeDuration> durations;
Vector<EdgeDistance> distances;
};
}
+2 -1
View File
@@ -21,7 +21,8 @@ struct CustomizationConfig final : storage::IOConfig
".osrm.partition",
".osrm.cells",
".osrm.ebg_nodes",
".osrm.properties"},
".osrm.properties",
".osrm.enw"},
{},
{".osrm.cell_metrics", ".osrm.mldgr"}),
requested_num_threads(0)
+104 -16
View File
@@ -16,28 +16,116 @@ namespace osrm
namespace customizer
{
using EdgeBasedGraphEdgeData = partitioner::EdgeBasedGraphEdgeData;
struct MultiLevelEdgeBasedGraph
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
struct EdgeBasedGraphEdgeData
{
using Base =
partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
using Base::Base;
NodeID turn_id; // ID of the edge based node (node based edge)
};
struct MultiLevelEdgeBasedGraphView
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
namespace serialization
{
using Base = partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
using Base::Base;
template <typename EdgeDataT, storage::Ownership Ownership>
void read(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph);
template <typename EdgeDataT, storage::Ownership Ownership>
void write(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
}
template <typename EdgeDataT, storage::Ownership Ownership>
class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership>
{
private:
using SuperT = partitioner::MultiLevelGraph<EdgeDataT, Ownership>;
using PartitionerGraphT = partitioner::MultiLevelGraph<partitioner::EdgeBasedGraphEdgeData,
storage::Ownership::Container>;
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public:
using NodeArrayEntry = typename SuperT::NodeArrayEntry;
using EdgeArrayEntry = typename SuperT::EdgeArrayEntry;
using EdgeOffset = typename SuperT::EdgeOffset;
MultiLevelGraph() = default;
MultiLevelGraph(MultiLevelGraph &&) = default;
MultiLevelGraph(const MultiLevelGraph &) = default;
MultiLevelGraph &operator=(MultiLevelGraph &&) = default;
MultiLevelGraph &operator=(const MultiLevelGraph &) = default;
MultiLevelGraph(PartitionerGraphT &&graph,
Vector<EdgeWeight> node_weights_,
Vector<EdgeDuration> node_durations_,
Vector<EdgeDistance> node_distances_)
: node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
node_distances(std::move(node_distances_))
{
util::ViewOrVector<PartitionerGraphT::EdgeArrayEntry, storage::Ownership::Container>
original_edge_array;
std::tie(SuperT::node_array,
original_edge_array,
SuperT::node_to_edge_offset,
SuperT::connectivity_checksum) = std::move(graph).data();
SuperT::edge_array.reserve(original_edge_array.size());
for (const auto &edge : original_edge_array)
{
SuperT::edge_array.push_back({edge.target, {edge.data.turn_id}});
is_forward_edge.push_back(edge.data.forward);
is_backward_edge.push_back(edge.data.backward);
}
}
MultiLevelGraph(Vector<NodeArrayEntry> node_array_,
Vector<EdgeArrayEntry> edge_array_,
Vector<EdgeOffset> node_to_edge_offset_,
Vector<EdgeWeight> node_weights_,
Vector<EdgeDuration> node_durations_,
Vector<EdgeDistance> node_distances_,
Vector<bool> is_forward_edge_,
Vector<bool> is_backward_edge_)
: SuperT(std::move(node_array_), std::move(edge_array_), std::move(node_to_edge_offset_)),
node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
node_distances(std::move(node_distances_)), is_forward_edge(is_forward_edge_),
is_backward_edge(is_backward_edge_)
{
}
EdgeWeight GetNodeWeight(NodeID node) const { return node_weights[node]; }
EdgeWeight GetNodeDuration(NodeID node) const { return node_durations[node]; }
EdgeDistance GetNodeDistance(NodeID node) const { return node_distances[node]; }
bool IsForwardEdge(EdgeID edge) const { return is_forward_edge[edge]; }
bool IsBackwardEdge(EdgeID edge) const { return is_backward_edge[edge]; }
friend void
serialization::read<EdgeDataT, Ownership>(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph);
friend void
serialization::write<EdgeDataT, Ownership>(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
protected:
Vector<EdgeWeight> node_weights;
Vector<EdgeDuration> node_durations;
Vector<EdgeDistance> node_distances;
Vector<bool> is_forward_edge;
Vector<bool> is_backward_edge;
};
struct StaticEdgeBasedGraphEdge : MultiLevelEdgeBasedGraph::InputEdge
{
using Base = MultiLevelEdgeBasedGraph::InputEdge;
using Base::Base;
};
using MultiLevelEdgeBasedGraph =
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
using MultiLevelEdgeBasedGraphView =
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
}
}
+33
View File
@@ -73,6 +73,39 @@ writeCellMetrics(const boost::filesystem::path &path,
}
}
}
// reads .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void readGraph(const boost::filesystem::path &path,
MultiLevelGraphT &graph,
std::uint32_t &connectivity_checksum)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
storage::tar::FileReader reader{path, storage::tar::FileReader::VerifyFingerprint};
reader.ReadInto("/mld/connectivity_checksum", connectivity_checksum);
serialization::read(reader, "/mld/multilevelgraph", graph);
}
// writes .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void writeGraph(const boost::filesystem::path &path,
const MultiLevelGraphT &graph,
const std::uint32_t connectivity_checksum)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
storage::tar::FileWriter writer{path, storage::tar::FileWriter::GenerateFingerprint};
writer.WriteElementCount64("/mld/connectivity_checksum", 1);
writer.WriteFrom("/mld/connectivity_checksum", connectivity_checksum);
serialization::write(writer, "/mld/multilevelgraph", graph);
}
}
}
}
+34
View File
@@ -1,6 +1,8 @@
#ifndef OSRM_CUSTOMIZER_SERIALIZATION_HPP
#define OSRM_CUSTOMIZER_SERIALIZATION_HPP
#include "customizer/edge_based_graph.hpp"
#include "partitioner/cell_storage.hpp"
#include "storage/serialization.hpp"
@@ -21,6 +23,7 @@ inline void read(storage::tar::FileReader &reader,
{
storage::serialization::read(reader, name + "/weights", metric.weights);
storage::serialization::read(reader, name + "/durations", metric.durations);
storage::serialization::read(reader, name + "/distances", metric.distances);
}
template <storage::Ownership Ownership>
@@ -30,6 +33,37 @@ inline void write(storage::tar::FileWriter &writer,
{
storage::serialization::write(writer, name + "/weights", metric.weights);
storage::serialization::write(writer, name + "/durations", metric.durations);
storage::serialization::write(writer, name + "/distances", metric.distances);
}
template <typename EdgeDataT, storage::Ownership Ownership>
inline void read(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::read(reader, name + "/node_array", graph.node_array);
storage::serialization::read(reader, name + "/node_weights", graph.node_weights);
storage::serialization::read(reader, name + "/node_durations", graph.node_durations);
storage::serialization::read(reader, name + "/node_distances", graph.node_distances);
storage::serialization::read(reader, name + "/edge_array", graph.edge_array);
storage::serialization::read(reader, name + "/is_forward_edge", graph.is_forward_edge);
storage::serialization::read(reader, name + "/is_backward_edge", graph.is_backward_edge);
storage::serialization::read(reader, name + "/node_to_edge_offset", graph.node_to_edge_offset);
}
template <typename EdgeDataT, storage::Ownership Ownership>
inline void write(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::write(writer, name + "/node_array", graph.node_array);
storage::serialization::write(writer, name + "/node_weights", graph.node_weights);
storage::serialization::write(writer, name + "/node_durations", graph.node_durations);
storage::serialization::write(writer, name + "/node_distances", graph.node_distances);
storage::serialization::write(writer, name + "/edge_array", graph.edge_array);
storage::serialization::write(writer, name + "/is_forward_edge", graph.is_forward_edge);
storage::serialization::write(writer, name + "/is_backward_edge", graph.is_backward_edge);
storage::serialization::write(writer, name + "/node_to_edge_offset", graph.node_to_edge_offset);
}
}
}
+9
View File
@@ -50,6 +50,9 @@ template <typename AlgorithmT> struct HasMapMatching final : std::false_type
template <typename AlgorithmT> struct HasManyToManySearch final : std::false_type
{
};
template <typename AlgorithmT> struct SupportsDistanceAnnotationType final : std::false_type
{
};
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
{
};
@@ -73,6 +76,9 @@ template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
{
};
template <> struct SupportsDistanceAnnotationType<ch::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
{
};
@@ -96,6 +102,9 @@ template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
{
};
template <> struct SupportsDistanceAnnotationType<mld::Algorithm> final : std::false_type
{
};
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
{
};
+5
View File
@@ -6,6 +6,7 @@
#include "engine/api/json_factory.hpp"
#include "engine/hint.hpp"
#include "util/coordinate_calculation.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm/transform.hpp>
@@ -53,6 +54,8 @@ class BaseAPI
// TODO: check forward/reverse
return json::makeWaypoint(
phantom.location,
util::coordinate_calculation::fccApproximateDistance(phantom.location,
phantom.input_location),
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string(),
Hint{phantom, facade.GetCheckSum()});
}
@@ -61,6 +64,8 @@ class BaseAPI
// TODO: check forward/reverse
return json::makeWaypoint(
phantom.location,
util::coordinate_calculation::fccApproximateDistance(phantom.location,
phantom.input_location),
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))
.to_string());
}
+16 -2
View File
@@ -63,6 +63,13 @@ namespace api
*/
struct BaseParameters
{
enum class SnappingType
{
Default,
Any
};
std::vector<util::Coordinate> coordinates;
std::vector<boost::optional<Hint>> hints;
std::vector<boost::optional<double>> radiuses;
@@ -73,15 +80,22 @@ struct BaseParameters
// Adds hints to response which can be included in subsequent requests, see `hints` above.
bool generate_hints = true;
SnappingType snapping = SnappingType::Default;
// Whether or not to add acceleration/decelleration penalties at waypoints
double waypoint_acceleration_factor = 0.;
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
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,
std::vector<std::string> exclude = {})
std::vector<std::string> exclude = {},
const SnappingType snapping_ = SnappingType::Default,
bool waypoint_acceleration_factor_ = 0.)
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_),
snapping(snapping_), waypoint_acceleration_factor(waypoint_acceleration_factor_)
{
}
+7 -4
View File
@@ -33,7 +33,7 @@ namespace json
namespace detail
{
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
util::json::Array coordinateToLonLat(const util::Coordinate &coordinate);
/**
* Ensures that a bearing value is a whole number, and clamped to the range 0-359
@@ -86,11 +86,14 @@ util::json::Object makeRoute(const guidance::Route &route,
const char *weight_name);
// Creates a Waypoint without Hint, see the Hint overload below
util::json::Object makeWaypoint(const util::Coordinate location, std::string name);
util::json::Object
makeWaypoint(const util::Coordinate &location, const double &distance, std::string name);
// Creates a Waypoint with Hint, see the overload above when Hint is not needed
util::json::Object
makeWaypoint(const util::Coordinate location, std::string name, const Hint &hint);
util::json::Object makeWaypoint(const util::Coordinate &location,
const double &distance,
std::string name,
const Hint &hint);
util::json::Object makeRouteLeg(guidance::RouteLeg leg, util::json::Array steps);
-1
View File
@@ -41,7 +41,6 @@ class NearestAPI final : public BaseAPI
[this](const PhantomNodeWithDistance &phantom_with_distance) {
auto &phantom_node = phantom_with_distance.phantom_node;
auto waypoint = MakeWaypoint(phantom_node);
waypoint.values["distance"] = phantom_with_distance.distance;
util::json::Array nodes;
+77 -8
View File
@@ -31,14 +31,25 @@ namespace api
class TableAPI final : public BaseAPI
{
public:
struct TableCellRef
{
TableCellRef(const std::size_t &row, const std::size_t &column) : row{row}, column{column}
{
}
std::size_t row;
std::size_t column;
};
TableAPI(const datafacade::BaseDataFacade &facade_, const TableParameters &parameters_)
: BaseAPI(facade_, parameters_), parameters(parameters_)
{
}
virtual void MakeResponse(const std::vector<EdgeWeight> &durations,
const std::vector<PhantomNode> &phantoms,
util::json::Object &response) const
virtual void
MakeResponse(const std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> &tables,
const std::vector<PhantomNode> &phantoms,
const std::vector<TableCellRef> &fallback_speed_cells,
util::json::Object &response) const
{
auto number_of_sources = parameters.sources.size();
auto number_of_destinations = parameters.destinations.size();
@@ -64,8 +75,23 @@ class TableAPI final : public BaseAPI
response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations);
}
response.values["durations"] =
MakeTable(durations, number_of_sources, number_of_destinations);
if (parameters.annotations & TableParameters::AnnotationsType::Duration)
{
response.values["durations"] =
MakeDurationTable(tables.first, number_of_sources, number_of_destinations);
}
if (parameters.annotations & TableParameters::AnnotationsType::Distance)
{
response.values["distances"] =
MakeDistanceTable(tables.second, number_of_sources, number_of_destinations);
}
if (parameters.fallback_speed != INVALID_FALLBACK_SPEED && parameters.fallback_speed > 0)
{
response.values["fallback_speed_cells"] = MakeEstimatesTable(fallback_speed_cells);
}
response.values["code"] = "Ok";
}
@@ -97,9 +123,9 @@ class TableAPI final : public BaseAPI
return json_waypoints;
}
virtual util::json::Array MakeTable(const std::vector<EdgeWeight> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
virtual util::json::Array MakeDurationTable(const std::vector<EdgeWeight> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
{
util::json::Array json_table;
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
@@ -116,6 +142,7 @@ class TableAPI final : public BaseAPI
{
return util::json::Value(util::json::Null());
}
// division by 10 because the duration is in deciseconds (10s)
return util::json::Value(util::json::Number(duration / 10.));
});
json_table.values.push_back(std::move(json_row));
@@ -123,6 +150,48 @@ class TableAPI final : public BaseAPI
return json_table;
}
virtual util::json::Array MakeDistanceTable(const std::vector<EdgeDistance> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
{
util::json::Array json_table;
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
{
util::json::Array json_row;
auto row_begin_iterator = values.begin() + (row * number_of_columns);
auto row_end_iterator = values.begin() + ((row + 1) * number_of_columns);
json_row.values.resize(number_of_columns);
std::transform(row_begin_iterator,
row_end_iterator,
json_row.values.begin(),
[](const EdgeDistance distance) {
if (distance == INVALID_EDGE_DISTANCE)
{
return util::json::Value(util::json::Null());
}
// round to single decimal place
return util::json::Value(
util::json::Number(std::round(distance * 10) / 10.));
});
json_table.values.push_back(std::move(json_row));
}
return json_table;
}
virtual util::json::Array
MakeEstimatesTable(const std::vector<TableCellRef> &fallback_speed_cells) const
{
util::json::Array json_table;
std::for_each(
fallback_speed_cells.begin(), fallback_speed_cells.end(), [&](const auto &cell) {
util::json::Array row;
row.values.push_back(util::json::Number(cell.row));
row.values.push_back(util::json::Number(cell.column));
json_table.values.push_back(std::move(row));
});
return json_table;
}
const TableParameters &parameters;
};
+75 -9
View File
@@ -59,6 +59,27 @@ struct TableParameters : public BaseParameters
{
std::vector<std::size_t> sources;
std::vector<std::size_t> destinations;
double fallback_speed = INVALID_FALLBACK_SPEED;
enum class FallbackCoordinateType
{
Input = 0,
Snapped = 1
};
FallbackCoordinateType fallback_coordinate_type = FallbackCoordinateType::Input;
enum class AnnotationsType
{
None = 0,
Duration = 0x01,
Distance = 0x02,
All = Duration | Distance
};
AnnotationsType annotations = AnnotationsType::Duration;
double scale_factor = 1;
TableParameters() = default;
template <typename... Args>
@@ -70,6 +91,32 @@ struct TableParameters : public BaseParameters
{
}
template <typename... Args>
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
const AnnotationsType annotations_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, annotations{annotations_}
{
}
template <typename... Args>
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
const AnnotationsType annotations_,
double fallback_speed_,
FallbackCoordinateType fallback_coordinate_type_,
double scale_factor_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
scale_factor{scale_factor_}
{
}
bool IsValid() const
{
if (!BaseParameters::IsValid())
@@ -79,16 +126,9 @@ struct TableParameters : public BaseParameters
if (coordinates.size() < 2)
return false;
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's her fault
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's their fault
// 2/ len(srcs) and len(dsts) smaller or equal to len(locations)
if (sources.size() > coordinates.size())
return false;
if (destinations.size() > coordinates.size())
return false;
// 3/ 0 <= index < len(locations)
// 2/ 0 <= index < len(locations)
const auto not_in_range = [this](const std::size_t x) { return x >= coordinates.size(); };
if (std::any_of(begin(sources), end(sources), not_in_range))
@@ -97,9 +137,35 @@ struct TableParameters : public BaseParameters
if (std::any_of(begin(destinations), end(destinations), not_in_range))
return false;
if (fallback_speed <= 0)
return false;
if (scale_factor <= 0)
return false;
return true;
}
};
inline bool operator&(TableParameters::AnnotationsType lhs, TableParameters::AnnotationsType rhs)
{
return static_cast<bool>(
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(lhs) &
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(rhs));
}
inline TableParameters::AnnotationsType operator|(TableParameters::AnnotationsType lhs,
TableParameters::AnnotationsType rhs)
{
return (TableParameters::AnnotationsType)(
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(lhs) |
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(rhs));
}
inline TableParameters::AnnotationsType &operator|=(TableParameters::AnnotationsType &lhs,
TableParameters::AnnotationsType rhs)
{
return lhs = lhs | rhs;
}
}
}
}
@@ -2,6 +2,7 @@
#define OSRM_ENGINE_DATAFACADE_ALGORITHM_DATAFACADE_HPP
#include "contractor/query_edge.hpp"
#include "customizer/edge_based_graph.hpp"
#include "extractor/edge_based_edge.hpp"
#include "engine/algorithm.hpp"
@@ -59,7 +60,7 @@ template <> class AlgorithmDataFacade<CH>
template <> class AlgorithmDataFacade<MLD>
{
public:
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
using EdgeData = customizer::EdgeBasedGraphEdgeData;
using EdgeRange = util::range<EdgeID>;
// search graph access
@@ -71,12 +72,22 @@ template <> class AlgorithmDataFacade<MLD>
virtual unsigned GetOutDegree(const NodeID n) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual EdgeWeight GetNodeWeight(const NodeID node) const = 0;
virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed
virtual EdgeDistance GetNodeDistance(const NodeID node) const = 0;
virtual bool IsForwardEdge(EdgeID edge) const = 0;
virtual bool IsBackwardEdge(EdgeID edge) const = 0;
virtual NodeID GetTarget(const EdgeID e) const = 0;
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
virtual const partitioner::CellStorageView &GetCellStorage() const = 0;
@@ -133,7 +133,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
using RTreeNode = SharedRTree::TreeNode;
extractor::ClassData exclude_mask;
std::string m_timestamp;
extractor::ProfileProperties *m_profile_properties;
extractor::Datasources *m_datasources;
@@ -283,13 +282,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return segment_data.GetReverseDatasources(id);
}
TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const override final
{
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
return m_turn_weight_penalties[id];
}
TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const override final
TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const override final
{
BOOST_ASSERT(m_turn_duration_penalties.size() > id);
return m_turn_duration_penalties[id];
@@ -313,12 +312,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(
input_coordinate, max_distance, approach);
input_coordinate, max_distance, approach, use_all_edges);
}
std::vector<PhantomNodeWithDistance>
@@ -326,12 +326,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
const float max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(
input_coordinate, max_distance, bearing, bearing_range, approach);
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
}
std::vector<PhantomNodeWithDistance>
@@ -385,23 +386,25 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, approach);
input_coordinate, approach, use_all_edges);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, approach);
input_coordinate, max_distance, approach, use_all_edges);
}
std::pair<PhantomNode, PhantomNode>
@@ -409,24 +412,26 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
const double max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range, approach);
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range,
const Approach approach) const override final
const Approach approach,
const bool use_all_edges) const override final
{
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range, approach);
input_coordinate, bearing, bearing_range, approach, use_all_edges);
}
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
@@ -622,7 +627,6 @@ class ContiguousInternalMemoryDataFacade<CH>
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, metric_name, exclude_index)
{
}
};
@@ -684,6 +688,36 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
return query_graph.GetOutDegree(n);
}
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return query_graph.GetAdjacentEdgeRange(node);
}
EdgeWeight GetNodeWeight(const NodeID node) const override final
{
return query_graph.GetNodeWeight(node);
}
EdgeDuration GetNodeDuration(const NodeID node) const override final
{
return query_graph.GetNodeDuration(node);
}
EdgeDistance GetNodeDistance(const NodeID node) const override final
{
return query_graph.GetNodeDistance(node);
}
bool IsForwardEdge(const NodeID node) const override final
{
return query_graph.IsForwardEdge(node);
}
bool IsBackwardEdge(const NodeID node) const override final
{
return query_graph.IsBackwardEdge(node);
}
NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); }
const EdgeData &GetEdgeData(const EdgeID e) const override final
@@ -691,11 +725,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
return query_graph.GetEdgeData(e);
}
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return query_graph.GetAdjacentEdgeRange(node);
}
EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final
{
return query_graph.GetBorderEdgeRange(level, node);
@@ -720,7 +749,6 @@ class ContiguousInternalMemoryDataFacade<MLD> final
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, metric_name, exclude_index)
{
}
};
+14 -9
View File
@@ -33,7 +33,6 @@
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/any_range.hpp>
#include <cstddef>
#include <string>
@@ -87,9 +86,9 @@ class BaseDataFacade
virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0;
virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0;
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const = 0;
virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const = 0;
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const = 0;
virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const = 0;
// Gets the weight values for each segment in an uncompressed geometry.
// Should always be 1 shorter than GetUncompressedGeometry
@@ -127,11 +126,13 @@ class BaseDataFacade
const float max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
@@ -158,22 +159,26 @@ class BaseDataFacade
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) 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 Approach approach) const = 0;
const Approach approach,
const bool use_all_edges) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range,
const Approach approach) const = 0;
const Approach approach,
const bool use_all_edges = false) const = 0;
virtual bool HasLaneData(const EdgeID id) const = 0;
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
@@ -10,6 +10,7 @@
#include <boost/iostreams/device/mapped_file.hpp>
#include <memory>
#include <string>
namespace osrm
{
@@ -24,8 +25,7 @@ namespace datafacade
class MMapMemoryAllocator : public ContiguousBlockAllocator
{
public:
explicit MMapMemoryAllocator(const storage::StorageConfig &config,
const boost::filesystem::path &memory_file);
explicit MMapMemoryAllocator(const storage::StorageConfig &config);
~MMapMemoryAllocator() override final;
// interface to give access to the datafacades
@@ -33,8 +33,8 @@ class MMapMemoryAllocator : public ContiguousBlockAllocator
private:
storage::SharedDataIndex index;
util::vector_view<char> mapped_memory;
boost::iostreams::mapped_file mapped_memory_file;
std::vector<boost::iostreams::mapped_file> mapped_memory_files;
std::string rtree_filename;
};
} // namespace datafacade
+2 -3
View File
@@ -32,9 +32,8 @@ class ExternalProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
public:
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
ExternalProvider(const storage::StorageConfig &config,
const boost::filesystem::path &memory_file)
: facade_factory(std::make_shared<datafacade::MMapMemoryAllocator>(config, memory_file))
ExternalProvider(const storage::StorageConfig &config)
: facade_factory(std::make_shared<datafacade::MMapMemoryAllocator>(config))
{
}
+9 -5
View File
@@ -63,12 +63,16 @@ template <typename Algorithm> class Engine final : public EngineInterface
<< "\" with algorithm " << routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name);
}
else if (!config.memory_file.empty())
else if (!config.memory_file.empty() || config.use_mmap)
{
util::Log(logDEBUG) << "Using memory mapped filed at " << config.memory_file
<< " with algorithm " << routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config,
config.memory_file);
if (!config.memory_file.empty())
{
util::Log(logWARNING)
<< "The 'memory_file' option is DEPRECATED - using direct mmaping instead";
}
util::Log(logDEBUG) << "Using direct memory mapping with algorithm "
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config);
}
else
{
+1
View File
@@ -89,6 +89,7 @@ struct EngineConfig final
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true;
boost::filesystem::path memory_file;
bool use_mmap = true;
Algorithm algorithm = Algorithm::CH;
std::string verbosity;
std::string dataset_name;
+81 -24
View File
@@ -13,6 +13,7 @@
#include <algorithm>
#include <cmath>
#include <iterator>
#include <memory>
#include <vector>
@@ -52,13 +53,15 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate](const CandidateSegment &segment) {
return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)),
CheckApproach(input_coordinate, segment, approach));
[this, approach, &input_coordinate, use_all_edges](const CandidateSegment &segment) {
return boolPairAnd(
boolPairAnd(HasValidEdge(segment, use_all_edges), CheckSegmentExclude(segment)),
CheckApproach(input_coordinate, segment, approach));
},
[this, max_distance, input_coordinate](const std::size_t,
const CandidateSegment &segment) {
@@ -75,15 +78,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const double max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate, bearing, bearing_range](
[this, approach, &input_coordinate, bearing, bearing_range, use_all_edges](
const CandidateSegment &segment) {
auto use_direction =
boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range),
boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)));
boolPairAnd(HasValidEdge(segment, use_all_edges),
CheckSegmentExclude(segment)));
use_direction =
boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach));
return use_direction;
@@ -200,18 +205,23 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
bool has_small_component = false;
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
const CandidateSegment &segment) {
[this,
approach,
&input_coordinate,
&has_big_component,
&has_small_component,
&use_all_edges](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);
const auto valid_edges = HasValidEdge(segment, use_all_edges);
const auto admissible_segments = CheckSegmentExclude(segment);
use_directions = boolPairAnd(use_directions, admissible_segments);
use_directions = boolPairAnd(use_directions, valid_edges);
@@ -246,19 +256,24 @@ 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 Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
bool has_small_component = false;
bool has_big_component = false;
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
const CandidateSegment &segment) {
[this,
approach,
&input_coordinate,
&has_big_component,
&has_small_component,
&use_all_edges](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);
const auto valid_edges = HasValidEdge(segment, use_all_edges);
const auto admissible_segments = CheckSegmentExclude(segment);
use_directions = boolPairAnd(use_directions, admissible_segments);
use_directions = boolPairAnd(use_directions, valid_edges);
@@ -293,7 +308,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -305,12 +321,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bearing,
bearing_range,
&has_big_component,
&has_small_component](const CandidateSegment &segment) {
&has_small_component,
&use_all_edges](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 admissible_segments = CheckSegmentExclude(segment);
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
if (use_segment)
{
@@ -351,7 +368,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const double max_distance,
const int bearing,
const int bearing_range,
const Approach approach) const
const Approach approach,
const bool use_all_edges) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -363,12 +381,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bearing,
bearing_range,
&has_big_component,
&has_small_component](const CandidateSegment &segment) {
&has_small_component,
&use_all_edges](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 admissible_segments = CheckSegmentExclude(segment);
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
if (use_segment)
{
@@ -447,6 +466,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const auto forward_durations = datafacade.GetUncompressedForwardDurations(geometry_id);
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
const auto forward_weight_offset =
std::accumulate(forward_weights.begin(),
forward_weights.begin() + data.fwd_segment_position,
@@ -457,12 +478,26 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
forward_durations.begin() + data.fwd_segment_position,
EdgeDuration{0});
EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
EdgeDuration forward_duration = forward_durations[data.fwd_segment_position];
EdgeDistance forward_distance_offset = 0;
// Sum up the distance from the start to the fwd_segment_position
for (auto current = forward_geometry.begin();
current < forward_geometry.begin() + data.fwd_segment_position;
++current)
{
forward_distance_offset += util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
}
BOOST_ASSERT(data.fwd_segment_position <
std::distance(forward_durations.begin(), forward_durations.end()));
EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
EdgeDuration forward_duration = forward_durations[data.fwd_segment_position];
EdgeDistance forward_distance = util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
point_on_segment);
const auto reverse_weight_offset =
std::accumulate(reverse_weights.begin(),
reverse_weights.end() - data.fwd_segment_position - 1,
@@ -473,10 +508,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_durations.end() - data.fwd_segment_position - 1,
EdgeDuration{0});
EdgeDistance reverse_distance_offset = 0;
// Sum up the distance from just after the fwd_segment_position to the end
for (auto current = forward_geometry.begin() + data.fwd_segment_position + 1;
current != std::prev(forward_geometry.end());
++current)
{
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
}
EdgeWeight reverse_weight =
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
EdgeDuration reverse_duration =
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1];
EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance(
point_on_segment,
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
ratio = std::min(1.0, std::max(0.0, ratio));
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
@@ -510,6 +559,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_weight,
forward_weight_offset,
reverse_weight_offset,
forward_distance,
reverse_distance,
forward_distance_offset,
reverse_distance_offset,
forward_duration,
reverse_duration,
forward_duration_offset,
@@ -595,7 +648,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
* which means that this edge is not currently traversible. If this is the case,
* then we shouldn't snap to this edge.
*/
std::pair<bool, bool> HasValidEdge(const CandidateSegment &segment) const
std::pair<bool, bool> HasValidEdge(const CandidateSegment &segment,
const bool use_all_edges = false) const
{
bool forward_edge_valid = false;
@@ -619,6 +673,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_edge_valid = data.reverse_segment_id.enabled;
}
forward_edge_valid = forward_edge_valid && (data.is_startpoint || use_all_edges);
reverse_edge_valid = reverse_edge_valid && (data.is_startpoint || use_all_edges);
return std::make_pair(forward_edge_valid, reverse_edge_valid);
}
+2 -2
View File
@@ -63,8 +63,8 @@ struct Hint
friend std::ostream &operator<<(std::ostream &, const Hint &);
};
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 92;
static_assert(sizeof(Hint) == 80 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 112;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
}
+42 -3
View File
@@ -47,10 +47,13 @@ struct PhantomNode
: forward_segment_id{SPECIAL_SEGMENTID, false},
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_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
forward_distance_offset(0), reverse_distance_offset(0),
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
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}, bearing(0)
{
}
@@ -78,6 +81,30 @@ struct PhantomNode
return reverse_duration + reverse_duration_offset;
}
// DO THIS FOR DISTANCE
EdgeDistance GetForwardDistance() const
{
// ..... <-- forward_distance
// .... <-- offset
// ......... <-- desired distance
// x <-- this is PhantomNode.location
// 0----1----2----3----4 <-- EdgeBasedGraph Node segments
BOOST_ASSERT(forward_segment_id.enabled);
return forward_distance + forward_distance_offset;
}
EdgeDistance GetReverseDistance() const
{
// .......... <-- reverse_distance
// ... <-- offset
// ............. <-- desired distance
// x <-- this is PhantomNode.location
// 0----1----2----3----4 <-- EdgeBasedGraph Node segments
BOOST_ASSERT(reverse_segment_id.enabled);
return reverse_distance + reverse_distance_offset;
}
bool IsBidirected() const { return forward_segment_id.enabled && reverse_segment_id.enabled; }
bool IsValid(const unsigned number_of_nodes) const
@@ -88,6 +115,8 @@ struct PhantomNode
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
((forward_duration != MAXIMAL_EDGE_DURATION) ||
(reverse_duration != MAXIMAL_EDGE_DURATION)) &&
((forward_distance != INVALID_EDGE_DISTANCE) ||
(reverse_distance != INVALID_EDGE_DISTANCE)) &&
(component.id != INVALID_COMPONENTID);
}
@@ -130,6 +159,10 @@ struct PhantomNode
EdgeWeight reverse_weight,
EdgeWeight forward_weight_offset,
EdgeWeight reverse_weight_offset,
EdgeDistance forward_distance,
EdgeDistance reverse_distance,
EdgeDistance forward_distance_offset,
EdgeDistance reverse_distance_offset,
EdgeWeight forward_duration,
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
@@ -144,7 +177,9 @@ struct PhantomNode
: forward_segment_id{other.forward_segment_id},
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_weight_offset{reverse_weight_offset}, forward_distance{forward_distance},
reverse_distance{reverse_distance}, forward_distance_offset{forward_distance_offset},
reverse_distance_offset{reverse_distance_offset}, forward_duration{forward_duration},
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
reverse_duration_offset{reverse_duration_offset},
component{component.id, component.is_tiny}, location{location},
@@ -162,13 +197,17 @@ struct PhantomNode
EdgeWeight reverse_weight;
EdgeWeight forward_weight_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight reverse_weight_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDistance forward_distance;
EdgeDistance reverse_distance;
EdgeDistance forward_distance_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDistance reverse_distance_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight forward_duration;
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
ComponentID component;
util::Coordinate location;
util::Coordinate location; // this is the coordinate of x
util::Coordinate input_location;
unsigned short fwd_segment_position;
// is phantom node valid to be used as source or target
@@ -180,7 +219,7 @@ struct PhantomNode
unsigned short bearing : 12;
};
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
static_assert(sizeof(PhantomNode) == 80, "PhantomNode has more padding then expected");
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
+15 -7
View File
@@ -138,7 +138,8 @@ class BasePlugin
std::vector<std::vector<PhantomNodeWithDistance>>
GetPhantomNodesInRange(const datafacade::BaseDataFacade &facade,
const api::BaseParameters &parameters,
const std::vector<double> radiuses) const
const std::vector<double> radiuses,
bool use_all_edges = false) const
{
std::vector<std::vector<PhantomNodeWithDistance>> phantom_nodes(
parameters.coordinates.size());
@@ -171,12 +172,13 @@ class BasePlugin
radiuses[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range,
approach);
approach,
use_all_edges);
}
else
{
phantom_nodes[i] = facade.NearestPhantomNodesInRange(
parameters.coordinates[i], radiuses[i], approach);
parameters.coordinates[i], radiuses[i], approach, use_all_edges);
}
}
@@ -268,6 +270,7 @@ class BasePlugin
const bool use_bearings = !parameters.bearings.empty();
const bool use_radiuses = !parameters.radiuses.empty();
const bool use_approaches = !parameters.approaches.empty();
const bool use_all_edges = parameters.snapping == api::BaseParameters::SnappingType::Any;
BOOST_ASSERT(parameters.IsValid());
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
@@ -294,7 +297,8 @@ class BasePlugin
*parameters.radiuses[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range,
approach);
approach,
use_all_edges);
}
else
{
@@ -303,7 +307,8 @@ class BasePlugin
parameters.coordinates[i],
parameters.bearings[i]->bearing,
parameters.bearings[i]->range,
approach);
approach,
use_all_edges);
}
}
else
@@ -312,13 +317,16 @@ class BasePlugin
{
phantom_node_pairs[i] =
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
parameters.coordinates[i], *parameters.radiuses[i], approach);
parameters.coordinates[i],
*parameters.radiuses[i],
approach,
use_all_edges);
}
else
{
phantom_node_pairs[i] =
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
parameters.coordinates[i], approach);
parameters.coordinates[i], approach, use_all_edges);
}
}
+23 -10
View File
@@ -30,10 +30,11 @@ class RoutingAlgorithmsInterface
virtual InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual std::vector<EdgeDuration>
virtual std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const = 0;
const std::vector<std::size_t> &target_indices,
const bool calculate_distance) const = 0;
virtual routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@@ -53,6 +54,7 @@ class RoutingAlgorithmsInterface
virtual bool HasDirectShortestPathSearch() const = 0;
virtual bool HasMapMatching() const = 0;
virtual bool HasManyToManySearch() const = 0;
virtual bool SupportsDistanceAnnotationType() const = 0;
virtual bool HasGetTileTurns() const = 0;
virtual bool HasExcludeFlags() const = 0;
virtual bool IsValid() const = 0;
@@ -81,10 +83,11 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
std::vector<EdgeDuration>
virtual std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const final override;
const std::vector<std::size_t> &target_indices,
const bool calculate_distance) const final override;
routing_algorithms::SubMatchingList
MapMatching(const routing_algorithms::CandidateLists &candidates_list,
@@ -124,6 +127,11 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
}
bool SupportsDistanceAnnotationType() const final override
{
return routing_algorithms::SupportsDistanceAnnotationType<Algorithm>::value;
}
bool HasGetTileTurns() const final override
{
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
@@ -184,10 +192,11 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatc
}
template <typename Algorithm>
std::vector<EdgeDuration> RoutingAlgorithms<Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &_source_indices,
const std::vector<std::size_t> &_target_indices) const
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
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 bool calculate_distance) const
{
BOOST_ASSERT(!phantom_nodes.empty());
@@ -205,8 +214,12 @@ std::vector<EdgeDuration> RoutingAlgorithms<Algorithm>::ManyToManySearch(
std::iota(target_indices.begin(), target_indices.end(), 0);
}
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, std::move(source_indices), std::move(target_indices));
return routing_algorithms::manyToManySearch(heaps,
*facade,
phantom_nodes,
std::move(source_indices),
std::move(target_indices),
calculate_distance);
}
template <typename Algorithm>
@@ -15,23 +15,46 @@ namespace engine
{
namespace routing_algorithms
{
namespace
{
struct NodeBucket
{
NodeID middle_node;
unsigned column_index; // a column in the weight/duration matrix
NodeID parent_node;
unsigned column_index : 31; // a column in the weight/duration matrix
unsigned from_clique_arc : 1;
EdgeWeight weight;
EdgeDuration duration;
EdgeDistance distance;
NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
: middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
NodeBucket(NodeID middle_node,
NodeID parent_node,
bool from_clique_arc,
unsigned column_index,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance)
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
from_clique_arc(from_clique_arc), weight(weight), duration(duration), distance(distance)
{
}
NodeBucket(NodeID middle_node,
NodeID parent_node,
unsigned column_index,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance)
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
from_clique_arc(false), weight(weight), duration(duration), distance(distance)
{
}
// partial order comparison
bool operator<(const NodeBucket &rhs) const { return middle_node < rhs.middle_node; }
bool operator<(const NodeBucket &rhs) const
{
return std::tie(middle_node, column_index) < std::tie(rhs.middle_node, rhs.column_index);
}
// functor for equal_range
struct Compare
@@ -46,15 +69,35 @@ struct NodeBucket
return lhs < rhs.middle_node;
}
};
// functor for equal_range
struct ColumnCompare
{
unsigned column_idx;
ColumnCompare(unsigned column_idx) : column_idx(column_idx){};
bool operator()(const NodeBucket &lhs, const NodeID &rhs) const // lowerbound
{
return std::tie(lhs.middle_node, lhs.column_index) < std::tie(rhs, column_idx);
}
bool operator()(const NodeID &lhs, const NodeBucket &rhs) const // upperbound
{
return std::tie(lhs, column_idx) < std::tie(rhs.middle_node, rhs.column_index);
}
};
};
}
} // namespace
template <typename Algorithm>
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>>
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices,
const bool calculate_distance);
} // namespace routing_algorithms
} // namespace engine
@@ -85,13 +85,17 @@ void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
{
heap.Insert(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
{phantom_node.forward_segment_id.id,
-phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance()});
}
if (phantom_node.IsValidReverseSource())
{
heap.Insert(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
{phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance()});
}
}
@@ -102,13 +106,17 @@ void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
{
heap.Insert(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
{phantom_node.forward_segment_id.id,
phantom_node.GetForwardDuration(),
phantom_node.GetForwardDistance()});
}
if (phantom_node.IsValidReverseTarget())
{
heap.Insert(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
{phantom_node.reverse_segment_id.id,
phantom_node.GetReverseDuration(),
phantom_node.GetReverseDistance()});
}
}
@@ -181,6 +189,7 @@ void annotatePath(const FacadeT &facade,
BOOST_ASSERT(datasource_vector.size() > 0);
BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size());
BOOST_ASSERT(duration_vector.size() + 1 == id_vector.size());
const bool is_first_segment = unpacked_path.empty();
const std::size_t start_index =
@@ -405,6 +414,22 @@ InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
return raw_route_data;
}
template <typename FacadeT> EdgeDistance computeEdgeDistance(const FacadeT &facade, NodeID node_id)
{
const auto geometry_index = facade.GetGeometryIndex(node_id);
EdgeDistance total_distance = 0.0;
auto geometry_range = facade.GetUncompressedForwardGeometry(geometry_index.id);
for (auto current = geometry_range.begin(); current < geometry_range.end() - 1; ++current)
{
total_distance += util::coordinate_calculation::fccApproximateDistance(
facade.GetCoordinateOfNode(*current), facade.GetCoordinateOfNode(*std::next(current)));
}
return total_distance;
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
@@ -186,9 +186,10 @@ void routingStep(const DataFacade<Algorithm> &facade,
}
template <bool UseDuration>
EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
std::tuple<EdgeWeight, EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
{
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
for (auto edge : facade.GetAdjacentEdgeRange(node))
{
const auto &data = facade.GetEdgeData(edge);
@@ -198,11 +199,15 @@ EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
if (to == node)
{
const auto value = UseDuration ? data.duration : data.weight;
loop_weight = std::min(loop_weight, value);
if (value < loop_weight)
{
loop_weight = value;
loop_distance = data.distance;
}
}
}
}
return loop_weight;
return std::make_tuple(loop_weight, loop_distance);
}
/**
@@ -288,6 +293,106 @@ void unpackPath(const DataFacade<Algorithm> &facade,
}
}
template <typename BidirectionalIterator>
EdgeDistance calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end)
{
// Make sure we have at least something to unpack
if (packed_path_begin == packed_path_end ||
std::distance(packed_path_begin, packed_path_end) <= 1)
return 0;
std::stack<std::tuple<NodeID, NodeID, bool>> recursion_stack;
std::stack<EdgeDistance> distance_stack;
// We have to push the path in reverse order onto the stack because it's LIFO.
for (auto current = std::prev(packed_path_end); current > packed_path_begin;
current = std::prev(current))
{
recursion_stack.emplace(*std::prev(current), *current, false);
}
std::tuple<NodeID, NodeID, bool> edge;
while (!recursion_stack.empty())
{
edge = recursion_stack.top();
recursion_stack.pop();
// Have we processed the edge before? tells us if we have values in the durations stack that
// we can add up
if (!std::get<2>(edge))
{ // haven't processed edge before, so process it in the body!
std::get<2>(edge) = true; // mark that this edge will now be processed
// Look for an edge on the forward CH graph (.forward)
EdgeID smaller_edge_id =
facade.FindSmallestEdge(std::get<0>(edge), std::get<1>(edge), [](const auto &data) {
return data.forward;
});
// If we didn't find one there, the we might be looking at a part of the path that
// was found using the backward search. Here, we flip the node order (.second,
// .first) and only consider edges with the `.backward` flag.
if (SPECIAL_EDGEID == smaller_edge_id)
{
smaller_edge_id =
facade.FindSmallestEdge(std::get<1>(edge),
std::get<0>(edge),
[](const auto &data) { return data.backward; });
}
// If we didn't find anything *still*, then something is broken and someone has
// called this function with bad values.
BOOST_ASSERT_MSG(smaller_edge_id != SPECIAL_EDGEID, "Invalid smaller edge ID");
const auto &data = facade.GetEdgeData(smaller_edge_id);
BOOST_ASSERT_MSG(data.weight != std::numeric_limits<EdgeWeight>::max(),
"edge weight invalid");
// If the edge is a shortcut, we need to add the two halfs to the stack.
if (data.shortcut)
{ // unpack
const NodeID middle_node_id = data.turn_id;
// Note the order here - we're adding these to a stack, so we
// want the first->middle to get visited before middle->second
recursion_stack.emplace(edge);
recursion_stack.emplace(middle_node_id, std::get<1>(edge), false);
recursion_stack.emplace(std::get<0>(edge), middle_node_id, false);
}
else
{
// compute the duration here and put it onto the duration stack using method
// similar to annotatePath but smaller
EdgeDistance distance = computeEdgeDistance(facade, std::get<0>(edge));
distance_stack.emplace(distance);
}
}
else
{ // the edge has already been processed. this means that there are enough values in the
// distances stack
BOOST_ASSERT_MSG(distance_stack.size() >= 2,
"There are not enough (at least 2) values on the distance stack");
EdgeDistance distance1 = distance_stack.top();
distance_stack.pop();
EdgeDistance distance2 = distance_stack.top();
distance_stack.pop();
EdgeDistance distance = distance1 + distance2;
distance_stack.emplace(distance);
}
}
EdgeDistance total_distance = 0;
while (!distance_stack.empty())
{
total_distance += distance_stack.top();
distance_stack.pop();
}
return total_distance;
}
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
@@ -340,6 +445,11 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHe
const NodeID middle_node_id,
std::vector<NodeID> &packed_path);
void retrievePackedPathFromSingleManyToManyHeap(
const SearchEngineData<Algorithm>::ManyToManyQueryHeap &search_heap,
const NodeID middle_node_id,
std::vector<NodeID> &packed_path);
// assumes that heaps are already setup correctly.
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
// Offsets.
@@ -54,7 +54,7 @@ inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return tr
// 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
// * check if the node cell is the same as the specified parent
template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &, NodeID, LevelID level, CellID)
{
@@ -65,6 +65,61 @@ inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
{
return cell == parent;
}
// Unrestricted search with a single phantom node (Args is const PhantomNode &):
// * use partition.GetQueryLevel to find the node query level
// * allow to traverse all cells
template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
const NodeID node,
const PhantomNode &phantom_node)
{
auto highest_diffrent_level = [&partition, node](const SegmentID &phantom_node) {
if (phantom_node.enabled)
return partition.GetHighestDifferentLevel(phantom_node.id, node);
return INVALID_LEVEL_ID;
};
const auto node_level = std::min(highest_diffrent_level(phantom_node.forward_segment_id),
highest_diffrent_level(phantom_node.reverse_segment_id));
return node_level;
}
// Unrestricted search with a single phantom node and a vector of phantom nodes:
// * use partition.GetQueryLevel to find the node query level
// * allow to traverse all cells
template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
NodeID node,
const std::vector<PhantomNode> &phantom_nodes,
const std::size_t phantom_index,
const std::vector<std::size_t> &phantom_indices)
{
auto min_level = [&partition, node](const PhantomNode &phantom_node) {
const auto &forward_segment = phantom_node.forward_segment_id;
const auto forward_level =
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
: INVALID_LEVEL_ID;
const auto &reverse_segment = phantom_node.reverse_segment_id;
const auto reverse_level =
reverse_segment.enabled ? partition.GetHighestDifferentLevel(node, reverse_segment.id)
: INVALID_LEVEL_ID;
return std::min(forward_level, reverse_level);
};
// Get minimum level over all phantoms of the highest different level with respect to node
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
auto result = min_level(phantom_nodes[phantom_index]);
for (const auto &index : phantom_indices)
{
result = std::min(result, min_level(phantom_nodes[index]));
}
return result;
}
}
// Heaps only record for each node its predecessor ("parent") on the shortest path.
@@ -74,6 +129,46 @@ inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
using PackedEdge = std::tuple</*from*/ NodeID, /*to*/ NodeID, /*from_clique_arc*/ bool>;
using PackedPath = std::vector<PackedEdge>;
template <bool DIRECTION, typename OutIter>
inline void retrievePackedPathFromSingleManyToManyHeap(
const SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap, const NodeID middle, OutIter out)
{
NodeID current = middle;
NodeID parent = heap.GetData(current).parent;
while (current != parent)
{
const auto &data = heap.GetData(current);
if (DIRECTION == FORWARD_DIRECTION)
{
*out = std::make_tuple(parent, current, data.from_clique_arc);
++out;
}
else if (DIRECTION == REVERSE_DIRECTION)
{
*out = std::make_tuple(current, parent, data.from_clique_arc);
++out;
}
current = parent;
parent = heap.GetData(parent).parent;
}
}
template <bool DIRECTION>
inline PackedPath retrievePackedPathFromSingleManyToManyHeap(
const SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap, const NodeID middle)
{
PackedPath packed_path;
retrievePackedPathFromSingleManyToManyHeap<DIRECTION>(
heap, middle, std::back_inserter(packed_path));
return packed_path;
}
template <bool DIRECTION, typename OutIter>
inline void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &heap,
const NodeID middle,
@@ -206,15 +301,22 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
for (const auto edge : facade.GetBorderEdgeRange(level, node))
{
const auto &edge_data = facade.GetEdgeData(edge);
if (DIRECTION == FORWARD_DIRECTION ? edge_data.forward : edge_data.backward)
if ((DIRECTION == FORWARD_DIRECTION) ? facade.IsForwardEdge(edge)
: facade.IsBackwardEdge(edge))
{
const NodeID to = facade.GetTarget(edge);
if (!facade.ExcludeNode(to) &&
checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
{
BOOST_ASSERT_MSG(edge_data.weight > 0, "edge_weight invalid");
const EdgeWeight to_weight = weight + edge_data.weight;
const auto node_weight =
facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? node : to);
const auto turn_penalty = facade.GetWeightPenaltyForEdgeID(edge_data.turn_id);
// TODO: BOOST_ASSERT(edge_data.weight == node_weight + turn_penalty);
const EdgeWeight to_weight = weight + node_weight + turn_penalty;
if (!forward_heap.WasInserted(to))
{
+13 -5
View File
@@ -30,7 +30,11 @@ struct HeapData
struct ManyToManyHeapData : HeapData
{
EdgeWeight duration;
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
EdgeDistance distance;
ManyToManyHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
: HeapData(p), duration(duration), distance(distance)
{
}
};
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
@@ -75,12 +79,16 @@ struct MultiLayerDijkstraHeapData
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
{
EdgeWeight duration;
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration)
: MultiLayerDijkstraHeapData(p), duration(duration)
EdgeDistance distance;
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
: MultiLayerDijkstraHeapData(p), duration(duration), distance(distance)
{
}
ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeWeight duration)
: MultiLayerDijkstraHeapData(p, from), duration(duration)
ManyToManyMultiLayerDijkstraHeapData(NodeID p,
bool from,
EdgeWeight duration,
EdgeDistance distance)
: MultiLayerDijkstraHeapData(p, from), duration(duration), distance(distance)
{
}
};
+12 -5
View File
@@ -15,20 +15,25 @@ struct EdgeBasedEdge
public:
struct EdgeData
{
EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {}
EdgeData()
: turn_id(0), weight(0), distance(0), duration(0), forward(false), backward(false)
{
}
EdgeData(const NodeID turn_id,
const EdgeWeight weight,
const EdgeDistance distance,
const EdgeWeight duration,
const bool forward,
const bool backward)
: turn_id(turn_id), weight(weight), duration(duration), forward(forward),
backward(backward)
: turn_id(turn_id), weight(weight), distance(distance), duration(duration),
forward(forward), backward(backward)
{
}
NodeID turn_id; // ID of the edge based node (node based edge)
EdgeWeight weight;
EdgeDistance distance;
EdgeWeight duration : 30;
std::uint32_t forward : 1;
std::uint32_t backward : 1;
@@ -43,6 +48,7 @@ struct EdgeBasedEdge
const NodeID edge_id,
const EdgeWeight weight,
const EdgeWeight duration,
const EdgeDistance distance,
const bool forward,
const bool backward);
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
@@ -53,7 +59,7 @@ struct EdgeBasedEdge
NodeID target;
EdgeData data;
};
static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
static_assert(sizeof(extractor::EdgeBasedEdge) == 24,
"Size of extractor::EdgeBasedEdge type is "
"bigger than expected. This will influence "
"memory consumption.");
@@ -67,9 +73,10 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID turn_id,
const EdgeWeight weight,
const EdgeWeight duration,
const EdgeDistance distance,
const bool forward,
const bool backward)
: source(source), target(target), data{turn_id, weight, duration, forward, backward}
: source(source), target(target), data{turn_id, weight, distance, duration, forward, backward}
{
}
@@ -89,8 +89,9 @@ class EdgeBasedGraphFactory
// The following get access functions destroy the content in the factory
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
void GetEdgeBasedNodeDurations(std::vector<EdgeWeight> &output_node_durations);
void GetEdgeBasedNodeDistances(std::vector<EdgeDistance> &output_node_distances);
std::uint32_t GetConnectivityChecksum() const;
std::uint64_t GetNumberOfEdgeBasedNodes() const;
@@ -110,13 +111,11 @@ class EdgeBasedGraphFactory
std::vector<ConditionalTurnPenalty>
IndexConditionals(std::vector<Conditional> &&conditionals) const;
//! maps index from m_edge_based_node_list to ture/false if the node is an entry point to the
//! graph
std::vector<bool> m_edge_based_node_is_startpoint;
//! node weights that indicate the length of the segment (node based) represented by the
//! edge-based node
std::vector<EdgeWeight> m_edge_based_node_weights;
std::vector<EdgeDuration> m_edge_based_node_durations;
std::vector<EdgeDistance> m_edge_based_node_distances;
//! list of edge based nodes (compressed segments)
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
@@ -22,7 +22,9 @@ 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())
fwd_segment_position(std::numeric_limits<unsigned short>::max() >>
1), // >> 1 because we've only got 15 bits
is_startpoint(false)
{
}
@@ -30,9 +32,10 @@ struct EdgeBasedNodeSegment
const SegmentID reverse_segment_id_,
NodeID u,
NodeID v,
unsigned short fwd_segment_position)
unsigned short fwd_segment_position,
bool is_startpoint_)
: forward_segment_id(forward_segment_id_), reverse_segment_id(reverse_segment_id_), u(u),
v(v), fwd_segment_position(fwd_segment_position)
v(v), fwd_segment_position(fwd_segment_position), is_startpoint(is_startpoint_)
{
BOOST_ASSERT(forward_segment_id.enabled || reverse_segment_id.enabled);
}
@@ -41,7 +44,8 @@ struct EdgeBasedNodeSegment
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
unsigned short fwd_segment_position : 15; // segment id in a compressed geometry
bool is_startpoint : 1;
};
}
}
+2 -2
View File
@@ -85,8 +85,9 @@ class Extractor
// output data
EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
std::vector<EdgeDuration> &edge_based_node_durations,
std::vector<EdgeDistance> &edge_based_node_distances,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
std::uint32_t &connectivity_checksum);
@@ -95,7 +96,6 @@ class Extractor
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<util::Coordinate> &coordinates);
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
+43 -5
View File
@@ -453,8 +453,8 @@ void writeNames(const boost::filesystem::path &path, const NameTableT &table)
serialization::write(writer, "/common/names", table);
}
template <typename NodeWeigtsVectorT>
void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVectorT &weights)
template <typename NodeWeightsVectorT>
void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeightsVectorT &weights)
{
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint};
@@ -462,14 +462,52 @@ void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVec
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
}
template <typename NodeWeigtsVectorT>
void writeEdgeBasedNodeWeights(const boost::filesystem::path &path,
const NodeWeigtsVectorT &weights)
template <typename NodeDistancesVectorT>
void readEdgeBasedNodeDistances(const boost::filesystem::path &path,
NodeDistancesVectorT &distances)
{
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint};
storage::serialization::read(reader, "/extractor/edge_based_node_distances", distances);
}
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT, typename NodeDistancesVectorT>
void writeEdgeBasedNodeWeightsDurationsDistances(const boost::filesystem::path &path,
const NodeWeightsVectorT &weights,
const NodeDurationsVectorT &durations,
const NodeDistancesVectorT &distances)
{
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
storage::tar::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights);
storage::serialization::write(writer, "/extractor/edge_based_node_durations", durations);
storage::serialization::write(writer, "/extractor/edge_based_node_distances", distances);
}
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT>
void readEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
NodeWeightsVectorT &weights,
NodeDurationsVectorT &durations)
{
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint};
storage::serialization::read(reader, "/extractor/edge_based_node_weights", weights);
storage::serialization::read(reader, "/extractor/edge_based_node_durations", durations);
}
template <typename NodeWeightsVectorT, typename NodeDurationsVectorT>
void writeEdgeBasedNodeWeightsDurations(const boost::filesystem::path &path,
const NodeWeightsVectorT &weights,
const NodeDurationsVectorT &durations)
{
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
storage::tar::FileWriter writer{path, fingerprint};
storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights);
storage::serialization::write(writer, "/extractor/edge_based_node_durations", durations);
}
template <typename RTreeT>
@@ -63,7 +63,7 @@ struct InternalExtractorEdge
WeightData weight_data,
DurationData duration_data,
util::Coordinate source_coordinate)
: result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
: result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
{
}
+18 -6
View File
@@ -97,6 +97,7 @@ struct NodeBasedEdge
NodeID target,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags);
@@ -107,6 +108,7 @@ struct NodeBasedEdge
NodeID target; // 32 4
EdgeWeight weight; // 32 4
EdgeDuration duration; // 32 4
EdgeDistance distance; // 32 4
GeometryID geometry_id; // 32 4
AnnotationID annotation_data; // 32 4
NodeBasedEdgeClassification flags; // 32 4
@@ -120,6 +122,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
OSMNodeID target,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags);
@@ -137,7 +140,8 @@ inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
}
inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), distance(0),
annotation_data(-1)
{
}
@@ -145,11 +149,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags)
: source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
annotation_data(annotation_data), flags(flags)
: source(source), target(target), weight(weight), duration(duration), distance(distance),
geometry_id(geometry_id), annotation_data(annotation_data), flags(flags)
{
}
@@ -175,11 +180,18 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id,
AnnotationID annotation_data,
NodeBasedEdgeClassification flags)
: NodeBasedEdge(
SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
: NodeBasedEdge(SPECIAL_NODEID,
SPECIAL_NODEID,
weight,
duration,
distance,
geometry_id,
annotation_data,
flags),
osm_source_id(std::move(source)), osm_target_id(std::move(target))
{
}
@@ -189,7 +201,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
{
}
static_assert(sizeof(extractor::NodeBasedEdge) == 28,
static_assert(sizeof(extractor::NodeBasedEdge) == 32,
"Size of extractor::NodeBasedEdge type is "
"bigger than expected. This will influence "
"memory consumption.");
+259 -5
View File
@@ -2,6 +2,7 @@
#define OSRM_BINDINGS_NODE_SUPPORT_HPP
#include "nodejs/json_v8_renderer.hpp"
#include "util/json_renderer.hpp"
#include "osrm/approach.hpp"
#include "osrm/bearing.hpp"
@@ -24,6 +25,7 @@
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
@@ -42,6 +44,13 @@ using match_parameters_ptr = std::unique_ptr<osrm::MatchParameters>;
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;
struct PluginParameters
{
bool renderJSONToBuffer = false;
};
using ObjectOrString = typename mapbox::util::variant<osrm::json::Object, std::string>;
template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);
template <> v8::Local<v8::Value> inline render(const std::string &result)
@@ -49,11 +58,21 @@ template <> v8::Local<v8::Value> inline render(const std::string &result)
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
}
template <> v8::Local<v8::Value> inline render(const osrm::json::Object &result)
template <> v8::Local<v8::Value> inline render(const ObjectOrString &result)
{
v8::Local<v8::Value> value;
renderToV8(value, result);
return value;
if (result.is<osrm::json::Object>())
{
// Convert osrm::json object tree into matching v8 object tree
v8::Local<v8::Value> value;
renderToV8(value, result.get<osrm::json::Object>());
return value;
}
else
{
// Return the string object as a node Buffer
return Nan::CopyBuffer(result.get<std::string>().data(), result.get<std::string>().size())
.ToLocalChecked();
}
}
inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
@@ -123,6 +142,10 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
if (shared_memory.IsEmpty())
return engine_config_ptr();
auto mmap_memory = params->Get(Nan::New("mmap_memory").ToLocalChecked());
if (mmap_memory.IsEmpty())
return engine_config_ptr();
if (!memory_file->IsUndefined())
{
if (path->IsUndefined())
@@ -171,6 +194,18 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
return engine_config_ptr();
}
}
if (!mmap_memory->IsUndefined())
{
if (mmap_memory->IsBoolean())
{
engine_config->use_mmap = Nan::To<bool>(mmap_memory).FromJust();
}
else
{
Nan::ThrowError("mmap_memory option must be a boolean");
return engine_config_ptr();
}
}
if (path->IsUndefined() && !engine_config->use_shared_memory)
{
@@ -657,6 +692,77 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
}
}
if (obj->Has(Nan::New("snapping").ToLocalChecked()))
{
v8::Local<v8::Value> snapping = obj->Get(Nan::New("snapping").ToLocalChecked());
if (snapping.IsEmpty())
return false;
if (!snapping->IsString())
{
Nan::ThrowError("Snapping must be a string: [default, any]");
return false;
}
const Nan::Utf8String snapping_utf8str(snapping);
std::string snapping_str{*snapping_utf8str, *snapping_utf8str + snapping_utf8str.length()};
if (snapping_str == "default")
{
params->snapping = osrm::RouteParameters::SnappingType::Default;
}
else if (snapping_str == "any")
{
params->snapping = osrm::RouteParameters::SnappingType::Any;
}
else
{
Nan::ThrowError("'snapping' param must be one of [default, any]");
return false;
}
}
if (obj->Has(Nan::New("acceleration_profile").ToLocalChecked()))
{
v8::Local<v8::Value> acceleration_profile =
obj->Get(Nan::New("acceleration_profile").ToLocalChecked());
if (acceleration_profile.IsEmpty())
return false;
if (!acceleration_profile->IsNumber() && !acceleration_profile->IsString())
{
Nan::ThrowError("acceleration_profile must be a decimal number or one of 'car', 'fast_car', 'slow_car', 'truck', or 'tractor_trailer'");
return false;
}
if (acceleration_profile->IsString()) {
std::string ssaf = *v8::String::Utf8Value(acceleration_profile);
// If they say 'yes', they get the default
if (ssaf == "car") {
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_CAR;
} else if (ssaf == "fast_car") {
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_FAST_CAR;
} else if (ssaf == "slow_car") {
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_SLOW_CAR;
} else if (ssaf == "truck") {
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_TRUCK;
} else if (ssaf == "tractor_trailer") {
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_TRACTOR_TRAILER;
} else {
Nan::ThrowError("acceleration_profile must be a decimal number or one of 'car', 'fast_car', 'slow_car', 'truck', or 'tractor_trailer'");
return false;
}
return true;
}
const auto value = acceleration_profile->NumberValue();
if (value < 0) {
Nan::ThrowError("acceleration_profile cannot be negative");
return false;
}
params->waypoint_acceleration_factor = value;
}
return true;
}
@@ -814,6 +920,50 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
return true;
}
inline PluginParameters
argumentsToPluginParameters(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
if (args.Length() < 3 || !args[1]->IsObject())
{
return {};
}
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[1]).ToLocalChecked();
if (obj->Has(Nan::New("format").ToLocalChecked()))
{
v8::Local<v8::Value> format = obj->Get(Nan::New("format").ToLocalChecked());
if (format.IsEmpty())
{
return {};
}
if (!format->IsString())
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
const Nan::Utf8String format_utf8str(format);
std::string format_str{*format_utf8str, *format_utf8str + format_utf8str.length()};
if (format_str == "object")
{
return {false};
}
else if (format_str == "json_buffer")
{
return {true};
}
else
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
}
return {};
}
inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
@@ -1064,6 +1214,110 @@ argumentsToTableParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
}
}
if (obj->Has(Nan::New("annotations").ToLocalChecked()))
{
v8::Local<v8::Value> annotations = obj->Get(Nan::New("annotations").ToLocalChecked());
if (annotations.IsEmpty())
return table_parameters_ptr();
if (!annotations->IsArray())
{
Nan::ThrowError(
"Annotations must an array containing 'duration' or 'distance', or both");
return table_parameters_ptr();
}
params->annotations = osrm::TableParameters::AnnotationsType::None;
v8::Local<v8::Array> annotations_array = v8::Local<v8::Array>::Cast(annotations);
for (std::size_t i = 0; i < annotations_array->Length(); ++i)
{
const Nan::Utf8String annotations_utf8str(annotations_array->Get(i));
std::string annotations_str{*annotations_utf8str,
*annotations_utf8str + annotations_utf8str.length()};
if (annotations_str == "duration")
{
params->annotations =
params->annotations | osrm::TableParameters::AnnotationsType::Duration;
}
else if (annotations_str == "distance")
{
params->annotations =
params->annotations | osrm::TableParameters::AnnotationsType::Distance;
}
else
{
Nan::ThrowError("this 'annotations' param is not supported");
return table_parameters_ptr();
}
}
}
if (obj->Has(Nan::New("fallback_speed").ToLocalChecked()))
{
auto fallback_speed = obj->Get(Nan::New("fallback_speed").ToLocalChecked());
if (!fallback_speed->IsNumber())
{
Nan::ThrowError("fallback_speed must be a number");
return table_parameters_ptr();
}
else if (fallback_speed->NumberValue() <= 0)
{
Nan::ThrowError("fallback_speed must be > 0");
return table_parameters_ptr();
}
params->fallback_speed = static_cast<double>(fallback_speed->NumberValue());
}
if (obj->Has(Nan::New("fallback_coordinate").ToLocalChecked()))
{
auto fallback_coordinate = obj->Get(Nan::New("fallback_coordinate").ToLocalChecked());
if (!fallback_coordinate->IsString())
{
Nan::ThrowError("fallback_coordinate must be a string: [input, snapped]");
return table_parameters_ptr();
}
std::string fallback_coordinate_str = *v8::String::Utf8Value(fallback_coordinate);
if (fallback_coordinate_str == "snapped")
{
params->fallback_coordinate_type =
osrm::TableParameters::FallbackCoordinateType::Snapped;
}
else if (fallback_coordinate_str == "input")
{
params->fallback_coordinate_type = osrm::TableParameters::FallbackCoordinateType::Input;
}
else
{
Nan::ThrowError("'fallback_coordinate' param must be one of [input, snapped]");
return table_parameters_ptr();
}
}
if (obj->Has(Nan::New("scale_factor").ToLocalChecked()))
{
auto scale_factor = obj->Get(Nan::New("scale_factor").ToLocalChecked());
if (!scale_factor->IsNumber())
{
Nan::ThrowError("scale_factor must be a number");
return table_parameters_ptr();
}
else if (scale_factor->NumberValue() <= 0)
{
Nan::ThrowError("scale_factor must be > 0");
return table_parameters_ptr();
}
params->scale_factor = static_cast<double>(scale_factor->NumberValue());
}
return params;
}
@@ -1317,6 +1571,6 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
return params;
}
} // ns node_osrm
} // namespace node_osrm
#endif
+33 -14
View File
@@ -75,28 +75,35 @@ template <storage::Ownership Ownership> class CellStorageImpl
// Implementation of the cell view. We need a template parameter here
// because we need to derive a read-only and read-write view from this.
template <typename WeightValueT, typename DurationValueT> class CellImpl
template <typename WeightValueT, typename DurationValueT, typename DistanceValueT>
class CellImpl
{
private:
using WeightPtrT = WeightValueT *;
using DurationPtrT = DurationValueT *;
using DistancePtrT = DistanceValueT *;
BoundarySize num_source_nodes;
BoundarySize num_destination_nodes;
WeightPtrT const weights;
DurationPtrT const durations;
DistancePtrT const distances;
const NodeID *const source_boundary;
const NodeID *const destination_boundary;
using RowIterator = WeightPtrT;
// Possibly replace with
// http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/strided.html
class ColumnIterator : public boost::iterator_facade<ColumnIterator,
WeightValueT,
template <typename ValuePtrT>
class ColumnIterator : public boost::iterator_facade<ColumnIterator<ValuePtrT>,
decltype(*std::declval<ValuePtrT>()),
boost::random_access_traversal_tag>
{
typedef boost::iterator_facade<ColumnIterator,
WeightValueT,
using ValueT = decltype(*std::declval<ValuePtrT>());
typedef boost::iterator_facade<ColumnIterator<ValueT>,
ValueT,
boost::random_access_traversal_tag>
base_t;
@@ -108,7 +115,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
explicit ColumnIterator() : current(nullptr), stride(1) {}
explicit ColumnIterator(WeightPtrT begin, std::size_t row_length)
explicit ColumnIterator(ValuePtrT begin, std::size_t row_length)
: current(begin), stride(row_length)
{
BOOST_ASSERT(begin != nullptr);
@@ -126,7 +133,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
}
friend class ::boost::iterator_core_access;
WeightPtrT current;
ValuePtrT current;
const std::size_t stride;
};
@@ -147,12 +154,13 @@ template <storage::Ownership Ownership> class CellStorageImpl
auto iter =
std::find(destination_boundary, destination_boundary + num_destination_nodes, node);
if (iter == destination_boundary + num_destination_nodes)
return boost::make_iterator_range(ColumnIterator{}, ColumnIterator{});
return boost::make_iterator_range(ColumnIterator<ValuePtr>{},
ColumnIterator<ValuePtr>{});
auto column = std::distance(destination_boundary, iter);
auto begin = ColumnIterator{ptr + column, num_destination_nodes};
auto end = ColumnIterator{ptr + column + num_source_nodes * num_destination_nodes,
num_destination_nodes};
auto begin = ColumnIterator<ValuePtr>{ptr + column, num_destination_nodes};
auto end = ColumnIterator<ValuePtr>{
ptr + column + num_source_nodes * num_destination_nodes, num_destination_nodes};
return boost::make_iterator_range(begin, end);
}
@@ -165,6 +173,10 @@ template <storage::Ownership Ownership> class CellStorageImpl
auto GetInDuration(NodeID node) const { return GetInRange(durations, node); }
auto GetInDistance(NodeID node) const { return GetInRange(distances, node); }
auto GetOutDistance(NodeID node) const { return GetOutRange(distances, node); }
auto GetSourceNodes() const
{
return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes);
@@ -179,17 +191,20 @@ template <storage::Ownership Ownership> class CellStorageImpl
CellImpl(const CellData &data,
WeightPtrT const all_weights,
DurationPtrT const all_durations,
DistancePtrT const all_distances,
const NodeID *const all_sources,
const NodeID *const all_destinations)
: num_source_nodes{data.num_source_nodes},
num_destination_nodes{data.num_destination_nodes},
weights{all_weights + data.value_offset},
durations{all_durations + data.value_offset},
distances{all_distances + data.value_offset},
source_boundary{all_sources + data.source_boundary_offset},
destination_boundary{all_destinations + data.destination_boundary_offset}
{
BOOST_ASSERT(all_weights != nullptr);
BOOST_ASSERT(all_durations != nullptr);
BOOST_ASSERT(all_distances != nullptr);
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr);
}
@@ -201,7 +216,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
const NodeID *const all_destinations)
: num_source_nodes{data.num_source_nodes},
num_destination_nodes{data.num_destination_nodes}, weights{nullptr},
durations{nullptr}, source_boundary{all_sources + data.source_boundary_offset},
durations{nullptr}, distances{nullptr},
source_boundary{all_sources + data.source_boundary_offset},
destination_boundary{all_destinations + data.destination_boundary_offset}
{
BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr);
@@ -212,8 +228,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
std::size_t LevelIDToIndex(LevelID level) const { return level - 1; }
public:
using Cell = CellImpl<EdgeWeight, EdgeDuration>;
using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration>;
using Cell = CellImpl<EdgeWeight, EdgeDuration, EdgeDistance>;
using ConstCell = CellImpl<const EdgeWeight, const EdgeDuration, const EdgeDistance>;
CellStorageImpl() {}
@@ -361,6 +377,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
metric.weights.resize(total_size + 1, INVALID_EDGE_WEIGHT);
metric.durations.resize(total_size + 1, MAXIMAL_EDGE_DURATION);
metric.distances.resize(total_size + 1, INVALID_EDGE_DISTANCE);
return metric;
}
@@ -388,6 +405,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
return ConstCell{cells[cell_index],
metric.weights.data(),
metric.durations.data(),
metric.distances.data(),
source_boundary.empty() ? nullptr : source_boundary.data(),
destination_boundary.empty() ? nullptr : destination_boundary.data()};
}
@@ -415,6 +433,7 @@ template <storage::Ownership Ownership> class CellStorageImpl
return Cell{cells[cell_index],
metric.weights.data(),
metric.durations.data(),
metric.distances.data(),
source_boundary.data(),
destination_boundary.data()};
}
@@ -43,6 +43,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
edge.data.turn_id,
std::max(edge.data.weight, 1),
edge.data.duration,
edge.data.distance,
edge.data.forward,
edge.data.backward);
@@ -51,6 +52,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
edge.data.turn_id,
std::max(edge.data.weight, 1),
edge.data.duration,
edge.data.distance,
edge.data.backward,
edge.data.forward);
}
+29 -35
View File
@@ -1,8 +1,6 @@
#ifndef OSRM_PARTITIONER_SERILIZATION_HPP
#define OSRM_PARTITIONER_SERILIZATION_HPP
#include "customizer/edge_based_graph.hpp"
#include "partitioner/serialization.hpp"
#include "storage/io.hpp"
@@ -14,39 +12,6 @@ namespace partitioner
namespace files
{
// reads .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void readGraph(const boost::filesystem::path &path,
MultiLevelGraphT &graph,
std::uint32_t &connectivity_checksum)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
storage::tar::FileReader reader{path, storage::tar::FileReader::VerifyFingerprint};
reader.ReadInto("/mld/connectivity_checksum", connectivity_checksum);
serialization::read(reader, "/mld/multilevelgraph", graph);
}
// writes .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void writeGraph(const boost::filesystem::path &path,
const MultiLevelGraphT &graph,
const std::uint32_t connectivity_checksum)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
storage::tar::FileWriter writer{path, storage::tar::FileWriter::GenerateFingerprint};
writer.WriteElementCount64("/mld/connectivity_checksum", 1);
writer.WriteFrom("/mld/connectivity_checksum", connectivity_checksum);
serialization::write(writer, "/mld/multilevelgraph", graph);
}
// read .osrm.partition file
template <typename MultiLevelPartitionT>
inline void readPartition(const boost::filesystem::path &path, MultiLevelPartitionT &mlp)
@@ -102,6 +67,35 @@ inline void writeCells(const boost::filesystem::path &path, CellStorageT &storag
serialization::write(writer, "/mld/cellstorage", storage);
}
// reads .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void readGraph(const boost::filesystem::path &path,
MultiLevelGraphT &graph,
std::uint32_t &connectivity_checksum)
{
static_assert(std::is_same<partitioner::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value, "");
storage::tar::FileReader reader{path, storage::tar::FileReader::VerifyFingerprint};
reader.ReadInto("/mld/connectivity_checksum", connectivity_checksum);
serialization::read(reader, "/mld/multilevelgraph", graph);
}
// writes .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void writeGraph(const boost::filesystem::path &path,
const MultiLevelGraphT &graph,
const std::uint32_t connectivity_checksum)
{
static_assert(std::is_same<partitioner::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value, "");
storage::tar::FileWriter writer{path, storage::tar::FileWriter::GenerateFingerprint};
writer.WriteElementCount64("/mld/connectivity_checksum", 1);
writer.WriteFrom("/mld/connectivity_checksum", connectivity_checksum);
serialization::write(writer, "/mld/multilevelgraph", graph);
}
}
}
}
+15
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_PARTITIONER_MULTI_LEVEL_GRAPH_HPP
#define OSRM_PARTITIONER_MULTI_LEVEL_GRAPH_HPP
#include "partitioner/edge_based_graph.hpp"
#include "partitioner/multi_level_partition.hpp"
#include "storage/shared_memory_ownership.hpp"
@@ -42,6 +43,8 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public:
using SuperT::SuperT;
// We limit each node to have 255 edges
// this is very generous, we could probably pack this
using EdgeOffset = std::uint8_t;
@@ -146,6 +149,14 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
return max_border_node_id;
}
auto data() && // rvalue ref-qualifier is a safety-belt
{
return std::make_tuple(std::move(SuperT::node_array),
std::move(SuperT::edge_array),
std::move(node_to_edge_offset),
connectivity_checksum);
}
private:
template <typename ContainerT>
auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
@@ -218,9 +229,13 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
protected:
Vector<EdgeOffset> node_to_edge_offset;
std::uint32_t connectivity_checksum;
};
using MultiLevelEdgeBasedGraph =
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
}
}
+1 -1
View File
@@ -16,7 +16,7 @@ namespace partitioner
struct PartitionerConfig final : storage::IOConfig
{
PartitionerConfig()
: IOConfig({".osrm", ".osrm.fileIndex", ".osrm.ebg_nodes"},
: IOConfig({".osrm", ".osrm.fileIndex", ".osrm.ebg_nodes", ".osrm.enw"},
{".osrm.hsgr", ".osrm.cnbg"},
{".osrm.ebg",
".osrm.cnbg",
-20
View File
@@ -19,26 +19,6 @@ namespace partitioner
namespace serialization
{
template <typename EdgeDataT, storage::Ownership Ownership>
inline void read(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::read(reader, name + "/node_array", graph.node_array);
storage::serialization::read(reader, name + "/edge_array", graph.edge_array);
storage::serialization::read(reader, name + "/node_to_edge_offset", graph.node_to_edge_offset);
}
template <typename EdgeDataT, storage::Ownership Ownership>
inline void write(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::write(writer, name + "/node_array", graph.node_array);
storage::serialization::write(writer, name + "/edge_array", graph.edge_array);
storage::serialization::write(writer, name + "/node_to_edge_offset", graph.node_to_edge_offset);
}
template <storage::Ownership Ownership>
inline void read(storage::tar::FileReader &reader,
const std::string &name,
+30 -2
View File
@@ -135,6 +135,19 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
},
qi::_1)];
acceleration_alpha_defaults_rule =
qi::lit("car")[qi::_val = ACCELERATION_ALPHA_CAR] |
qi::lit("fast_car")[qi::_val = ACCELERATION_ALPHA_FAST_CAR] |
qi::lit("slow_car")[qi::_val = ACCELERATION_ALPHA_SLOW_CAR] |
qi::lit("truck")[qi::_val = ACCELERATION_ALPHA_TRUCK] |
qi::lit("tractor_trailer")[qi::_val = ACCELERATION_ALPHA_TRACTOR_TRAILER];
acceleration_profile_rule =
qi::lit("acceleration_profile=") >
(qi::double_ | acceleration_alpha_defaults_rule)
[ph::bind(&engine::api::BaseParameters::waypoint_acceleration_factor, qi::_r1) =
qi::_1];
query_rule =
((location_rule % ';') | polyline_rule |
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
@@ -162,6 +175,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
(-approach_type %
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
snapping_type.add("default", engine::api::BaseParameters::SnappingType::Default)(
"any", engine::api::BaseParameters::SnappingType::Any);
snapping_rule =
qi::lit("snapping=") >
snapping_type[ph::bind(&engine::api::BaseParameters::snapping, qi::_r1) = qi::_1];
exclude_rule = qi::lit("exclude=") >
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
@@ -171,13 +191,17 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
| bearings_rule(qi::_r1) //
| generate_hints_rule(qi::_r1) //
| approach_rule(qi::_r1) //
| exclude_rule(qi::_r1);
| exclude_rule(qi::_r1) //
| snapping_rule(qi::_r1) //
| acceleration_profile_rule(qi::_r1);//
}
protected:
qi::rule<Iterator, Signature> base_rule;
qi::rule<Iterator, Signature> query_rule;
qi::real_parser<double, json_policy> double_;
private:
qi::rule<Iterator, Signature> bearings_rule;
qi::rule<Iterator, Signature> radiuses_rule;
@@ -186,6 +210,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
qi::rule<Iterator, Signature> generate_hints_rule;
qi::rule<Iterator, Signature> approach_rule;
qi::rule<Iterator, Signature> exclude_rule;
qi::rule<Iterator, Signature> acceleration_profile_rule;
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
@@ -195,9 +220,12 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
qi::rule<Iterator, unsigned char()> base64_char;
qi::rule<Iterator, std::string()> polyline_chars;
qi::rule<Iterator, double()> unlimited_rule;
qi::real_parser<double, json_policy> double_;
qi::rule<Iterator, Signature> snapping_rule;
qi::rule<Iterator, double()> acceleration_alpha_defaults_rule;
qi::symbols<char, engine::Approach> approach_type;
qi::symbols<char, engine::api::BaseParameters::SnappingType> snapping_type;
};
}
}
+48 -3
View File
@@ -22,11 +22,11 @@ namespace qi = boost::spirit::qi;
template <typename Iterator = std::string::iterator,
typename Signature = void(engine::api::TableParameters &)>
struct TableParametersGrammar final : public BaseParametersGrammar<Iterator, Signature>
struct TableParametersGrammar : public BaseParametersGrammar<Iterator, Signature>
{
using BaseGrammar = BaseParametersGrammar<Iterator, Signature>;
TableParametersGrammar() : BaseGrammar(root_rule)
TableParametersGrammar() : TableParametersGrammar(root_rule)
{
#ifdef BOOST_HAS_LONG_LONG
if (std::is_same<std::size_t, unsigned long long>::value)
@@ -48,18 +48,63 @@ struct TableParametersGrammar final : public BaseParametersGrammar<Iterator, Sig
(qi::lit("all") |
(size_t_ % ';')[ph::bind(&engine::api::TableParameters::sources, qi::_r1) = qi::_1]);
fallback_speed_rule =
qi::lit("fallback_speed=") >
(double_)[ph::bind(&engine::api::TableParameters::fallback_speed, qi::_r1) = qi::_1];
fallback_coordinate_type.add("input",
engine::api::TableParameters::FallbackCoordinateType::Input)(
"snapped", engine::api::TableParameters::FallbackCoordinateType::Snapped);
scale_factor_rule =
qi::lit("scale_factor=") >
(double_)[ph::bind(&engine::api::TableParameters::scale_factor, qi::_r1) = qi::_1];
table_rule = destinations_rule(qi::_r1) | sources_rule(qi::_r1);
root_rule = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") >
-('?' > (table_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&');
-('?' > (table_rule(qi::_r1) | base_rule(qi::_r1) | scale_factor_rule(qi::_r1) |
fallback_speed_rule(qi::_r1) |
(qi::lit("fallback_coordinate=") >
fallback_coordinate_type
[ph::bind(&engine::api::TableParameters::fallback_coordinate_type,
qi::_r1) = qi::_1])) %
'&');
}
TableParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
{
using AnnotationsType = engine::api::TableParameters::AnnotationsType;
annotations.add("duration", AnnotationsType::Duration)("distance",
AnnotationsType::Distance);
annotations_list = annotations[qi::_val |= qi::_1] % ',';
base_rule = BaseGrammar::base_rule(qi::_r1) |
(qi::lit("annotations=") >
annotations_list[ph::bind(&engine::api::TableParameters::annotations,
qi::_r1) = qi::_1]);
}
protected:
qi::rule<Iterator, Signature> base_rule;
private:
using json_policy = no_trailing_dot_policy<double, 'j', 's', 'o', 'n'>;
qi::rule<Iterator, Signature> root_rule;
qi::rule<Iterator, Signature> table_rule;
qi::rule<Iterator, Signature> sources_rule;
qi::rule<Iterator, Signature> destinations_rule;
qi::rule<Iterator, Signature> fallback_speed_rule;
qi::rule<Iterator, Signature> scale_factor_rule;
qi::rule<Iterator, std::size_t()> size_t_;
qi::symbols<char, engine::api::TableParameters::AnnotationsType> annotations;
qi::rule<Iterator, engine::api::TableParameters::AnnotationsType()> annotations_list;
qi::symbols<char, engine::api::TableParameters::FallbackCoordinateType>
fallback_coordinate_type;
qi::real_parser<double, json_policy> double_;
};
}
}
+8 -3
View File
@@ -16,10 +16,15 @@ struct Block
{
std::uint64_t num_entries;
std::uint64_t byte_size;
std::uint64_t offset;
Block() : num_entries(0), byte_size(0) {}
Block() : num_entries(0), byte_size(0), offset(0) {}
Block(std::uint64_t num_entries, std::uint64_t byte_size, std::uint64_t offset)
: num_entries(num_entries), byte_size(byte_size), offset(offset)
{
}
Block(std::uint64_t num_entries, std::uint64_t byte_size)
: num_entries(num_entries), byte_size(byte_size)
: num_entries(num_entries), byte_size(byte_size), offset(0)
{
}
};
@@ -29,7 +34,7 @@ using NamedBlock = std::tuple<std::string, Block>;
template <typename T> Block make_block(uint64_t num_entries)
{
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
return Block{num_entries, sizeof(T) * num_entries};
return Block{num_entries, sizeof(T) * num_entries, 0};
}
}
}
+40 -22
View File
@@ -9,6 +9,7 @@
#include "storage/shared_datatype.hpp"
#include "storage/tar.hpp"
#include <boost/assert.hpp>
#include <boost/function_output_iterator.hpp>
#include <boost/iterator/function_input_iterator.hpp>
@@ -30,22 +31,37 @@ namespace serialization
namespace detail
{
template <typename T, typename BlockT = unsigned char>
inline BlockT packBits(const T &data, std::size_t index, std::size_t count)
inline BlockT packBits(const T &data, std::size_t base_index, const std::size_t count)
{
static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool");
static_assert(std::is_unsigned<BlockT>::value, "BlockT must be unsigned type");
static_assert(std::is_integral<BlockT>::value, "BlockT must be an integral type");
static_assert(CHAR_BIT == 8, "Non-8-bit bytes not supported, sorry!");
BOOST_ASSERT(sizeof(BlockT) * CHAR_BIT >= count);
// Note: if this packing is changed, be sure to update vector_view<bool>
// as well, so that on-disk and in-memory layouts match.
BlockT value = 0;
for (std::size_t bit = 0; bit < count; ++bit, ++index)
value = (value << 1) | data[index];
for (std::size_t bit = 0; bit < count; ++bit)
{
value |= (data[base_index + bit] ? BlockT{1} : BlockT{0}) << bit;
}
return value;
}
template <typename T, typename BlockT = unsigned char>
inline void unpackBits(T &data, std::size_t index, std::size_t count, BlockT value)
inline void
unpackBits(T &data, const std::size_t base_index, const std::size_t count, const BlockT value)
{
static_assert(std::is_same<typename T::value_type, bool>::value, "value_type is not bool");
const BlockT mask = BlockT{1} << (count - 1);
for (std::size_t bit = 0; bit < count; value <<= 1, ++bit, ++index)
data[index] = value & mask;
static_assert(std::is_unsigned<BlockT>::value, "BlockT must be unsigned type");
static_assert(std::is_integral<BlockT>::value, "BlockT must be an integral type");
static_assert(CHAR_BIT == 8, "Non-8-bit bytes not supported, sorry!");
BOOST_ASSERT(sizeof(BlockT) * CHAR_BIT >= count);
for (std::size_t bit = 0; bit < count; ++bit)
{
data[base_index + bit] = value & (BlockT{1} << bit);
}
}
template <typename VectorT>
@@ -55,15 +71,16 @@ void readBoolVector(tar::FileReader &reader, const std::string &name, VectorT &d
data.resize(count);
std::uint64_t index = 0;
constexpr std::uint64_t WORD_BITS = CHAR_BIT * sizeof(std::uint64_t);
using BlockType = std::uint64_t;
constexpr std::uint64_t BLOCK_BITS = CHAR_BIT * sizeof(BlockType);
const auto decode = [&](const std::uint64_t block) {
auto read_size = std::min<std::size_t>(count - index, WORD_BITS);
unpackBits<VectorT, std::uint64_t>(data, index, read_size, block);
index += WORD_BITS;
const auto decode = [&](const BlockType block) {
auto read_size = std::min<std::size_t>(count - index, BLOCK_BITS);
unpackBits<VectorT, BlockType>(data, index, read_size, block);
index += BLOCK_BITS;
};
reader.ReadStreaming<std::uint64_t>(name, boost::make_function_output_iterator(decode));
reader.ReadStreaming<BlockType>(name, boost::make_function_output_iterator(decode));
}
template <typename VectorT>
@@ -73,19 +90,20 @@ void writeBoolVector(tar::FileWriter &writer, const std::string &name, const Vec
writer.WriteElementCount64(name, count);
std::uint64_t index = 0;
constexpr std::uint64_t WORD_BITS = CHAR_BIT * sizeof(std::uint64_t);
using BlockType = std::uint64_t;
constexpr std::uint64_t BLOCK_BITS = CHAR_BIT * sizeof(BlockType);
// FIXME on old boost version the function_input_iterator does not work with lambdas
// so we need to wrap it in a function here.
const std::function<std::uint64_t()> encode_function = [&]() -> std::uint64_t {
auto write_size = std::min<std::size_t>(count - index, WORD_BITS);
auto packed = packBits<VectorT, std::uint64_t>(data, index, write_size);
index += WORD_BITS;
const std::function<BlockType()> encode_function = [&]() -> BlockType {
auto write_size = std::min<std::size_t>(count - index, BLOCK_BITS);
auto packed = packBits<VectorT, BlockType>(data, index, write_size);
index += BLOCK_BITS;
return packed;
};
std::uint64_t number_of_blocks = (count + WORD_BITS - 1) / WORD_BITS;
writer.WriteStreaming<std::uint64_t>(
std::uint64_t number_of_blocks = (count + BLOCK_BITS - 1) / BLOCK_BITS;
writer.WriteStreaming<BlockType>(
name,
boost::make_function_input_iterator(encode_function, boost::infinite()),
number_of_blocks);
@@ -266,9 +284,9 @@ template <typename K, typename V> void write(io::BufferWriter &writer, const std
}
}
inline void read(io::BufferReader &reader, DataLayout &layout) { read(reader, layout.blocks); }
inline void read(io::BufferReader &reader, BaseDataLayout &layout) { read(reader, layout.blocks); }
inline void write(io::BufferWriter &writer, const DataLayout &layout)
inline void write(io::BufferWriter &writer, const BaseDataLayout &layout)
{
write(writer, layout.blocks);
}
+38 -19
View File
@@ -5,6 +5,7 @@
#include <boost/function_output_iterator.hpp>
#include <type_traits>
#include <unordered_map>
namespace osrm
@@ -19,8 +20,8 @@ class SharedDataIndex
public:
struct AllocatedRegion
{
char *memory_ptr;
DataLayout layout;
void *memory_ptr;
std::unique_ptr<BaseDataLayout> layout;
};
SharedDataIndex() = default;
@@ -29,10 +30,10 @@ class SharedDataIndex
// Build mapping from block name to region
for (auto index : util::irange<std::uint32_t>(0, regions.size()))
{
regions[index].layout.List("",
boost::make_function_output_iterator([&](const auto &name) {
block_to_region[name] = index;
}));
regions[index].layout->List("",
boost::make_function_output_iterator([&](const auto &name) {
block_to_region[name] = index;
}));
}
}
@@ -40,39 +41,57 @@ class SharedDataIndex
{
for (const auto &region : regions)
{
region.layout.List(name_prefix, out);
region.layout->List(name_prefix, out);
}
}
template <typename T> auto GetBlockPtr(const std::string &name) const
{
const auto index_iter = block_to_region.find(name);
const auto &region = regions[index_iter->second];
return region.layout.GetBlockPtr<T>(region.memory_ptr, name);
#if !defined(__GNUC__) || (__GNUC__ > 4)
// is_tivially_copyable only exists in GCC >=5
static_assert(std::is_trivially_copyable<T>::value,
"Block-based data must be a trivially copyable type");
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
#endif
const auto &region = GetBlockRegion(name);
return reinterpret_cast<T *>(region.layout->GetBlockPtr(region.memory_ptr, name));
}
template <typename T> auto GetBlockPtr(const std::string &name)
{
const auto index_iter = block_to_region.find(name);
const auto &region = regions[index_iter->second];
return region.layout.GetBlockPtr<T>(region.memory_ptr, name);
#if !defined(__GNUC__) || (__GNUC__ > 4)
// is_tivially_copyable only exists in GCC >=5
static_assert(std::is_trivially_copyable<T>::value,
"Block-based data must be a trivially copyable type");
static_assert(sizeof(T) % alignof(T) == 0, "aligned T* can't be used as an array pointer");
#endif
const auto &region = GetBlockRegion(name);
return reinterpret_cast<T *>(region.layout->GetBlockPtr(region.memory_ptr, name));
}
std::size_t GetBlockEntries(const std::string &name) const
{
const auto index_iter = block_to_region.find(name);
const auto &region = regions[index_iter->second];
return region.layout.GetBlockEntries(name);
const auto &region = GetBlockRegion(name);
return region.layout->GetBlockEntries(name);
}
std::size_t GetBlockSize(const std::string &name) const
{
const auto index_iter = block_to_region.find(name);
const auto &region = regions[index_iter->second];
return region.layout.GetBlockSize(name);
const auto &region = GetBlockRegion(name);
return region.layout->GetBlockSize(name);
}
private:
const AllocatedRegion &GetBlockRegion(const std::string &name) const
{
const auto index_iter = block_to_region.find(name);
if (index_iter == block_to_region.end())
{
throw util::exception("data block " + name + " not found " + SOURCE_REF);
}
return regions[index_iter->second];
}
std::vector<AllocatedRegion> regions;
std::unordered_map<std::string, std::uint32_t> block_to_region;
};
+76 -41
View File
@@ -20,13 +20,13 @@ namespace osrm
namespace storage
{
class DataLayout;
class BaseDataLayout;
namespace serialization
{
inline void read(io::BufferReader &reader, DataLayout &layout);
inline void read(io::BufferReader &reader, BaseDataLayout &layout);
inline void write(io::BufferWriter &writer, const DataLayout &layout);
}
inline void write(io::BufferWriter &writer, const BaseDataLayout &layout);
} // namespace serialization
namespace detail
{
@@ -52,46 +52,30 @@ inline std::string trimName(const std::string &name_prefix, const std::string &n
return name;
}
}
}
} // namespace detail
class DataLayout
class BaseDataLayout
{
public:
DataLayout() : blocks{} {}
virtual ~BaseDataLayout() = default;
inline void SetBlock(const std::string &name, Block block) { blocks[name] = std::move(block); }
inline uint64_t GetBlockEntries(const std::string &name) const
inline std::uint64_t GetBlockEntries(const std::string &name) const
{
return GetBlock(name).num_entries;
}
inline uint64_t GetBlockSize(const std::string &name) const { return GetBlock(name).byte_size; }
inline std::uint64_t GetBlockSize(const std::string &name) const
{
return GetBlock(name).byte_size;
}
inline bool HasBlock(const std::string &name) const
{
return blocks.find(name) != blocks.end();
}
inline uint64_t GetSizeOfLayout() const
{
uint64_t result = 0;
for (const auto &name_and_block : blocks)
{
result += GetBlockSize(name_and_block.first) + BLOCK_ALIGNMENT;
}
return result;
}
template <typename T> inline T *GetBlockPtr(char *shared_memory, const std::string &name) const
{
static_assert(BLOCK_ALIGNMENT % std::alignment_of<T>::value == 0,
"Datatype does not fit alignment constraints.");
char *ptr = (char *)GetAlignedBlockPtr(shared_memory, name);
return (T *)ptr;
}
// Depending on the name prefix this function either lists all blocks with the same prefix
// or all entries in the sub-directory.
// '/ch/edge' -> '/ch/edge_filter/0/blocks', '/ch/edge_filter/1/blocks'
@@ -115,10 +99,10 @@ class DataLayout
}
}
private:
friend void serialization::read(io::BufferReader &reader, DataLayout &layout);
friend void serialization::write(io::BufferWriter &writer, const DataLayout &layout);
virtual inline void *GetBlockPtr(void *base_ptr, const std::string &name) const = 0;
virtual inline std::uint64_t GetSizeOfLayout() const = 0;
protected:
const Block &GetBlock(const std::string &name) const
{
auto iter = blocks.find(name);
@@ -130,10 +114,42 @@ class DataLayout
return iter->second;
}
friend void serialization::read(io::BufferReader &reader, BaseDataLayout &layout);
friend void serialization::write(io::BufferWriter &writer, const BaseDataLayout &layout);
std::map<std::string, Block> blocks;
};
class ContiguousDataLayout final : public BaseDataLayout
{
public:
inline std::uint64_t GetSizeOfLayout() const override final
{
std::uint64_t result = 0;
for (const auto &name_and_block : blocks)
{
result += GetBlockSize(name_and_block.first) + BLOCK_ALIGNMENT;
}
return result;
}
inline void *GetBlockPtr(void *base_ptr, const std::string &name) const override final
{
// TODO: re-enable this alignment checking somehow
// static_assert(BLOCK_ALIGNMENT % std::alignment_of<T>::value == 0,
// "Datatype does not fit alignment constraints.");
return GetAlignedBlockPtr(base_ptr, name);
}
private:
friend void serialization::read(io::BufferReader &reader, BaseDataLayout &layout);
friend void serialization::write(io::BufferWriter &writer, const BaseDataLayout &layout);
// Fit aligned storage in buffer to 64 bytes to conform with AVX 512 types
inline void *align(void *&ptr) const noexcept
{
const auto intptr = reinterpret_cast<uintptr_t>(ptr);
const auto intptr = reinterpret_cast<std::uintptr_t>(ptr);
const auto aligned = (intptr - 1u + BLOCK_ALIGNMENT) & -BLOCK_ALIGNMENT;
return ptr = reinterpret_cast<void *>(aligned);
}
@@ -157,7 +173,27 @@ class DataLayout
}
static constexpr std::size_t BLOCK_ALIGNMENT = 64;
std::map<std::string, Block> blocks;
};
class TarDataLayout final : public BaseDataLayout
{
public:
inline std::uint64_t GetSizeOfLayout() const override final
{
std::uint64_t result = 0;
for (const auto &name_and_block : blocks)
{
result += GetBlockSize(name_and_block.first);
}
return result;
}
inline void *GetBlockPtr(void *base_ptr, const std::string &name) const override final
{
auto offset = GetBlock(name).offset;
const auto offset_address = reinterpret_cast<std::uintptr_t>(base_ptr) + offset;
return reinterpret_cast<void *>(offset_address);
}
};
struct SharedRegion
@@ -165,7 +201,7 @@ struct SharedRegion
static constexpr const int MAX_NAME_LENGTH = 254;
SharedRegion() : name{0}, timestamp{0} {}
SharedRegion(const std::string &name_, std::uint64_t timestamp, std::uint8_t shm_key)
SharedRegion(const std::string &name_, std::uint64_t timestamp, std::uint16_t shm_key)
: name{0}, timestamp{timestamp}, shm_key{shm_key}
{
std::copy_n(name_.begin(), std::min<std::size_t>(MAX_NAME_LENGTH, name_.size()), name);
@@ -175,14 +211,14 @@ struct SharedRegion
char name[MAX_NAME_LENGTH + 1];
std::uint64_t timestamp;
std::uint8_t shm_key;
std::uint16_t shm_key;
};
// Keeps a list of all shared regions in a fixed-sized struct
// for fast access and deserialization.
struct SharedRegionRegister
{
using RegionID = std::uint8_t;
using RegionID = std::uint16_t;
static constexpr const RegionID INVALID_REGION_ID = std::numeric_limits<RegionID>::max();
using ShmKey = decltype(SharedRegion::shm_key);
@@ -250,12 +286,11 @@ struct SharedRegionRegister
void ReleaseKey(ShmKey key) { shm_key_in_use[key] = false; }
static constexpr const std::uint8_t MAX_SHARED_REGIONS =
std::numeric_limits<RegionID>::max() - 1;
static constexpr const std::size_t MAX_SHARED_REGIONS = 512;
static_assert(MAX_SHARED_REGIONS < std::numeric_limits<RegionID>::max(),
"Number of shared memory regions needs to be less than the region id size.");
static constexpr const std::uint8_t MAX_SHM_KEYS = std::numeric_limits<std::uint8_t>::max() - 1;
static constexpr const std::size_t MAX_SHM_KEYS = MAX_SHARED_REGIONS * 2;
static constexpr const char *name = "osrm-region";
@@ -263,7 +298,7 @@ struct SharedRegionRegister
std::array<SharedRegion, MAX_SHARED_REGIONS> regions;
std::array<bool, MAX_SHM_KEYS> shm_key_in_use;
};
}
}
} // namespace storage
} // namespace osrm
#endif /* SHARED_DATA_TYPE_HPP */
+10 -9
View File
@@ -34,10 +34,10 @@ namespace storage
struct OSRMLockFile
{
boost::filesystem::path operator()()
template <typename IdentifierT> boost::filesystem::path operator()(const IdentifierT &id)
{
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
boost::filesystem::path lock_file = temp_dir / ("osrm-" + std::to_string(id) + ".lock");
return lock_file;
}
};
@@ -93,7 +93,7 @@ class SharedMemory
try
{
OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
boost::interprocess::xsi_key key(lock_file(id).string().c_str(), id);
result = RegionExists(key);
}
catch (...)
@@ -106,7 +106,7 @@ class SharedMemory
template <typename IdentifierT> static bool Remove(const IdentifierT id)
{
OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
boost::interprocess::xsi_key key(lock_file(id).string().c_str(), id);
return Remove(key);
}
@@ -287,10 +287,11 @@ class SharedMemory
template <typename IdentifierT, typename LockFileT = OSRMLockFile>
std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint64_t size = 0)
{
static_assert(sizeof(id) == sizeof(std::uint16_t), "Key type is not 16 bits");
try
{
LockFileT lock_file;
if (!boost::filesystem::exists(lock_file()))
if (!boost::filesystem::exists(lock_file(id)))
{
if (0 == size)
{
@@ -298,10 +299,10 @@ std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint
}
else
{
boost::filesystem::ofstream ofs(lock_file());
boost::filesystem::ofstream ofs(lock_file(id));
}
}
return std::make_unique<SharedMemory>(lock_file(), id, size);
return std::make_unique<SharedMemory>(lock_file(id), id, size);
}
catch (const boost::interprocess::interprocess_exception &e)
{
@@ -310,7 +311,7 @@ std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint
throw util::exception(e.what() + SOURCE_REF);
}
}
}
}
} // namespace storage
} // namespace osrm
#endif // SHARED_MEMORY_HPP
+19 -4
View File
@@ -33,7 +33,7 @@ template <class Lock> class InvertedLock
InvertedLock(Lock &lock) : lock(lock) { lock.unlock(); }
~InvertedLock() { lock.lock(); }
};
}
} // namespace
// The shared monitor implementation based on a semaphore and mutex
template <typename Data> struct SharedMonitor
@@ -117,6 +117,19 @@ template <typename Data> struct SharedMonitor
#endif
static void remove() { bi::shared_memory_object::remove(Data::name); }
static bool exists()
{
try
{
bi::shared_memory_object shmem_open =
bi::shared_memory_object(bi::open_only, Data::name, bi::read_only);
}
catch (const bi::interprocess_exception &exception)
{
return false;
}
return true;
}
private:
#if USE_BOOST_INTERPROCESS_CONDITION
@@ -133,7 +146,9 @@ template <typename Data> struct SharedMonitor
// like two-turnstile reusable barrier or boost/interprocess/sync/spin/condition.hpp
// fail if a waiter is killed.
static constexpr int buffer_size = 256;
// Buffer size needs to be large enough to hold all the semaphores for every
// listener you want to support.
static constexpr int buffer_size = 4096 * 4;
struct InternalData
{
@@ -219,8 +234,8 @@ template <typename Data> struct SharedMonitor
bi::shared_memory_object shmem;
bi::mapped_region region;
};
}
}
} // namespace storage
} // namespace osrm
#undef USE_BOOST_INTERPROCESS_CONDITION
+9 -3
View File
@@ -35,22 +35,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/filesystem/path.hpp>
#include <string>
#include <vector>
namespace osrm
{
namespace storage
{
void populateLayoutFromFile(const boost::filesystem::path &path, storage::BaseDataLayout &layout);
class Storage
{
public:
Storage(StorageConfig config);
int Run(int max_wait, const std::string &name, bool only_metric);
void PopulateStaticLayout(DataLayout &layout);
void PopulateUpdatableLayout(DataLayout &layout);
void PopulateStaticData(const SharedDataIndex &index);
void PopulateUpdatableData(const SharedDataIndex &index);
void PopulateLayout(storage::BaseDataLayout &layout,
const std::vector<std::pair<bool, boost::filesystem::path>> &files);
std::string PopulateLayoutWithRTree(storage::BaseDataLayout &layout);
std::vector<std::pair<bool, boost::filesystem::path>> GetUpdatableFiles();
std::vector<std::pair<bool, boost::filesystem::path>> GetStaticFiles();
private:
StorageConfig config;
+2 -4
View File
@@ -29,10 +29,8 @@ checkMTarError(int error_code, const boost::filesystem::path &filepath, const st
case MTAR_ESUCCESS:
return;
case MTAR_EFAILURE:
throw util::RuntimeError(filepath.string() + " : " + name,
ErrorCode::FileIOError,
SOURCE_REF,
std::strerror(errno));
throw util::RuntimeError(
filepath.string() + " : " + name, ErrorCode::FileIOError, SOURCE_REF);
case MTAR_EOPENFAIL:
throw util::RuntimeError(filepath.string() + " : " + name,
ErrorCode::FileOpenError,
+21 -5
View File
@@ -294,11 +294,14 @@ inline auto make_filtered_cell_metric_view(const SharedDataIndex &index,
auto prefix = name + "/exclude/" + std::to_string(exclude_index);
auto weights_block_id = prefix + "/weights";
auto durations_block_id = prefix + "/durations";
auto distances_block_id = prefix + "/distances";
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
return customizer::CellMetricView{std::move(weights), std::move(durations)};
return customizer::CellMetricView{
std::move(weights), std::move(durations), std::move(distances)};
}
inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name)
@@ -311,12 +314,14 @@ inline auto make_cell_metric_view(const SharedDataIndex &index, const std::strin
{
auto weights_block_id = prefix + "/weights";
auto durations_block_id = prefix + "/durations";
auto distances_block_id = prefix + "/distances";
auto weights = make_vector_view<EdgeWeight>(index, weights_block_id);
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
cell_metric_excludes.push_back(
customizer::CellMetricView{std::move(weights), std::move(durations)});
cell_metric_excludes.push_back(customizer::CellMetricView{
std::move(weights), std::move(durations), std::move(distances)});
}
return cell_metric_excludes;
@@ -330,9 +335,20 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std:
index, name + "/edge_array");
auto node_to_offset = make_vector_view<customizer::MultiLevelEdgeBasedGraphView::EdgeOffset>(
index, name + "/node_to_edge_offset");
auto node_weights = make_vector_view<EdgeWeight>(index, name + "/node_weights");
auto node_durations = make_vector_view<EdgeDuration>(index, name + "/node_durations");
auto node_distances = make_vector_view<EdgeDistance>(index, name + "/node_distances");
auto is_forward_edge = make_vector_view<bool>(index, name + "/is_forward_edge");
auto is_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge");
return customizer::MultiLevelEdgeBasedGraphView(
std::move(node_list), std::move(edge_list), std::move(node_to_offset));
return customizer::MultiLevelEdgeBasedGraphView(std::move(node_list),
std::move(edge_list),
std::move(node_to_offset),
std::move(node_weights),
std::move(node_durations),
std::move(node_distances),
std::move(is_forward_edge),
std::move(is_backward_edge));
}
inline auto make_maneuver_overrides_views(const SharedDataIndex &index, const std::string &name)
+12 -4
View File
@@ -17,15 +17,23 @@ class Updater
public:
Updater(UpdaterConfig config_) : config(std::move(config_)) {}
using NumNodesAndEdges =
std::tuple<EdgeID, std::vector<extractor::EdgeBasedEdge>, std::uint32_t>;
NumNodesAndEdges LoadAndUpdateEdgeExpandedGraph() const;
EdgeID
LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights,
std::uint32_t &connectivity_checksum) const;
EdgeID LoadAndUpdateEdgeExpandedGraph(
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights,
std::vector<EdgeDuration> &node_durations, // TODO: remove when optional
std::uint32_t &connectivity_checksum) const;
EdgeID LoadAndUpdateEdgeExpandedGraph(
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
std::vector<EdgeWeight> &node_weights,
std::vector<EdgeDuration> &node_durations, // TODO: remove when optional
std::vector<EdgeDistance> &node_distances, // TODO: remove when optional
std::uint32_t &connectivity_checksum) const;
private:
UpdaterConfig config;
};
+2 -1
View File
@@ -53,7 +53,8 @@ struct UpdaterConfig final : storage::IOConfig
".osrm.geometry",
".osrm.fileIndex",
".osrm.properties",
".osrm.restrictions"},
".osrm.restrictions",
".osrm.enw"},
{},
{".osrm.datasource_names"}),
valid_now(0)
+3
View File
@@ -43,6 +43,9 @@ inline double radToDeg(const double radian)
//! Takes the squared euclidean distance of the input coordinates. Does not return meters!
std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs);
double fccApproximateDistance(const Coordinate first_coordinate,
const Coordinate second_coordinate);
double haversineDistance(const Coordinate first_coordinate, const Coordinate second_coordinate);
double greatCircleDistance(const Coordinate first_coordinate, const Coordinate second_coordinate);

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