Compare commits

..

798 Commits

Author SHA1 Message Date
Dennis Luxen d42772a261 bump variant dependency 2014-10-20 16:02:26 +02:00
Dennis Luxen c1136099a9 fix link order to make symbol available in libosrm 2014-10-20 13:26:51 +02:00
Dennis Luxen 06f8a975c0 prevent double compile of dependent compile units 2014-10-20 13:04:44 +02:00
Dennis Luxen c8cd8775f6 Merge branch 'develop' of github.com:Project-OSRM/osrm-backend into develop 2014-10-20 12:54:12 +02:00
Dennis Luxen f9900c91bd Merge branch 'alex85k-mingw-support' into develop 2014-10-20 12:53:09 +02:00
Dennis Luxen accaf6e77e Merge branch 'mingw-support' of https://github.com/alex85k/Project-OSRM into alex85k-mingw-support 2014-10-20 12:52:45 +02:00
Dennis Luxen 8490e297a9 add todo marker 2014-10-20 11:39:23 +02:00
Dennis Luxen 6d3a4b5f6c deactivate inactive includes 2014-10-20 11:25:50 +02:00
Dennis Luxen 1f36206f45 replace boost::get<> call with proper function call to mapbox::variant 2014-10-20 11:25:34 +02:00
Dennis Luxen 952e10936c rename variable 2014-10-20 10:58:45 +02:00
Dennis Luxen 2b3093a687 reformat file according to guidelines 2014-10-20 10:32:57 +02:00
Dennis Luxen d7e25772b0 remove left-over boost::noncopyable and replace by c++11 ctor deletes. 2014-10-20 10:20:58 +02:00
Dennis Luxen c66c9b0353 Merge branch 'alex85k-warning-fix' into develop 2014-10-20 10:13:36 +02:00
alex85k bbde0d75da remove unused variable in Windows code 2014-10-18 19:19:26 +06:00
alex85k c3aec4f627 do not use gcc-ar for MinGW 4.9 2014-10-18 19:13:46 +06:00
alex85k 113852eed4 use math defines on Mingw 2014-10-18 18:47:17 +06:00
Dennis Luxen 6b9b2c1468 Merge pull request #1231 from Project-OSRM/testing/smarter_caching
smarter caching of test files
2014-10-17 15:59:08 +02:00
Emil Tin 2c87b295ff add raketask for clearing test cache files 2014-10-17 15:13:06 +02:00
Emil Tin 93767d68f8 remove debug output 2014-10-17 15:07:56 +02:00
Emil Tin cc3646ca16 fix tests that use {base} expansion 2014-10-17 15:07:56 +02:00
Emil Tin 48333f73d5 rename rather than copy then when possible 2014-10-17 15:07:56 +02:00
Emil Tin 1f4241a63d smarter caching of test files 2014-10-17 15:07:56 +02:00
Dennis Luxen 8eccfaa034 fix a number of implicit conversions 2014-10-17 14:19:33 +02:00
Dennis Luxen 438d1af12a fix implicit type conversios 2014-10-17 13:03:49 +02:00
Dennis Luxen 5be6ef380f replace shared_ptr instances to make intent of single owner more obvious 2014-10-17 12:35:53 +02:00
Dennis Luxen 76419ed2fc remove unneeded member variable 2014-10-17 12:32:18 +02:00
Dennis Luxen 4684921e51 fix implicit casts 2014-10-17 12:31:02 +02:00
Dennis Luxen edd8caa2bf compile Fingerprint only once 2014-10-17 12:30:11 +02:00
Dennis Luxen cb5575ae89 remove compile-time time stamps, rely on git SHA instead, fixes #1229 2014-10-17 10:57:00 +02:00
Dennis Luxen 42e726dec5 reformat according to styleguide 2014-10-16 17:49:10 +02:00
Dennis Luxen e3d33aa171 add const keywords where possible 2014-10-16 17:43:05 +02:00
Dennis Luxen f2ceeb35da fixes issue #1167, odd routing instructions
- the turn angle for compressed edges was not computed from the uncompressed geometry
- for a given turn (a,b,c) the last compressed node for edge (a,b) and the first packed node for (b,c) is returned
- adds a cucumber test to guard against regression
2014-10-16 15:58:58 +02:00
Dennis Luxen 577cf5ddc4 retrieve first and last nodes of a compressed segment 2014-10-16 15:42:33 +02:00
Dennis Luxen 91ced39233 replace shared_ptrs with std::unique_ptr<> in Prepare 2014-10-16 12:10:43 +02:00
Dennis Luxen 4b6cb0b8b8 replace raw ptrs with std::unique_ptr<> in Prepare 2014-10-16 12:10:12 +02:00
Dennis Luxen fb81302382 fix typo: Lunux->Linux 2014-10-16 11:52:16 +02:00
Dennis Luxen dfc81f65ee Merge pull request #889 from Project-OSRM/experimental/cuke_datastore
use osrm-datastore for testing, keep osrm-routed runnning
2014-10-15 15:41:38 +02:00
Dennis Luxen 909db4c861 replace inline with anonynmous namespace to avoid duplicate symbols during linking 2014-10-15 15:15:40 +02:00
Dennis Luxen 4277eed1b6 Revert "remove whitespace from package description"
This reverts commit 6f5703a5fe.
2014-10-15 13:21:42 +02:00
Dennis Luxen 6f5703a5fe remove whitespace from package description 2014-10-15 12:55:40 +02:00
Dennis Luxen f7469f298d add a tail to the oneway circle to avoid edge cases 2014-10-15 11:33:43 +02:00
Dennis Luxen b29d5df7a2 simplify conditional operation, remove useless parantheses 2014-10-15 10:43:58 +02:00
Dennis Luxen 549ba65861 catch a number of uncaught exceptions 2014-10-15 10:23:48 +02:00
Dennis Luxen a9d99cbe54 fix inverted logic 2014-10-14 18:03:24 +02:00
Emil Tin 8438024370 avoid unnessecary process check 2014-10-14 16:05:06 +02:00
Dennis Luxen e6a00ddcfd rethrow exception, refactor default block in fully covered switch statement 2014-10-14 15:59:18 +02:00
Emil Tin 71b967d243 test both datastore and direct data load 2014-10-14 15:35:14 +02:00
Dennis Luxen 1fc1e9590a throw an exception instead of false asserts 2014-10-14 12:52:11 +02:00
Dennis Luxen 0a0099fb41 rename variable, break long lines 2014-10-14 12:49:50 +02:00
Dennis Luxen b890d394ad Add range based CRC32 computation for iterable objects 2014-10-13 18:18:15 +02:00
Dennis Luxen a7fd37ae76 make Descriptor classes final 2014-10-13 18:17:24 +02:00
Dennis Luxen 41fafae21d mark Plugin classes as final 2014-10-13 17:29:53 +02:00
Dennis Luxen a38c007f51 throw instead of assert(false) 2014-10-13 17:20:34 +02:00
Dennis Luxen c7ee402b0e make link tests less brittle, no overlapping paths 2014-10-13 14:56:17 +02:00
Dennis Luxen 1c19796e3e fix container.hpp to properly use std::next and std::end 2014-10-13 13:54:40 +02:00
Emil Tin 76fb0cb965 get process handling up to date 2014-10-13 11:19:49 +02:00
Dennis Luxen 23c79f5cc9 reformat StaticRTreeBench.cpp 2014-10-13 11:15:22 +02:00
Emil Tin 14eac50261 remove datastore test 2014-10-13 11:10:40 +02:00
Emil Tin cf3eae1c91 disable failing test 2014-10-13 10:58:03 +02:00
Emil Tin db06cdb4ce adjust datastore testing 2014-10-13 10:58:03 +02:00
Emil Tin 7ba8e51fa9 use osrm-database during testing 2014-10-13 10:58:03 +02:00
Dennis Luxen bc6466cc36 fix test to inlcude renamed headers 2014-10-13 09:45:07 +02:00
Dennis Luxen 4fbefaef9a catch an uncaught exception and give git revision in springclean tool 2014-10-13 09:42:47 +02:00
Dennis Luxen be11d3325d add mutex include 2014-10-10 19:38:59 +02:00
Dennis Luxen 274140d309 refactor SimpleLogger into simple_logger compile unit 2014-10-10 19:32:49 +02:00
Dennis Luxen ed960ccc8d refactor angle computation into class/compile unit 2014-10-10 18:47:28 +02:00
Dennis Luxen f2b72113c1 refactor ContainerUtil into container.hpp 2014-10-10 18:24:13 +02:00
Dennis Luxen 67a8d30e87 renamed file 2014-10-10 18:19:10 +02:00
Dennis Luxen dafd0e5db7 rewrite NumericUtils into floating_point.hpp 2014-10-10 18:18:56 +02:00
Dennis Luxen d6d10cbf06 reformat Coordinate class 2014-10-10 18:00:09 +02:00
Dennis Luxen 3d3ba86be4 Merge pull request #1212 from Project-OSRM/fix_997
implements and fixes #997: support base path for c'tor
2014-10-10 17:17:41 +02:00
Dennis Luxen 52ed8a7ed0 move springclean functionality in its own tools, remove from datastore 2014-10-10 16:55:24 +02:00
Dennis Luxen 9449c99e25 enable partitioning on LTO, good riddance GCC 4.7 2014-10-10 10:46:43 +02:00
Dennis Luxen 4c0846734e rework the population and checking of base paths 2014-10-10 10:41:06 +02:00
Dennis Luxen 4c64f5fe62 remove shared memory indicator member, use unique_ptr for barriers 2014-10-10 10:41:06 +02:00
Dennis Luxen 9455ea0547 fix initialization of use_shared_memory 2014-10-10 10:41:06 +02:00
Dennis Luxen c3b54a63c3 remove ServerPaths member from OSRM_impl. pass it by value to c'tor 2014-10-10 10:41:06 +02:00
Dennis Luxen b9e1d3116c implements and fixes #997
- ServerPaths object can be populated by passing base path to OSRM
- reduces code/functionality duplication in node-OSRM
2014-10-10 10:41:05 +02:00
Dennis Luxen 5bb7e62a7c fix test on 'some' Intel FPU 2014-10-10 10:36:24 +02:00
Dennis Luxen a443f3a0bb add barrier checkpoint to the white list of passable tags 2014-10-10 10:34:34 +02:00
Dennis Luxen 440244eed8 use double precision fp math for mercartor projection and point-line projections (for now), fixes #1191 2014-10-09 18:58:58 +02:00
Dennis Luxen 2b9e25300f disable checking for empty data sets to make tests pass in debug mode, #889 2014-10-09 17:27:41 +02:00
Dennis Luxen de264dbf94 untangle includes 2014-10-09 14:08:12 +02:00
Dennis Luxen 848b773e24 fix reloading of RTree from shared memory, potentially fixes a number of issue from #889 2014-10-08 19:20:15 +02:00
Dennis Luxen d92f022041 remove implicit inline keyword from header files 2014-10-08 14:47:51 +02:00
Dennis Luxen 57fab61789 move casts from/to string into static class 2014-10-08 14:47:22 +02:00
Dennis Luxen ec8f977ebe reformat StringUtil.h 2014-10-08 12:48:20 +02:00
Dennis Luxen 8dc85e7641 use C++11 type traits to reduce code size in integral->string conversion 2014-10-08 12:40:56 +02:00
Dennis Luxen 4e00ebcd74 Merge pull request #1211 from Project-OSRM/fix_1173
Fix and close #1173
2014-10-08 11:44:48 +02:00
Dennis Luxen 335e719b5d pick compressed edge-weights in correct order 2014-10-08 11:01:58 +02:00
Dennis Luxen 415f8ef2d8 add test-case for bug 2014-10-08 11:01:33 +02:00
Dennis Luxen 17615d1d4a Merge pull request #1209 from Project-OSRM/test/links
test link speeds
2014-10-07 18:08:23 +02:00
Emil Tin 5072252c72 test link speeds 2014-10-07 17:05:39 +02:00
Dennis Luxen 46e93770c9 Merge pull request #1208 from Project-OSRM/feature/surfaces
surface, tracktype, smoothness tags in car profile, closes #955, #1208, #389.
2014-10-07 15:11:55 +02:00
Emil Tin fe43734811 use nil for unlimited surface speeds 2014-10-07 13:50:53 +02:00
Emil Tin 0df81c49d5 surface, tracktype, smoothness tags in car profile 2014-10-07 10:43:47 +02:00
Dennis Luxen 5653516b32 traverse *_link roads at a significantly lower speed than the main link, fixes #1174 2014-10-06 13:42:30 +02:00
Dennis Luxen 22da5be08e Merge branch 'frodrigo-develop' into develop 2014-10-06 09:43:11 +02:00
Dennis Luxen 862656aecc Merge branch 'develop' of https://github.com/frodrigo/osrm-backend into frodrigo-develop 2014-10-06 09:42:55 +02:00
Frédéric Rodrigo ec119a6d52 Add test for maxspeed like 'countrycode:zone type' for car profile 2014-10-04 21:17:18 +02:00
Frédéric Rodrigo 6b98b5f4c7 Parse maxspeed value like FR:urban on car profile 2014-10-04 14:12:14 +02:00
Dennis Luxen 5effe95f2c reformat JSONContainer.h 2014-10-03 11:13:50 +02:00
Dennis Luxen f22e3fd3ff mark Renderer c'tors in JSONContainer as explicit 2014-10-03 11:02:28 +02:00
Dennis Luxen 0047040af9 encapsulate base64 encoding into class to remove static functions from global namespace 2014-10-03 10:38:37 +02:00
Dennis Luxen 60987e6b9b mark c'tors explicit 2014-10-03 10:27:24 +02:00
Dennis Luxen 27d5e2b219 fix include order 2014-10-03 10:23:21 +02:00
Dennis Luxen 53fd0c3a55 fix initialization of EdgeBasedGraphFactory 2014-10-03 10:21:15 +02:00
Dennis Luxen 63456a6d4f fix position of include guard 2014-10-03 10:19:45 +02:00
Dennis Luxen d4cd3c2f7b remove superflous include 2014-10-03 10:17:02 +02:00
Dennis Luxen dbf7137a1a fix include guard name 2014-10-03 10:15:03 +02:00
Dennis Luxen 785891c315 fix name of include guard 2014-10-03 10:03:44 +02:00
Dennis Luxen b7417ec954 fix name of include guard 2014-10-03 10:02:36 +02:00
Dennis Luxen 61b861f0e5 fix name of include guard 2014-10-03 10:01:24 +02:00
Dennis Luxen 0fea0738bf remove superflous inline keyword 2014-10-03 09:59:04 +02:00
Dennis Luxen 4f25d29815 use nullptr instead of NULL 2014-10-03 09:56:07 +02:00
Dennis Luxen 28302a5040 unique_ptr<T> should be unique_ptr<T[]> when used with array 2014-10-02 19:26:57 +02:00
Dennis Luxen 9cc5ca5c58 fix name of include guard 2014-10-02 19:24:43 +02:00
Dennis Luxen 4c4e60b3c9 fix name of include guard 2014-10-02 19:24:06 +02:00
Dennis Luxen 5689a96602 make c'tors of Descriptors explicit 2014-10-02 19:22:02 +02:00
Dennis Luxen 8b57db467a move c'tor should not take const argument 2014-10-02 19:19:52 +02:00
Dennis Luxen 50339e53e2 rename variable across all ifdef paths 2014-09-30 14:52:16 +02:00
Dennis Luxen bc9f5189a5 use irange based for loop in DouglasPeucker run 2014-09-30 14:42:55 +02:00
Dennis Luxen fee83fee40 rename short variable and reformat, OCLint 2014-09-30 14:30:15 +02:00
Dennis Luxen cd5112ab0e rename short variable, OCLint 2014-09-30 14:28:00 +02:00
Dennis Luxen a43b88f9a2 reformat 2014-09-30 14:22:11 +02:00
Dennis Luxen c20fd5dcaa fix short variable name, OCLint 2014-09-30 14:21:24 +02:00
Dennis Luxen f12e296c09 fix short variable name, OCLint 2014-09-30 14:19:49 +02:00
Dennis Luxen 9c3a572646 link unlocking tool against Threads 2014-09-29 16:59:09 +02:00
Dennis Luxen 6175faa9a4 Merge pull request #1202 from Project-OSRM/fix_1192
Fix and close #1192
2014-09-29 12:27:52 +02:00
Dennis Luxen af02fc6bbe add tests for ferry durations 2014-09-29 11:44:51 +02:00
Dennis Luxen cc0bbc42a2 add duration to backward speed, fixes #1192 2014-09-29 11:37:36 +02:00
Dennis Luxen fd747c7340 propagate Lua include dir when compile-checking Luabind, fixes #1196 2014-09-25 12:58:23 +02:00
Dennis Luxen bd33202972 make routing algorithm classes final 2014-09-24 16:03:52 +02:00
Dennis Luxen f6f0de0e38 pimpl OSRM lib with std::unique_ptr 2014-09-24 13:17:55 +02:00
Dennis Luxen 881041800b remove superflous include 2014-09-23 09:41:28 +02:00
Dennis Luxen 11f3ac16f6 add some formatting 2014-09-23 09:41:10 +02:00
Dennis Luxen 969bf95230 Merge pull request #1194 from Project-OSRM/better_luabind_check
better checking for luabind compilation, fixes some OSX woes
2014-09-19 17:08:39 +02:00
Dennis Luxen abc6b4180c better checking for luabind compilation, fixes some OSX woes 2014-09-19 16:33:24 +02:00
Dennis Luxen f74d762a92 Merge branch 'alex85k-luabind-check' into develop 2014-09-19 09:57:56 +02:00
Dennis Luxen f00892ed66 Merge branch 'luabind-check' of https://github.com/alex85k/Project-OSRM into alex85k-luabind-check 2014-09-19 09:57:43 +02:00
alex85k f14c6e6845 Auto-detect Lua compatible with installed Luabind 2014-09-18 23:34:51 +06:00
Dennis Luxen b1bbf2ef84 add relational operators 2014-09-18 11:10:23 +02:00
Dennis Luxen 201062cade make width of computation depend on base type, i.e. if its 64bit then use 64bit math 2014-09-18 10:19:40 +02:00
Dennis Luxen 8cb9198bcf allow a 64bit base type 2014-09-18 09:43:11 +02:00
Dennis Luxen f5e53c0452 make cast operators explicit 2014-09-18 09:42:38 +02:00
Dennis Luxen 41d9c00f70 FixedPointNumber implementation 2014-09-17 19:20:15 +02:00
Dennis Luxen b52f392c92 Merge branch 'srajkovic-stefan-rajkovic-multiple-nearest-points' into develop 2014-09-16 12:33:06 +02:00
Dennis Luxen efaa3b5ab2 Merge branch 'stefan-rajkovic-multiple-nearest-points' of https://github.com/srajkovic/osrm-backend into srajkovic-stefan-rajkovic-multiple-nearest-points
Conflicts:
	DataStructures/RouteParameters.cpp
	Server/APIGrammar.h
2014-09-16 12:32:40 +02:00
Dennis Luxen 36f3d8d6ac Merge pull request #1187 from Project-OSRM/upgrade_protobuf_appveyor
2nd try: upgrade to protobuf 2.5.0 on appveyor
2014-09-15 20:10:57 +02:00
Dennis Luxen e469afa4a9 upgrade to protobuf 2.5.0 on appveyor 2014-09-15 16:21:37 +02:00
Dennis Luxen 9d4b0caa5b fix #1181, uncompressed geometries regressed into array of strings 2014-09-15 14:27:27 +02:00
Dennis Luxen 392c07951e some renaming of member functions to remove ambiguity 2014-09-15 14:23:43 +02:00
Dennis Luxen 8e72c3d81e Merge pull request #1184 from Project-OSRM/cmake_object_library
use object libraries in cmake, bump cmake to 2.8.8+
2014-09-15 13:15:12 +02:00
Dennis Luxen 02428f1e06 add object library to benchmarks 2014-09-15 12:21:13 +02:00
Dennis Luxen b3aa513563 manually install cmake on Travis 2014-09-15 12:14:32 +02:00
Dennis Luxen b8b08cb114 use object libraries in cmake, bump cmake to 2.8.8+ 2014-09-15 11:34:55 +02:00
Dennis Luxen ebbbf1059d Revert "disable LUA 5.2", cf. #1179
This reverts commit 994bd0a910.
2014-09-15 10:24:44 +02:00
Dennis Luxen 37297076f8 Merge pull request #1177 from joto/patch-3
Add object_types to some tags.
2014-09-07 23:15:03 +02:00
Jochen Topf a75b2df6fe Add object_types to some tags.
The newest taginfo understand an `object_types` field to restrict the key/value to certain types of OSM objects.
2014-09-07 20:39:56 +02:00
Dennis Luxen 9ccd0f0282 bump variant version 2014-09-04 16:19:00 +02:00
Dennis Luxen e57d9f2e2e Merge pull request #1157 from Project-OSRM/fix/spelling_of_edge
fix spelling of 'edge'
2014-08-31 11:25:56 +02:00
Emil Tin cf593ba9f9 fix spelling of edge in SharedDataFacade 2014-08-31 09:09:12 +02:00
Dennis Luxen 9eb862a6a4 Merge pull request #1172 from joto/patch-2
Update taginfo.json
2014-08-25 22:07:08 +02:00
Jochen Topf bc84e08da5 Update taginfo.json 2014-08-25 21:55:07 +02:00
Dennis Luxen 24dae2f096 fix URL 2014-08-22 10:43:25 +02:00
Dennis Luxen ab24d6bd96 add JSON file for taginfo analysis 2014-08-22 10:42:43 +02:00
Dennis Luxen 7782c80c4f implement missing loading of TravelMode vector into shared memory 2014-08-22 10:31:47 +02:00
Dennis Luxen 994bd0a910 disable LUA 5.2 2014-08-22 10:31:47 +02:00
Stefan Rajkovic bc9dcba4d4 Removed unnecessary whitespace 2014-08-21 13:24:04 -04:00
Dennis Luxen 85c244ed08 Merge pull request #1166 from Project-OSRM/server_instance_unique_ptr
keep server instance in a shared_ptr
2014-08-21 19:22:37 +02:00
Stefan Rajkovic 495196193c Uses range based check for number of results 2014-08-21 13:19:05 -04:00
Stefan Rajkovic def1e5e1d8 Set restrictions on number of results possible, so 0 < number <= 100. 2014-08-21 13:15:13 -04:00
Dennis Luxen 2727091e47 Merge pull request #1154 from Project-OSRM/feature/travel_mode
travel mode, closes #569, #603 and #606. Great job!
2014-08-21 15:12:02 +02:00
Dennis Luxen d7fbd416ba fix expected values of backward speed in test 2014-08-21 12:18:19 +02:00
Dennis Luxen 6a09ce1613 fix comparison in car speed profile 2014-08-21 12:17:03 +02:00
Emil Tin 774e6346e7 more robust check for parsed ways 2014-08-20 17:10:40 +02:00
Dennis Luxen 05b939760c Revert "use more osrm::irange"
This reverts commit d6c6fbfe03.
2014-08-20 15:47:48 +02:00
Dennis Luxen d6c6fbfe03 use more osrm::irange 2014-08-20 15:34:10 +02:00
Dennis Luxen bb3cbf2dda fix indentation, remove superflous else clause 2014-08-20 14:01:40 +02:00
Dennis Luxen 39d96a45aa fix lambda syntax 2014-08-20 12:14:31 +02:00
Dennis Luxen 6a8c5c8869 fix typo 2014-08-20 11:57:46 +02:00
Dennis Luxen 96318bbe11 switch from unique to shared ptr 2014-08-20 11:57:31 +02:00
Emil Tin 00dd2463fd use lambda to decide turn value 2014-08-20 11:48:47 +02:00
Emil Tin bcd55626ef make accessors const, add comments 2014-08-20 11:37:47 +02:00
Dennis Luxen 8f8cb6a52f keep server instance in a unique_ptr 2014-08-20 11:24:29 +02:00
Emil Tin 2e3d33dfcd remove type from more structs, remove asserts 2014-08-20 11:08:59 +02:00
Emil Tin 1e40cd6f0b remove type assertion 2014-08-20 11:08:59 +02:00
Emil Tin 6e2608b2f2 fix cuke support file 2014-08-20 11:08:59 +02:00
Emil Tin 60d80cf261 code style fixes 2014-08-20 11:08:59 +02:00
Emil Tin 9c23fd4a31 remove accidentially added file 2014-08-20 11:08:59 +02:00
Emil Tin fccb1aad32 remove type attribute 2014-08-20 11:08:59 +02:00
Emil Tin 2780ff31b5 fix bug with mode of 1st instruction 2014-08-20 11:08:59 +02:00
Emil Tin c37c8dc21d add mode test 2014-08-20 11:08:59 +02:00
Emil Tin 6ee7a81f10 update foot profile, add ferry mode 2014-08-20 11:08:58 +02:00
Emil Tin 3d94638d86 update car profile, add ferry mode 2014-08-20 11:08:58 +02:00
Emil Tin 418ff95543 fix initialization order 2014-08-20 11:08:58 +02:00
Emil Tin 221113cbb7 fix assert 2014-08-20 11:08:58 +02:00
Emil Tin 13ea12cf6e fix unit test 2014-08-20 11:08:58 +02:00
Dennis Luxen 1945aae4dc reorder members of SegmentInformation, remove bit fields where possible 2014-08-20 11:08:58 +02:00
Emil Tin 30362cfc0c update lua interface to speed and mode 2014-08-20 11:08:58 +02:00
Emil Tin 6cdc590db5 typedef instead of enum for TravelMode to avoid gcc warnings 2014-08-20 11:08:58 +02:00
Emil Tin eb122a2b8c tidy feature file 2014-08-20 11:08:58 +02:00
Emil Tin feaf8711d3 announce mode changes 2014-08-20 11:08:58 +02:00
Emil Tin 6e364ff0ba rename travel mode None to Inaccessible 2014-08-20 11:08:58 +02:00
Emil Tin 6f6aff7493 remove direction field from ExtractionWay 2014-08-20 11:08:58 +02:00
Emil Tin 207cddd50b use enum for TravelMode 2014-08-20 11:08:58 +02:00
Emil Tin 35988d8f09 fix problem with mode of first instruction 2014-08-20 11:08:42 +02:00
Emil Tin bea63028c7 remove bitfield from SegmentInformation, works around compile err 2014-08-20 11:08:42 +02:00
Emil Tin 0244060806 add a few tests 2014-08-20 11:08:42 +02:00
Emil Tin bfdc296f43 reduce failing test 2014-08-20 11:08:42 +02:00
Emil Tin 8e625a5d07 rename test 2014-08-20 11:08:42 +02:00
Emil Tin 3460bd0ba9 fix problems with mode, 1 failing test left 2014-08-20 11:08:42 +02:00
Emil Tin 4dd0377eb8 fix compilation of tests 2014-08-20 11:08:42 +02:00
Emil Tin 6e1ab9fe3a profile fixes 2014-08-20 11:08:42 +02:00
Emil Tin 7a2d214cc4 reactivate assert of sizeof(NodeBasedEdgeData) 2014-08-20 11:08:42 +02:00
Emil Tin 62495a6de4 remove comment 2014-08-20 11:08:42 +02:00
Emil Tin 8ea88468f3 remove unneeded methods 2014-08-20 11:08:42 +02:00
Emil Tin 687892890b remove spurious comment 2014-08-20 11:08:42 +02:00
Emil Tin ff0dfacc48 fix initialization order to avoid compiler warning 2014-08-20 11:08:42 +02:00
Emil Tin 235a52032a more tests passing 2014-08-20 11:08:42 +02:00
Emil Tin a5ee7e78f6 fixes 2014-08-20 11:08:41 +02:00
Emil Tin 181dbe8493 improve tests for travel mode 2014-08-20 11:08:41 +02:00
Emil Tin dae9c9a7ed use 4 bits for travel mode 2014-08-20 11:08:41 +02:00
Emil Tin 6d6d299ea4 most tests passing 2014-08-20 11:08:41 +02:00
Emil Tin 6fd615b9cd first cut at porting travel mode, some tests fail 2014-08-20 11:08:41 +02:00
Emil Tin d09394ed52 add failing tests for travel mode 2014-08-20 11:08:41 +02:00
Emil Tin 3e6f27d173 rename contra_flow to travel_mode, use unsigned char 2014-08-20 11:08:41 +02:00
Dennis Luxen 82c2ae5441 first round of replacing deprecated typedefs with much nicer using statements 2014-08-19 13:01:38 +02:00
Dennis Luxen 7edf2bb2c2 Merge pull request #1164 from Project-OSRM/appveyor_nuget
Install protoc on both Travis and AppVeyor.
2014-08-19 11:00:23 +02:00
Dennis Luxen c9607b99a3 install protoc thru nuget 2014-08-19 10:11:32 +02:00
Dennis Luxen 2fe1a84dd4 adding protobuf compiler to dependencies, used in branches 2014-08-19 09:56:49 +02:00
Dennis Luxen c63218a889 add final/override keyword where possible to help compiler de-virtualize function calls 2014-08-18 10:19:33 +02:00
Dennis Luxen 5efa9664db Revert "fixing line endings"
This reverts commit dc75469e78.
2014-08-15 18:53:00 +02:00
Dennis Luxen dc75469e78 fixing line endings 2014-08-15 18:47:26 +02:00
Dennis Luxen 9d1e21b5ad Merge pull request #1104 from Project-OSRM/experimental/mapbox_variant
Experimental/mapbox variant
2014-08-14 18:57:53 +02:00
Dennis Luxen 27a367c733 enter build directory before calling tests 2014-08-14 17:29:11 +02:00
Dennis Luxen ffa0ace2a7 build tests by running msbuild on tests project file 2014-08-14 17:29:10 +02:00
Dennis Luxen 074e1e992c build test target explicitly on AppVeyor 2014-08-14 17:29:10 +02:00
Dennis Luxen cdd72c7e56 fast forward variant lib 2014-08-14 17:29:10 +02:00
Dennis Luxen a5e99a95a3 remove constexpr workaround as minimum req. is now Nov 2013 CTP 2014-08-14 17:29:10 +02:00
Dennis Luxen 1de736019d make canary static const instead of constexpr 2014-08-14 17:29:10 +02:00
Dennis Luxen d6b2712070 make msbuild less verbose 2014-08-14 17:29:10 +02:00
Dennis Luxen eda8f4ccec make integer literals static const instead of constexpr 2014-08-14 17:29:10 +02:00
Dennis Luxen 7e3f476407 use 64bit cmake generator 2014-08-14 17:29:10 +02:00
Dennis Luxen e10f36d5f0 use explicit OSRM.sln filename 2014-08-14 17:29:10 +02:00
Dennis Luxen 1bfd9abda3 replace nmake by msbuild 2014-08-14 17:29:10 +02:00
Dennis Luxen 4a1a10fde8 use Nov 2013 CTP to build 2014-08-14 17:29:10 +02:00
Dennis Luxen 4c3cb76ced remove remnants of boost::variant 2014-08-14 17:29:10 +02:00
Dennis Luxen e2794e9f06 initial checkin of mapbox::util::variant 2014-08-14 17:29:10 +02:00
Dennis Luxen 7d2c627ad2 replace boost::variant w/ mapbox::util::variant 2014-08-14 17:29:10 +02:00
Dennis Luxen b310e0f718 apply some reformatting 2014-08-14 17:12:58 +02:00
Dennis Luxen 18915ae2bd make dummy __get_cpuid available on Windows 2014-08-14 17:12:58 +02:00
Dennis Luxen 5dbda8f519 refactoring of IteratorBasedCRC32, fixes #1140 2014-08-14 17:12:58 +02:00
Dennis Luxen 82ce9dfc04 reactivate software-based CRC32 on x64 platforms without SSE4.2 2014-08-14 17:12:57 +02:00
Dennis Luxen ad5cd564ab even more reformatting 2014-08-13 16:11:56 +02:00
Dennis Luxen 6f01f580ca fix several errors reported by OCLint:
- rename variable with short name
- fix inverted logic
- rename members in SpeedProfile
2014-08-13 11:02:36 +02:00
Dennis Luxen d5130d9fe4 reformatting DescriptionFactory.cpp 2014-08-13 11:02:36 +02:00
Dennis Luxen 0341a0d5e7 reformatting DescriptionFactory.cpp 2014-08-12 19:29:54 +02:00
Dennis Luxen 32191fb05a also build tests on Travis 2014-08-12 16:17:27 +02:00
Dennis Luxen 1592fe377a Merge pull request #1150 from Project-OSRM/feature/announce_via_locations
implements announcement of waypoints, closes #584
2014-08-12 11:49:51 +02:00
Dennis Luxen 5add28410f Adapt test cases to output of way points
- waypoints are now announced in the route guidance
- implements #584
2014-08-12 09:27:17 +02:00
Dennis Luxen d54a55c12b implements announcement of waypoints, closes #584 2014-08-11 20:29:15 +02:00
Dennis Luxen aab5e8430f ignore package related files 2014-08-11 16:16:56 +02:00
Dennis Luxen 2e20fdb462 allow building of packages 2014-08-11 16:16:56 +02:00
Dennis Luxen 2ac3da7a90 update minimum compiler to gcc 4.8, take 2 2014-08-11 09:42:29 +02:00
Dennis Luxen 399b79bab2 update minimum compiler to gcc 4.8 2014-08-11 09:39:35 +02:00
Stefan Rajkovic b9eb936cac Uses current JSON format if number of results requested is 1 2014-08-08 14:06:06 -04:00
Stefan Rajkovic 38117df11b Added ability to get multiple points from /nearest by using num_results argument 2014-08-08 13:58:30 -04:00
Dennis Luxen 27d729baf0 use a return value in Prepare::BuildEdgeExpandedGraph instead of parameter re-assignment 2014-08-08 13:00:39 +02:00
Dennis Luxen d408a64c8c rename variable to have a longer, more telling name in Prepare 2014-08-08 12:41:57 +02:00
Dennis Luxen 9aeb28066d fix inverted logic 2014-08-07 19:19:21 +02:00
Dennis Luxen 6fb7c8687e fixes #1107, turn restriction combination including overlaps and one-ways 2014-08-07 18:34:56 +02:00
Dennis Luxen d9666008e3 remove left-over debug output 2014-08-07 18:17:35 +02:00
Dennis Luxen e132230651 add some minor comments to Range 2014-08-07 17:39:53 +02:00
Dennis Luxen c2877a0c22 use std::shared_ptr instead of raw ptr 2014-08-07 13:40:43 +02:00
Dennis Luxen 251fc3ec68 apply some more constness 2014-08-07 12:02:57 +02:00
Dennis Luxen 287f0a3b68 minor edit 2014-08-07 12:01:32 +02:00
Dennis Luxen b03d9fe987 replace INT_MAX by proper typedef 2014-08-07 12:01:31 +02:00
Dennis Luxen 98372ef33f replace boost::irange in Tools 2014-08-05 18:06:15 +02:00
Dennis Luxen d00f4afb84 replace C limits with STL-defined and typedef'ed limits 2014-08-05 17:20:01 +02:00
Dennis Luxen d4bf02c882 replace boost integer range 2014-08-05 17:19:09 +02:00
Dennis Luxen 284e671163 add convenience class for integer range 2014-08-04 17:27:34 +02:00
Dennis Luxen 0f112e5c9d untangle includes 2014-08-04 13:23:37 +02:00
Dennis Luxen 759449b4be remove an unneeded check in JSONDescriptor 2014-08-01 15:59:45 +02:00
Dennis Luxen 9c03f919a3 Merge pull request #1138 from dmbreaker/fix/alter_route_end
Fixes alternative route end-point (http://imgur.com/ZQhwTZi)
2014-07-31 17:07:08 +02:00
Dennis Luxen c9afd9a281 make dummy date in generated test files valid 2014-07-31 16:41:38 +02:00
dmbreaker a999cb9db9 Fixes alternative route end-point (http://imgur.com/ZQhwTZi) 2014-07-31 16:10:02 +04:00
Dennis Luxen fdc5bd6195 add try catch, fixes coverity issues 1229132 and 1229133 2014-07-30 11:28:36 +02:00
Dennis Luxen e1d94eee21 Merge branch 'Zhdanovich-scc_develop' into develop 2014-07-30 09:42:55 +02:00
Kirill Zhdanovich 885f237217 Apply diff https://github.com/Project-OSRM/osrm-backend/pull/1133 to develop branch 2014-07-29 22:12:59 +02:00
Dennis Luxen 5860a4e28e clear external vector after use, closes #1131 2014-07-28 16:15:21 +02:00
Dennis Luxen 2bebed44ff use stxxl as external data store instead of hand-rolled code in /tmp 2014-07-28 15:58:50 +02:00
Dennis Luxen 4990e544cf add a distinct tool to check if hsgr file is valid, closes #1081 2014-07-28 14:51:33 +02:00
Dennis Luxen 8010506d4e remove reverted include 2014-07-28 14:20:17 +02:00
Dennis Luxen f2f7abb9a8 remove reverted include 2014-07-28 14:19:16 +02:00
Dennis Luxen 85f6ab869e Revert "let ServerFactory return unique ptr instead of raw ptr"
This reverts commit cc7c6b9ece.
2014-07-28 14:08:54 +02:00
Dennis Luxen fc87b0a11e enabling defaultctor for Server 2014-07-28 12:04:11 +02:00
Dennis Luxen 79bc071754 enabling default copy ctor for Server 2014-07-28 11:24:49 +02:00
Dennis Luxen 797243fc9c return unique ptr instead of raw ptr 2014-07-28 11:03:53 +02:00
Dennis Luxen cc7c6b9ece let ServerFactory return unique ptr instead of raw ptr 2014-07-28 10:15:22 +02:00
Dennis Luxen 279071e5bb re-add pairwise container traversal 2014-07-28 10:14:24 +02:00
Dennis Luxen 426374ff8a register all classes at once in LUA environment 2014-07-24 18:26:40 +02:00
Dennis Luxen 1508874ebc return early if way is not either highway=* or route=* in car profile. Estimated cost saving 10% 2014-07-24 18:00:37 +02:00
Dennis Luxen bbe440cacd fix implcit conversion in DynamicGraph 2014-07-24 11:29:03 +02:00
Dennis Luxen e647e73af9 fix implcit conversion in RestrictionMap 2014-07-24 11:25:43 +02:00
Dennis Luxen 696ddfde0e mark temporaries const 2014-07-24 11:23:33 +02:00
Dennis Luxen 37d6257524 fix implicit conversion in TemporaryStorage 2014-07-24 11:23:03 +02:00
Dennis Luxen faee894052 add a couple of consts to range based for loops 2014-07-24 10:15:04 +02:00
Dennis Luxen 61f16b8c5e remove code duplication 2014-07-24 09:56:20 +02:00
Dennis Luxen 85eb38e755 reformatting code according to guidelines 2014-07-23 19:28:04 +02:00
Dennis Luxen a87cf60dfc move common code into Util header 2014-07-23 19:25:09 +02:00
Dennis Luxen 3b135447f3 use typedef Edgeweight instead of raw int 2014-07-23 14:50:45 +02:00
Dennis Luxen 0c3713f7e5 Merge branch 'TheMarex-boost-test' into develop 2014-07-22 18:55:33 +02:00
Patrick Niklaus 4d0571fd73 Fix win32 linking and run test automatically in AppVayor 2014-07-22 18:23:43 +02:00
Patrick Niklaus 4722988bf0 Try including typedefs 2014-07-22 17:17:56 +02:00
Patrick Niklaus 61151535e6 Fix include in RangeTableTest 2014-07-22 17:17:56 +02:00
Patrick Niklaus bcff6c192c Remove template paramters and constexpr in test
Stops clang from complaining about non-constexpr.
2014-07-22 17:17:56 +02:00
Patrick Niklaus 020d0cfb49 Revert "Change StaticRTree serialization constructor to static function"
This makes clang 3.4 crash on ubuntu because it can not handle lambda
expressions + binding in static member functions correctly.

This reverts commit d6dd6693b18e042c0068da579dcc64d1e5a2e002.
2014-07-22 17:17:56 +02:00
Patrick Niklaus d38e3bd729 Add tests and benchmarks to appveyor 2014-07-22 17:17:56 +02:00
Patrick Niklaus 84a604f70b Add test for new GetMinDist 2014-07-22 17:17:56 +02:00
Patrick Niklaus 782baf54a3 Remove perpendicular distance call
Since we know that the MBB is axis aligned we can compute
the distance to the line segments a lot simpler.
2014-07-22 17:17:56 +02:00
Patrick Niklaus d754e4eeca Add benchmark for StaticRTree
Build with 'make benchmarks'
2014-07-22 17:17:56 +02:00
Patrick Niklaus db98f6191e Prepare alrady writes the correct number of nodes 2014-07-22 17:17:56 +02:00
Patrick Niklaus b453a42f77 Fixed perpendicular distance calculation of segment endpoint is on equator 2014-07-22 17:17:56 +02:00
Patrick Niklaus 2a6585e664 Add regression test for 'gap' querry bug 2014-07-22 17:17:56 +02:00
Patrick Niklaus bc013925b8 Consider points on the edge of the rectangle as inside 2014-07-22 17:17:56 +02:00
Patrick Niklaus 8108ecc4d3 Add test for StaticRTree 2014-07-22 17:17:56 +02:00
Patrick Niklaus 1c80584206 Fix GetMinDistance 2014-07-22 17:17:56 +02:00
Patrick Niklaus a3dd9c3e57 Change StaticRTree serialization constructor to static function
Since the constructor does not satisfy the requirements for a
constructor (the RTree is not properly initialized) make it a
static function instead.
2014-07-22 17:17:56 +02:00
Patrick Niklaus 8f05fc0a84 Make tuning constants template agruments in StaticRTree 2014-07-22 17:17:56 +02:00
Patrick Niklaus 3c4feecda0 Make fstream non-static and StaticRTree thread-specific instead 2014-07-22 17:17:56 +02:00
Patrick Niklaus e776a51c73 Added test for StaticGraph 2014-07-22 17:17:56 +02:00
Patrick Niklaus 129e8ef98a Fix small errors in StaticGraph 2014-07-22 17:17:56 +02:00
Patrick Niklaus 69134f6d6a Add test for RangeTable 2014-07-22 17:17:56 +02:00
Patrick Niklaus b32062f875 Fix typo in RangeTable 2014-07-22 17:17:56 +02:00
Patrick Niklaus 8d46ee85f1 Add test for BinaryHeap 2014-07-22 17:17:56 +02:00
Patrick Niklaus 9f9fde1f2b Fix missing include in BinaryHeap 2014-07-22 17:17:56 +02:00
Emil Tin 2b041e09ac tests uturn query param 2014-07-22 13:24:26 +02:00
Emil Tin 73b32bb45e enable setting query params in cuke tests 2014-07-22 13:24:26 +02:00
Dennis Luxen 11e6e74f09 fix implicit conversion 2014-07-22 12:56:24 +02:00
Dennis Luxen bf3e3f0c3d fix segfault when index into packed geometry ran out of bounds 2014-07-22 11:59:31 +02:00
Dennis Luxen 2656acc321 produce stack trace if script fails during setup. partially implements #1128 2014-07-21 15:46:19 +02:00
Dennis Luxen e46c9be79f dont fail if script does not define member 2014-07-21 15:44:57 +02:00
Dennis Luxen 507167d5c1 use 64bit int types to not lose precision in for loop counting variables 2014-07-21 13:14:05 +02:00
Dennis Luxen fc90162f69 fix typo, thx @joto, see #1126 2014-07-21 10:55:13 +02:00
Dennis Luxen 1e8fb7a38c Updated README to reflect new location 2014-07-21 10:50:41 +02:00
Dennis Luxen afb6c5a09d comparison between signed and unsigned integer expressions 2014-07-18 13:58:37 +02:00
Dennis Luxen 2255ab0a37 remove unneede include 2014-07-18 11:38:05 +02:00
Dennis Luxen a6ab042078 use parallel sorting for DeallocatingVector 2014-07-18 11:37:07 +02:00
Dennis Luxen 480f70c049 fix down-sizing in resize operation 2014-07-18 11:20:27 +02:00
Dennis Luxen 0592897859 rework assignment/copy operator, add operator[] to DeallocatingVector RA-iterator 2014-07-18 10:59:46 +02:00
Dennis Luxen d5a9f8e177 refactor DeallocatingVector, apply boost::iterator_facade 2014-07-17 18:26:14 +02:00
Dennis Luxen 5840829cdc refactor DeallocatingVector, apply boost::iterator_facade 2014-07-17 18:25:23 +02:00
Dennis Luxen fd0946b770 remove unneeded includes, fix variable names 2014-07-17 14:14:14 +02:00
Dennis Luxen 293b462fd2 add timing to SCC generation 2014-07-17 11:27:06 +02:00
Dennis Luxen 3db50fdd54 rename variables in SCC class, add const to variables, reformat 2014-07-17 11:16:26 +02:00
Dennis Luxen 1540e6518c rename variables in SCC class to be more legible 2014-07-17 11:07:35 +02:00
Dennis Luxen 8b30c13cd9 make sure edges are put into shapefile once and only once. 2014-07-17 10:48:30 +02:00
Dennis Luxen a7eb89b2f0 reformat SCC class, make sure road distances are not counted twice 2014-07-17 10:43:21 +02:00
Dennis Luxen 53c102e1e9 use boost::irange and range based for loop in // for (NodeID node = 0; node < last_node; ++node) 2014-07-17 10:30:56 +02:00
Dennis Luxen 7d90737921 remove zombie code from StronglyConnectedComponents.h 2014-07-17 10:27:47 +02:00
Dennis Luxen e281f88f2e remove zombie code from StronglyConnectedComponents.h 2014-07-17 10:27:23 +02:00
Dennis Luxen 16c5c7bbb4 set projection to EPSG:4326 for created shapefile 2014-07-17 10:26:27 +02:00
Dennis Luxen 7d4dfd87f1 add c'tor to TarjanEdgeData, use emplace_back in-place construction of edges 2014-07-17 10:25:39 +02:00
Dennis Luxen 6156bf0f9d make uturn parameter optional 2014-07-16 13:01:25 +02:00
Dennis Luxen ee1fdca52e implement path query with uturns at via nodes 2014-07-16 12:53:33 +02:00
Dennis Luxen 95b5bcbd49 add and parse U-turn parameters in servers APIGrammar 2014-07-16 12:48:11 +02:00
Dennis Luxen 0c529361a3 add member variable/functions to store information if uturns are allowed 2014-07-16 12:47:10 +02:00
Dennis Luxen 7110acc94f add initialization to QueryEdge::EdgeData 2014-07-16 09:44:09 +02:00
Dennis Luxen 1188002bcb downcast position explicitly to unsigned 2014-07-15 16:48:04 +02:00
Dennis Luxen b47a3f15ce fix initialization on Windows, i.e. cannot convert from bool to bool& 2014-07-15 15:37:30 +02:00
Dennis Luxen 695a2a2b6e use correctly sized 64bit integer and avoid unintended (implicit up/down casts) 2014-07-15 15:25:44 +02:00
Dennis Luxen c8b4ef3eed add two tests for turn restrictions starting/ending on the same segment 2014-07-15 15:10:13 +02:00
Dennis Luxen 6091248493 fix range initialization on Windows 2014-07-15 15:06:34 +02:00
Dennis Luxen 32fd507ad9 apply more emplace_backs and range based for loops to Contractor 2014-07-15 12:06:52 +02:00
Dennis Luxen 0ee77a37d1 make DynamicGraph::InputEdge c'tor variadic, forward args to EdgeData type 2014-07-15 11:50:08 +02:00
Dennis Luxen 05241544c5 make DeallocatingVector::emplace_back variadic and forward Args to contained element 2014-07-15 11:47:58 +02:00
Dennis Luxen 495c872489 add c'tors to QueryEdge and its EdgeData 2014-07-15 11:46:26 +02:00
Dennis Luxen 8c09edfdbd add minor reformatting 2014-07-15 11:42:27 +02:00
Dennis Luxen 67722cf788 make c'tor of DynamicGraph::InputEdge variadic to be more flexible against changing EdgeData types 2014-07-14 17:35:26 +02:00
Dennis Luxen 8e3484b873 rename ContractorEdgeData members 2014-07-14 17:35:02 +02:00
Dennis Luxen 4622aebabb reorder members for potentially tighter alignment 2014-07-14 17:31:50 +02:00
Dennis Luxen 96f29c27cd make c'tor of StaticGraph::InputEdge variadic to be more flexible against changing EdgeData types 2014-07-14 17:16:28 +02:00
Dennis Luxen 3de98f7a9d prevent in-source builds 2014-07-14 16:21:16 +02:00
Dennis Luxen 2b33fcd92d add c'tor to InputEdge of StaticGraph 2014-07-14 14:49:53 +02:00
Dennis Luxen b1ffcd4350 rename member to distance 2014-07-14 14:44:24 +02:00
Dennis Luxen fd500001fb Revert "also build tools on Windows"
This reverts commit 54a757a917.
2014-07-14 14:43:07 +02:00
Dennis Luxen 54a757a917 also build tools on Windows 2014-07-14 14:35:51 +02:00
Dennis Luxen 98dfc218d9 install tools if activated 2014-07-11 15:25:26 +02:00
Dennis Luxen f6f0f1fb72 fix signed/unsigned comparison in assertion 2014-07-11 14:04:09 +02:00
Dennis Luxen 218c810860 rename variable in XMLParser to make sure its name reflects the actual content 2014-07-11 14:03:38 +02:00
Dennis Luxen c836b6df3b fix SCC computation in debug mode by clearing a vector 2014-07-11 14:01:28 +02:00
Dennis Luxen 637bab29c6 transform negative numbers to positives by *(-1) 2014-07-11 14:00:33 +02:00
Dennis Luxen 0061b3fcbf remove unneeded member in Extractor, move to function scope 2014-07-11 10:10:50 +02:00
Dennis Luxen 2a19ded9d5 reformat Prepare.h/cpp with clang-format 2014-07-10 15:24:30 +02:00
Dennis Luxen bda9de0775 use boost::irange and range based for loop 2014-07-10 15:22:02 +02:00
Dennis Luxen 7047610a45 header untangling 2014-07-10 15:17:57 +02:00
Dennis Luxen 903d6f9e12 make instance of Prepare object an rvalue, remove dead code 2014-07-10 15:08:55 +02:00
Dennis Luxen 7d61bb2868 Merge branch 'dmbreaker-feature/prepare' into develop 2014-07-10 15:07:24 +02:00
Dennis Luxen def7164cad Merge branch 'feature/prepare' of https://github.com/dmbreaker/Project-OSRM into dmbreaker-feature/prepare 2014-07-10 15:07:15 +02:00
Dennis Luxen fc399e01fe explicitly cast segment length from float to int 2014-07-10 15:06:20 +02:00
Dennis Luxen ffdc3eee2d use proper float literal instead of implicit cast from int 2014-07-10 15:01:38 +02:00
Dennis Luxen 1f6f44ab01 include untangling of Extractor 2014-07-10 14:45:59 +02:00
Dennis Luxen 19740758c9 Merge branch 'dmbreaker-feature/extractor' into develop 2014-07-10 14:32:20 +02:00
Dennis Luxen f618660d24 Merge branch 'feature/extractor' of https://github.com/dmbreaker/Project-OSRM into dmbreaker-feature/extractor 2014-07-10 14:32:09 +02:00
Dennis Luxen f50dbe298a properly initialize variable 2014-07-10 14:03:20 +02:00
Dennis Luxen c324fbace4 path searches were pruned too early, fixes #1117 2014-07-10 13:56:36 +02:00
Dennis Luxen d05152af71 Merge pull request #1109 from DennisOSRM/fix/update_rspec_style
update rspec matchers to use expect()
2014-07-05 15:40:37 +02:00
Dennis Luxen bf228b4ae4 fix integer range to have correct end 2014-07-04 17:41:56 +02:00
Dennis Luxen ba0c17e287 make sure all node-based edges are serialized in forward fashion 2014-07-04 17:33:18 +02:00
Dennis Luxen 6cfbd4cefe fix unpacking of local path 2014-07-04 17:31:22 +02:00
Dennis Luxen e17a2e79a0 use range based for w/ integer ranges where possible 2014-07-04 17:23:45 +02:00
Dennis Luxen 72d709ae6c use explicit NodeID type in SharedDataFacade 2014-07-04 17:20:04 +02:00
Dennis Luxen 08ca450c40 change simplified graph loader to return a list of coordinates 2014-07-04 17:19:01 +02:00
dmbreaker a2951659ac prepare.cpp refactoring 2014-07-03 15:29:15 +04:00
dmbreaker 3a6af3810f One more blank line. 2014-07-03 10:23:43 +04:00
dmbreaker 3973554f07 Added blank lines between includes. 2014-07-03 10:23:43 +04:00
dmbreaker 718cba2e36 Trying to fix win-build 2014-07-03 10:23:43 +04:00
dmbreaker d2a70d1504 Removed pragma, reorganized includes. 2014-07-03 10:23:43 +04:00
dmbreaker 4bc847ac42 extractor.cpp refactored a bit 2014-07-03 10:23:43 +04:00
Dennis Luxen c3621edf9c refactor DynamicGraph to use integer ranges where possible 2014-07-02 16:58:19 +02:00
Dennis Luxen a64f2de9e1 add function to add a node into DynamicGraph 2014-07-02 15:27:09 +02:00
Dennis Luxen ce684cf9d4 fixes #1110, linker issues on CentOS 2014-07-02 14:38:02 +02:00
Dennis Luxen 1d1be10f16 add functions to load graph into simplified data structures 2014-07-02 14:36:20 +02:00
Dennis Luxen a09f97c9d5 remove OpenMP library linking 2014-07-02 14:34:44 +02:00
Dennis Luxen 48da2d2dfb add some comment to datastore 2014-07-02 11:21:34 +02:00
Dennis Luxen 36c0edea2a collapse if statement in datastore 2014-07-02 11:18:45 +02:00
Dennis Luxen 3568dc2083 use auto keyword to make code more legible 2014-07-02 11:07:29 +02:00
Dennis Luxen 51ad72a432 remove superflous include 2014-07-02 11:06:55 +02:00
Dennis Luxen 9ce970df8f use default keyword to get rid of compiler warning of not returning a value in a non-void function 2014-07-01 16:51:18 +02:00
Dennis Luxen cfa4d80dd7 make comparion of loop safe against underflows 2014-07-01 16:30:05 +02:00
Dennis Luxen 885cd05f1a fix data race in SimpleLogger by making state indicator variable atomic 2014-07-01 16:15:56 +02:00
Dennis Luxen 21188725d5 apply a bit of code refactoring to SCC implementation 2014-07-01 15:16:41 +02:00
Dennis Luxen 70f257b62f add BUILD_TOOLS flag, retire WITH_TOOLS soon 2014-07-01 15:16:41 +02:00
Dennis Luxen e8fb8e13df deactivate unused code 2014-07-01 15:16:41 +02:00
Dennis Luxen 7b7b93e9ba remove debug.bin generation 2014-07-01 15:16:41 +02:00
Dennis Luxen 4014da3cc5 make facade d'tors virtual 2014-07-01 14:26:29 +02:00
Dennis Luxen 410120adee close LUA context to avoid memory leak on shutdown 2014-07-01 14:26:02 +02:00
Dennis Luxen a98e65aa1e make variables const 2014-07-01 13:27:08 +02:00
Emil Tin dba9998118 update rspec matchers to use expect() 2014-06-30 20:43:51 +02:00
Dennis Luxen 1c75ce5911 reformat according w/ clang-format 2014-06-30 19:25:45 +02:00
Dennis Luxen 33b30aeb95 Merge branch 'fix/shared_mem_warnings' into develop 2014-06-30 19:23:30 +02:00
Dennis Luxen abd8d3459a Merge branch 'develop' into fix/shared_mem_warnings 2014-06-30 19:23:15 +02:00
Dennis Luxen 471698c59f fix picking of second route name 2014-06-30 16:05:26 +02:00
Dennis Luxen e67cf578ae remove explicit c'tor from Coordinate, use initializer list in PolylineCompressor 2014-06-30 15:16:35 +02:00
Dennis Luxen 186ad5d444 stream-line code in PolylineCompressor, apply range-based for loop again 2014-06-30 15:10:28 +02:00
Emil Tin 7eb810c34a fix shared mem warnings 2014-06-30 13:01:59 +02:00
Dennis Luxen 7817384e3c remove debug call 2014-06-30 11:53:36 +02:00
Dennis Luxen 34256ba358 properly compute sharing of nodes in search space with packed shortest path 2014-06-27 19:41:40 +02:00
Dennis Luxen 08eb5aa7d1 use shrink_to_fit() instead of swap trick 2014-06-27 19:40:47 +02:00
Dennis Luxen 1d3932e8c5 fix an off-by-one issue in the output JSON 2014-06-27 16:18:38 +02:00
Dennis Luxen 3f85b30d4a remove some unneeded includes 2014-06-27 10:38:28 +02:00
Dennis Luxen e4c398aa23 make std::hash specialization for std::pair<> fully generic 2014-06-27 09:50:57 +02:00
Dennis Luxen f9417555d0 remove superflous include 2014-06-27 09:50:26 +02:00
Dennis Luxen 5d3123b97f reformat code using clang-format 2014-06-26 13:50:29 +02:00
dmbreaker 25080aaf1d Non-explicit constructor and hash-functions. 2014-06-26 13:50:29 +02:00
dmbreaker 05ac4b5ab6 Fixes to fulfill remarks. 2014-06-26 13:50:29 +02:00
dmbreaker 07e13e2499 Replaced std::pair with classes.
Looks like fixed wrong restriction type in CheckForEmanatingIsOnlyTurn (now RestrictionTarget instead if RestrictionSource).
2014-06-26 13:50:29 +02:00
dmbreaker 2d9645b9b0 Added structures for RestrictionTarget and RestrictionSource. 2014-06-26 13:50:29 +02:00
Dennis Luxen 65ccbedab2 Merge pull request #1103 from dmbreaker/feature/graph_comments
Added some graphical explanations for variables.
2014-06-26 12:16:44 +02:00
Dennis Luxen 631567864b Merge pull request #1098 from TheMarex/rangetable-covertity
Fix coverity warning in RangeTable
2014-06-26 12:15:35 +02:00
Dennis Luxen 39d479128c add better comment to document the source of the hash_combine work 2014-06-26 12:14:47 +02:00
Dennis Luxen 4c0b315c07 Merge pull request #1094 from gberaudo/fixes
Several fixes: remove dead code, fix Int->String conversion for INT_MIN, remove duplicated coordinate from encoded polyline.
2014-06-26 11:54:45 +02:00
dmbreaker 264e83a1f3 Added comments with graphical representation of variables. 2014-06-26 12:31:45 +04:00
Dennis Luxen 2b2ed50721 add a hash combine implementation that has some minor performance guarantees 2014-06-25 18:50:46 +02:00
Dennis Luxen 31fbf99109 fail hard when building tools and not all prequisites are met 2014-06-25 10:53:51 +02:00
Dennis Luxen 63381ad221 fix compilation on GCC 4.8.2, type of priority_queue<> is not properly deduced 2014-06-24 18:31:34 +02:00
Guillaume Beraudo 6ee2d1103e Remove duplicated point in polyline encoded data
First point was outputted twice.
Add test case.
2014-06-24 17:25:36 +02:00
Guillaume Beraudo bee18dba54 Display warning when routing without street names.
Indeed, street names are optional for routing.
2014-06-24 17:18:52 +02:00
Guillaume Beraudo 481e445e8a Fix printInt when value=INT_MIN (was overflowing) 2014-06-24 17:18:52 +02:00
Guillaume Beraudo 129f7b7441 Remove unused polyline method 2014-06-24 17:18:52 +02:00
Guillaume Beraudo d6bc3c5175 Remove unused test method 2014-06-24 17:18:52 +02:00
Dennis Luxen de7c56c6bc remove remaining NULL pointers by nullptrs 2014-06-24 16:50:00 +02:00
Dennis Luxen 0c59ecfa14 remove dead code, produce empty route when origin and destination are the same 2014-06-24 16:09:25 +02:00
Patrick Niklaus f67241a3cb Fix coverity warning in RangeTable 2014-06-24 13:26:27 +02:00
Dennis Luxen 3b2893944c remove non-existing dependency 2014-06-24 12:45:16 +02:00
Dennis Luxen dd7d6df4c6 streamline PBF parsing code 2014-06-24 12:25:19 +02:00
Dennis Luxen efbda436f3 properly cast from int to bool 2014-06-24 11:46:32 +02:00
Dane Springmeyer 2064934939 link -lrt to osrm-prepare 2014-06-23 16:02:58 -07:00
Dennis Luxen b36cf7c450 remove debug output 2014-06-23 17:34:20 +02:00
Dennis Luxen a24dd3dee2 use incremental NN query for Nearest plugin 2014-06-23 17:33:55 +02:00
Dennis Luxen 7b22f08869 remove dead code 2014-06-23 17:32:52 +02:00
Dennis Luxen 840929754a remove debug output 2014-06-23 17:32:24 +02:00
Dennis Luxen 51fd332806 add incremental query to Facades 2014-06-23 16:56:01 +02:00
Dennis Luxen 4d7e0f6b79 use incremental NN query for distance table generation 2014-06-23 16:55:38 +02:00
Dennis Luxen b74a573ec5 add typedef for an array of phantom node vectors 2014-06-23 16:54:57 +02:00
Dennis Luxen 5faf88afdb implement incremental NN query for R-tree 2014-06-23 16:54:31 +02:00
Dennis Luxen 5e1110930e use proper floating point literal instead of implicit cast from int 2014-06-23 14:42:37 +02:00
Dennis Luxen f11adf5f80 fix signed/unsigned comparison 2014-06-23 14:35:09 +02:00
Dennis Luxen 40a71e09a6 use an explicit downcast to initialize variable 2014-06-23 13:22:46 +02:00
Dennis Luxen 1231847a3c replace hashmap with a dummy vector based implementation as the number of tags per object is tiny 2014-06-23 13:22:14 +02:00
Dennis Luxen b06a73e893 replace hashmap with a dummy vector based implementation as the number of tags per object is tiny 2014-06-23 13:21:56 +02:00
Dennis Luxen f99f194927 use proper interface of HashTable, use prefix increment 2014-06-23 12:13:01 +02:00
Dennis Luxen eac7d07ef6 rename variables to cut OCLint warnings 2014-06-23 12:11:56 +02:00
Dennis Luxen 60d70a9f4c fix leak on shutdown 2014-06-20 17:32:20 +02:00
Dennis Luxen c944783590 don't downcast from std:.size_t to unsigned 2014-06-20 17:32:03 +02:00
Dennis Luxen 8104a8aea1 reformat to cut long line 2014-06-20 16:49:33 +02:00
Dennis Luxen a4db678895 reformat to cut long line 2014-06-20 16:48:34 +02:00
Dennis Luxen da33d02461 reformat to cut long line 2014-06-20 16:47:09 +02:00
Dennis Luxen 9b4071006e reformat to cut long line 2014-06-20 16:39:58 +02:00
Dennis Luxen b3cdd5b3bf reformat to cut long line 2014-06-20 16:36:15 +02:00
Dennis Luxen 93e53ec612 fix comparison to accept 0 distance results in distance table 2014-06-19 19:52:15 +02:00
Dennis Luxen ea8319e2b9 add more asserts to test for data corruption during MBR merging in StaticRTree 2014-06-19 17:52:59 +02:00
Dennis Luxen 2fae253c62 use std::size_t consistently and avoid possible loss of data 2014-06-19 11:14:28 +02:00
Dennis Luxen e204b257ad add proper size_t->unsigned cast 2014-06-19 10:40:24 +02:00
Dennis Luxen dd83d8ed61 make size of table compact 2014-06-19 10:40:04 +02:00
Dennis Luxen 61f3d85af1 add even more cast sanity 2014-06-18 11:49:01 +02:00
Dennis Luxen 804e515847 stream line code a bit in Reply 2014-06-18 11:25:56 +02:00
Dennis Luxen 35977b6c7f add explicit cast 2014-06-18 11:24:50 +02:00
Dennis Luxen 23f1d3d83b add explicit cast 2014-06-18 11:20:24 +02:00
Dennis Luxen b8ea935424 cast bearing to unsigned 2014-06-18 11:17:51 +02:00
Dennis Luxen 7c0866f626 stream line code a bit in Reply 2014-06-18 11:17:23 +02:00
Dennis Luxen 0f2062b739 round bearing value to integers 2014-06-18 11:00:13 +02:00
Dennis Luxen e91454eeee use auto keyword to deduce types automatically 2014-06-18 10:59:43 +02:00
Dennis Luxen 58134200df use float consistently in DescriptionFactory 2014-06-18 10:44:46 +02:00
Dennis Luxen f6bab21928 use double consistently in JSONDescriptor 2014-06-18 10:44:09 +02:00
Dennis Luxen 011910811b use float consistently in Contractor 2014-06-18 10:43:26 +02:00
Dennis Luxen bbc0ba147a reformat Descriptors/JSONDescriptor.h 2014-06-18 10:15:38 +02:00
Dennis Luxen 922a4331db reformat source file datastore.cpp 2014-06-18 09:42:45 +02:00
Dennis Luxen 8f7f1e2683 reformat source file Server/RequestHandler.cpp 2014-06-18 09:40:53 +02:00
Dennis Luxen 1980cc007f cast parameters before c'ting Coordinate 2014-06-17 19:10:26 +02:00
Dennis Luxen 39611f7477 couple more explicit casts 2014-06-17 18:52:01 +02:00
Dennis Luxen e3d659576f cast std::size_t and unsigned in a proper way 2014-06-17 16:01:06 +02:00
Dennis Luxen 46d4670b74 cast float to unsigned in a proper way 2014-06-17 16:00:42 +02:00
Dennis Luxen 15ca6d5ca9 use explicit casts where feasible 2014-06-17 15:57:03 +02:00
Dennis Luxen 58f23cda4a use explicit casts where feasible 2014-06-17 15:51:43 +02:00
Dennis Luxen a58d8420a2 add some formatting whitespace 2014-06-17 15:48:47 +02:00
Dennis Luxen 96f834fb81 use explicit casts 2014-06-17 15:47:59 +02:00
Dennis Luxen 86617eccb1 use explicit casts 2014-06-17 15:47:40 +02:00
Dennis Luxen f2936d1c2d add disabled HipChat notifications to Windows build 2014-06-17 15:47:16 +02:00
Dennis Luxen 0fc8e04ab5 use proper data types to avoid uncessary casts 2014-06-17 15:30:28 +02:00
Dennis Luxen a65e2d3115 downcast size_t to unsigned 2014-06-17 13:19:59 +02:00
Dennis Luxen ca6e25b11c make many more conversions explicit 2014-06-17 13:18:55 +02:00
Dennis Luxen 3ec6a6f5bc remove ignored parameter 2014-06-17 13:09:58 +02:00
Dennis Luxen c12fae47e7 allow results at high latitudes to be a bit more imprecise 2014-06-17 13:00:13 +02:00
Dennis Luxen 604d2c698b replace fp divisions by multiplications 2014-06-17 12:50:29 +02:00
Dennis Luxen 5d14016366 add static_casts to avoid unnecessary conversion from double to float 2014-06-17 12:37:55 +02:00
Dennis Luxen b112becbba use explicit casts to mitigate MSVC warnings 2014-06-17 12:15:40 +02:00
Dennis Luxen e68a09fb3c fix windows deploy on develop branch, partially fixes #1085 2014-06-16 15:13:19 +02:00
Dennis Luxen 30e9b4513a Merge branch 'alex85k-develop' into develop 2014-06-16 13:43:26 +02:00
alex85k 671b14dac0 pack only develop version to zip on AppVeyor 2014-06-16 16:02:14 +06:00
Porjo 82e99988e8 Change content-type header for JSON data 2014-06-16 09:29:34 +02:00
Dennis Luxen 313a7ed7fa Merge pull request #1076 from alex85k/patch-mingw
Add Mingw support (tune libraries and disable cpuid with #ifdef)
2014-06-15 21:55:18 +02:00
Dennis Luxen cf3365574e Merge branch 'TheMarex-thread-control' into develop 2014-06-15 12:35:26 +02:00
Dennis Luxen 0e1f6f50ea Merge branch 'thread-control' of https://github.com/TheMarex/Project-OSRM into TheMarex-thread-control 2014-06-15 12:35:15 +02:00
Dennis Luxen 5b6518d4a9 Merge branch 'TheMarex-diffencoding' into develop 2014-06-15 12:10:18 +02:00
Patrick Niklaus c009dce591 Another VC2013 fix 2014-06-15 11:42:59 +02:00
Patrick Niklaus 40e2d7932b Fix VC2013 issues 2014-06-15 11:29:36 +02:00
Patrick Niklaus e29b7a6eae Fix some minor style issues 2014-06-15 11:04:10 +02:00
Patrick Niklaus a3e9cbc000 Allow user to force thread number
This allows the user to do (potentially) stupid things, but warns him.
The default is TBBs default, so probably the right thing.
To enforce thread numbers in extractor it must be passed to the child
threads.
2014-06-14 17:02:43 +02:00
Patrick Niklaus aedcc2ff40 Add array inlcude 2014-06-12 22:01:23 +02:00
Patrick Niklaus 4c17aeb180 Removed SSE code in RangeTable to rely on compiler optimazation 2014-06-12 22:01:23 +02:00
Patrick Niklaus ef60ae652c Fix edge cases in RangeTable 2014-06-12 22:01:23 +02:00
Patrick Niklaus 1d62ed028e Fix off-by-one since back() gives last value inside [begin,end) 2014-06-12 22:01:23 +02:00
Patrick Niklaus 50bf7694c2 Constify some parts of RangeTable 2014-06-12 22:01:22 +02:00
Patrick Niklaus 807f1d7c1c Initial support for SharedDataFacade
SharedDataLayout was refactored to include canary values at the
boundaries of each memory block. This makes it easy to detect overruns
and block-size mismatches between osrm-datastore and the
SharedDataFacade.
2014-06-12 22:01:22 +02:00
Patrick Niklaus 7a7d0c09d9 Integrate RangeTable into server 2014-06-12 22:00:03 +02:00
Patrick Niklaus f90ce77da4 Use differential encoding for name offsets
Each name is represented as an integer range in a vector of chars.
Instead of storing the absolute offset inside this array, we can store
only the offset to the previous entry (the string size). By doing this we reduce
the number of bytes need to store an offset from 4 to 1 bytes (if we
set a maximum string length of 255).
This is however slower, since the absolute offset must be computed on
each querry by summing up all previous lengths. To limit the
performance inpact we only do this for blocks of a certain size (16).
2014-06-12 22:00:03 +02:00
Dennis Luxen d27ac27bc7 remove one fwd decl, add more comments to Connection 2014-06-12 13:46:07 +02:00
Dennis Luxen 44c6a64bf4 make c'tor of NodeInfo explicit 2014-06-11 18:26:34 +02:00
Dennis Luxen 2d6eae9391 make conversion explicit 2014-06-11 18:15:36 +02:00
Dennis Luxen ba440550a6 make conversion explicit 2014-06-11 18:15:31 +02:00
Dennis Luxen 8e24fee9da explicitly cast from int to bool 2014-06-11 17:44:50 +02:00
alex85k 1148652101 Add Mingw support (tune libraries and disable cpuid with #ifdef) 2014-06-11 20:58:53 +06:00
Dennis Luxen ed01eeaeb3 reformat SharedMemoryFactory according to code guidelines 2014-06-11 15:22:51 +02:00
Dennis Luxen 096f187d6f remove empty line 2014-06-11 15:19:11 +02:00
Dennis Luxen fa35eb1959 adapt for merge, add deployment details 2014-06-11 15:17:51 +02:00
Dennis Luxen 8d89d30c74 Merge branch 'alex85k-win-038' into develop 2014-06-11 15:15:05 +02:00
alex85k f1bde40939 add appveyor.yml template 2014-06-11 18:38:03 +06:00
alex85k 4e7ccaa298 use std::memcpy instead of std::copy (avoid checked iterators assertions) 2014-06-11 18:38:02 +06:00
alex85k d0284991ed patch Ruby files for successful testing on Windows 2014-06-11 18:38:01 +06:00
alex85k c4998990e5 disable io-benchmark on Windows 2014-06-11 18:38:01 +06:00
alex85k 42d3ee9b94 workaround for std::packaged_task<void()> problem on MSVC 2014-06-11 18:38:00 +06:00
alex85k be5c3e41e1 Replace sizeof asserts with warning on Windows 2014-06-11 18:37:26 +06:00
alex85k 3282d410c4 Add basic shared memory support for Windows OS 2014-06-11 18:15:17 +06:00
Alexei Kasatkin 75303c95f8 Avoid constexpr by #ifdef (not supported in MSVC18) 2014-06-11 18:15:16 +06:00
Alexei Kasatkin 0209272831 fix includes and definitions (avoid unistd.h, isatty, fix min,max, round and M_PI) 2014-06-11 18:15:15 +06:00
Alexei Kasatkin 0e16c4ed97 Add more Boost libraries on Windows, fix TBB debug linking, stop building
on old Microsoft compilers
2014-06-11 18:15:14 +06:00
Dennis Luxen e49720f34a add include 2014-06-11 13:44:10 +02:00
Dennis Luxen 8aee371d81 further include untangling, chops 5sec compile time 2014-06-11 12:25:57 +02:00
Dennis Luxen 71c4f81b59 avoid signed/unsigned comparison 2014-06-10 18:08:58 +02:00
Dennis Luxen 3127fafc88 Merge branch 'patch-6' of https://github.com/alex85k/Project-OSRM into develop 2014-06-10 17:40:56 +02:00
Dennis Luxen 4e6bdf28cc fixes #1041, some only_ turn restrictions are inverted under certain conditions 2014-06-10 17:26:22 +02:00
Dennis Luxen 621a5a86a0 fixes #1041, some only_ turn restrictions are inverted under certain conditions 2014-06-10 17:26:05 +02:00
Dennis Luxen d80c8cbd2f add another turn restriction test 2014-06-10 17:23:24 +02:00
Dennis Luxen 686f1aeeb2 reformat some code 2014-06-10 17:23:07 +02:00
alex85k e27a69bab7 Use one more .string().c_str() call 2014-06-10 20:34:21 +06:00
Dennis Luxen 4ee2e1d049 fix long line 2014-06-10 10:49:45 +02:00
Dennis Luxen 2102648102 fix short variable name 2014-06-10 10:48:43 +02:00
Dennis Luxen 8611e40172 Merge branch 'TheMarex-fix-cucumber' into develop 2014-06-09 18:41:37 +02:00
Dennis Luxen 7d5b88fff8 Merge branch 'fix-cucumber' of https://github.com/TheMarex/Project-OSRM into TheMarex-fix-cucumber 2014-06-09 18:41:18 +02:00
Dennis Luxen cfd9aa31a9 add algorithm include 2014-06-09 18:32:07 +02:00
Dennis Luxen 62aea4c321 refactored function names 2014-06-09 18:10:46 +02:00
Dennis Luxen f75fcb3041 refactor RequestHandler to remove code duplication, nested blocks and object copies 2014-06-09 18:06:23 +02:00
Dennis Luxen 971c557d85 explicitly initialize Header member 2014-06-09 17:58:17 +02:00
Dennis Luxen ea05aa225e rename some function names in Reply 2014-06-09 17:57:35 +02:00
Dennis Luxen 56cdabff6a add move c'tor to Header 2014-06-09 17:57:03 +02:00
Dennis Luxen 15f62e680a use inplace construction for Headers instead of explicit objects and copying 2014-06-09 17:55:16 +02:00
Dennis Luxen 0af4e16c21 use inplace construction for Headers instead of explicit objects and copying 2014-06-09 17:54:46 +02:00
Dennis Luxen c7b90bac1a add explicit unsigned->string conversion 2014-06-09 17:50:50 +02:00
Patrick Niklaus 4b81331d53 Don't reset response, so log_fail won't crash cucumber 2014-06-09 14:33:30 +02:00
Dennis Luxen 47ab0cbf62 reduce some code duplication 2014-06-09 12:11:44 +02:00
Dennis Luxen f5b079b8e7 add more comments to reduce NCSS number 2014-06-09 11:58:23 +02:00
Emil Tin 21c4691d40 cuke: make File.tail utility more robust 2014-06-08 12:06:34 +02:00
Dennis Luxen 3726706608 remove another superflous include 2014-06-06 19:19:45 +02:00
Dennis Luxen 28a53aa147 remove superflous include 2014-06-06 19:18:44 +02:00
Dennis Luxen 2ad572490c const as const can 2014-06-06 18:06:05 +02:00
Dennis Luxen 0ed9caf969 fix a couple of implicit signed/unsigned conversions 2014-06-06 18:05:07 +02:00
Dennis Luxen 63ee376f71 removing constexpr at one position 2014-06-06 18:01:01 +02:00
Dennis Luxen 67bcb98a84 make some constants explicit floats to cut down on MSVC conversion warnings 2014-06-06 15:39:29 +02:00
Dennis Luxen 9cd91ae99c Merge pull request #1066 from alex85k/patch-path-cstr
Obtain char* from boost::filesystem::path on all systems
2014-06-06 12:02:32 +02:00
Dennis Luxen d111a0e5e6 guard against an empty alternative path in ExtractRouteNames 2014-06-06 11:50:14 +02:00
Dennis Luxen 11d4c04cea removed left-overs from win/, i.e. a previous windows porting attempt 2014-06-06 11:33:47 +02:00
Dennis Luxen 01773c2a00 fix and refactor the selection of RouteNames 2014-06-06 11:30:12 +02:00
alex85k 1079bf7843 sort vectors before using std::set_difference
discussed in https://github.com/DennisOSRM/Project-OSRM/pull/998#issuecomment-45238338
The vectors are better to be sorted up to ``name_id_comperator`` before running std::set_difference. Elsewhere we get debug checked iterator assertions on Windows and theretically possible incorrect results.
2014-06-06 10:27:35 +02:00
Dennis Luxen 05bcfd2c1c Merge pull request #1065 from alex85k/patch-skip-zero-rw
skip zero bytes reading or wrtiting
2014-06-06 10:22:49 +02:00
Alexei Kasatkin 5357a6a4fd get char* from boost::filesystem::path 2014-06-05 23:48:54 +06:00
Alexei Kasatkin b6787b0014 safeguard: do not read/write 0 bytes (iostream) 2014-06-05 23:16:19 +06:00
Dennis Luxen a32116d24c Merge pull request #1063 from alex85k/patch-6
simplify static asserts
2014-06-05 18:58:08 +02:00
alex85k a03b698e5a simplify static asserts
Simplify static asserts to make them compatible with older compilers and MSVC 2013
2014-06-05 22:55:22 +06:00
Dennis Luxen fa0c5db18c include <string> as it is needed 2014-06-05 18:29:22 +02:00
Dennis Luxen bc063ded7a make sure result is always > 0, hits when origin and destination are on the same one-way segment in reversed order 2014-06-05 18:28:54 +02:00
Dennis Luxen 846505cbc8 Merge pull request #1051 from TheMarex/linker-fix
Fix linking for linux
2014-06-05 18:14:33 +02:00
Dennis Luxen 964118d1d6 add more comments and rename a couple of badly named variables 2014-06-05 17:27:00 +02:00
Patrick Niklaus c43b67ea2e Fixes build using gcc 4.9 with LTO.
Otherwise sem_close is not found.
2014-06-05 17:26:19 +02:00
Dennis Luxen f68af08931 fix short variable names and long lines 2014-06-05 15:40:52 +02:00
Dennis Luxen cdd5a41965 remove duplicate edges from NodeBasedGraph 2014-06-05 15:33:24 +02:00
Dennis Luxen e13ee59af3 remove some code lint 2014-06-05 15:14:39 +02:00
Dennis Luxen 9eb183e01d Merge branch 'alex85k-patch-timing' into develop 2014-06-05 11:22:52 +02:00
Dennis Luxen 1163417722 Merge branch 'patch-timing' of https://github.com/alex85k/Project-OSRM into alex85k-patch-timing
Conflicts:
	extractor.cpp
2014-06-05 11:22:26 +02:00
Dennis Luxen 3edc48cda5 Merge branch 'alex85k-patch-6' into develop 2014-06-05 11:04:35 +02:00
Dennis Luxen 2c01425ee5 Merge branch 'patch-6' of https://github.com/alex85k/Project-OSRM into alex85k-patch-6 2014-06-05 11:04:17 +02:00
Dennis Luxen ed9c72814f Merge pull request #1058 from alex85k/patch-4
add a safe-guard against bad input
2014-06-05 11:02:39 +02:00
Dennis Luxen adbbe2b097 fix broken transmission of checksum/hinting mechanism on shared memory 2014-06-05 10:55:27 +02:00
alex85k 7335e0809a Globally rename UUID to FingerPrint 2014-06-05 10:31:19 +02:00
alex85k 75dabb75e2 Use TimingUtil.h for all time measurement,
and make TimingUtil.h Windows-compatible
2014-06-04 19:52:34 +06:00
alex85k 15adcd24be Remove extra mutex unlocking in ConcurrentQueue.h
As discussed in https://github.com/DennisOSRM/Project-OSRM/pull/998 , unlocking the mutex is performed on destruction. Second unlocking gives an assertion (for debug version) for Windows and FreeBSD 10.
2014-06-04 18:01:48 +06:00
alex85k e98ba99331 add a safe-guard against bad input
do not write empty original_edge_data_vector to file
2014-06-04 16:02:18 +06:00
Dennis Luxen 11459d38d0 Merge pull request #1052 from alex85k/patch-4
add a cmake option WITH_TOOLS
2014-06-03 14:58:36 +02:00
alex85k baf4ea2e8c add a cmake option WITH_TOOLS 2014-06-03 18:38:33 +06:00
Dennis Luxen 6a29168c14 use EdgeWeight typedef where possible 2014-06-03 11:28:39 +02:00
Dennis Luxen a4689c7a27 add some comments to reduce NCSS complexity 2014-06-03 10:49:25 +02:00
Dennis Luxen 8fda5a187b rename variable to a shorter name 2014-06-03 10:44:09 +02:00
Dennis Luxen 7b78270f4b safe-guard against broken input data 2014-06-02 19:23:50 +02:00
Dennis Luxen afd3599a9c remove depth of nested block 2014-06-02 18:18:27 +02:00
Dennis Luxen 4bc8562cd0 further reduce lint 2014-06-02 18:18:03 +02:00
Dennis Luxen 11fed4c06c remove variable name lint 2014-06-02 16:05:19 +02:00
Dennis Luxen 9416a983c6 rename one char variable names 2014-06-02 16:04:44 +02:00
Dennis Luxen 8108c6320d use lambda for complex initialization 2014-06-02 15:56:06 +02:00
Dennis Luxen b40b931568 unlinting DouglasPeucker 2014-06-02 09:48:43 +02:00
Dennis Luxen 282f70ea91 remove debug output 2014-05-30 19:48:34 +02:00
Dennis Luxen a671f63a3e Apply strong heuristics to speed up line generalization 2014-05-30 19:10:37 +02:00
Dennis Luxen f3ad14cb7f use integer approximation for polyline generalization 2014-05-30 14:34:04 +02:00
Dennis Luxen 21eb5b661d add integer based approximation for perpendicular distance 2014-05-30 14:33:37 +02:00
Dennis Luxen 87fe073118 re-layout parameters 2014-05-30 13:30:54 +02:00
Dennis Luxen 507dadebf4 fix a couple of variable names 2014-05-30 10:15:35 +02:00
Dennis Luxen 7dac8c621c fix a couple of OCLint warning, i.e. short variable names and useless parantheses 2014-05-30 10:01:55 +02:00
Dennis Luxen 19f4ebf3c5 make threshold values floats by construction 2014-05-30 10:01:18 +02:00
Dennis Luxen c21b40bebc further renaming of variable names, reduces legacy lint 2014-05-29 19:25:17 +02:00
Dennis Luxen 0766c3c62d refactor member names in ImportEdge 2014-05-29 18:46:20 +02:00
Dennis Luxen cc40eb709c moved ImportNode/Edge into compile units 2014-05-29 18:31:20 +02:00
Dennis Luxen 3625308585 moved ImportNode/Edge into compile units 2014-05-29 18:31:02 +02:00
Dennis Luxen df3a7676eb streamline branch-and-bound query code in R-tree 2014-05-29 17:16:24 +02:00
Dennis Luxen 8f6077e973 add proper c'tor to PhantomNode 2014-05-29 17:15:41 +02:00
Dennis Luxen e6689144c4 remove debug output 2014-05-29 16:27:08 +02:00
Dennis Luxen a67de410bf move TreeNode exploration into its own function, fix performance regression 2014-05-29 15:36:14 +02:00
Dennis Luxen 54ec1a89de use complex const variable initialization w/ lambda functions instead of conditional operator 2014-05-29 12:47:03 +02:00
Dennis Luxen 4b5f744c6f move distance calculations to float 2014-05-28 18:34:48 +02:00
Dennis Luxen df978345d7 rename start->source 2014-05-28 18:20:47 +02:00
Dennis Luxen facc07c60d use correct edge weight type in PathData 2014-05-28 18:20:29 +02:00
Dennis Luxen 2f203ac22c rename start->source 2014-05-28 18:19:27 +02:00
Dennis Luxen cc864191b8 remove some unneeded flags when compiling with clang 2014-05-28 18:18:57 +02:00
Dennis Luxen 547455245e link against UUID (needed in node-OSRM) 2014-05-28 16:09:51 +02:00
Dennis Luxen b0d7449bb4 add type traits include 2014-05-28 12:53:18 +02:00
Dennis Luxen aed04c7d55 server cast int to string only where it is needed 2014-05-28 12:34:48 +02:00
Dennis Luxen bb5973f2fd rename variable 2014-05-28 12:34:24 +02:00
Dennis Luxen f801fd1f0d fix inverted logic 2014-05-28 12:06:57 +02:00
Dennis Luxen 44ca12ead6 fix inverted logic 2014-05-28 12:05:42 +02:00
Dennis Luxen 9c48389f74 collapse if statements 2014-05-28 12:03:07 +02:00
Dennis Luxen acefb5a5f3 remove debug output 2014-05-27 19:05:37 +02:00
Dennis Luxen 3d691a3aec implements #947, free osrm-datastore's shared memory 2014-05-27 18:14:43 +02:00
Dennis Luxen 38ebdbb563 implements #949, wrong duration on first segment 2014-05-27 16:54:10 +02:00
Dennis Luxen 1090325c31 remove superflous check 2014-05-27 14:50:59 +02:00
Dennis Luxen f8ba4b9312 use C++11 shrinktofit() instead of swap tricks 2014-05-27 12:16:53 +02:00
Dennis Luxen 49a1dfff60 fix off-by-one issue related to #1020 2014-05-27 12:09:05 +02:00
Dennis Luxen 5f4d342d45 move last leg handling into DescribeLeg() function 2014-05-27 11:48:19 +02:00
Dennis Luxen e1c1f79068 remove todo marker 2014-05-27 11:44:47 +02:00
Dennis Luxen a716fa252f implements #792 2014-05-27 11:16:55 +02:00
Dennis Luxen 0b12e4d8be remove assert 2014-05-27 10:45:57 +02:00
Dennis Luxen 6ad6c94355 further CMakeLists.txt lint removal 2014-05-26 18:42:29 +02:00
Dennis Luxen 78270c8155 fix unneeded variable warning in release build 2014-05-26 18:40:21 +02:00
Dennis Luxen 4573ae21e6 unlinting CMakeLists.txt 2014-05-26 18:36:11 +02:00
Dennis Luxen 0ab6220635 add some more constness 2014-05-26 18:35:37 +02:00
Dennis Luxen 3b51976b96 remove unneeded include 2014-05-26 18:11:32 +02:00
Dennis Luxen c35211b2f6 add some const keywords where applicable 2014-05-26 17:37:44 +02:00
Dennis Luxen f62515e13b commented assertion that is triggered on trivial instances 2014-05-26 16:03:08 +02:00
Dennis Luxen 7f2daf8926 some variables renamed to replace camel case 2014-05-26 16:02:15 +02:00
Dennis Luxen 0325861ef3 remove an unneeded parameter 2014-05-26 15:31:30 +02:00
Dennis Luxen 37f8285a6e implements #1020 2014-05-26 15:31:09 +02:00
Dennis Luxen d3906cffdc add property to mark end of leg 2014-05-26 15:30:06 +02:00
Dennis Luxen bee1c77efe make variable const 2014-05-26 15:29:28 +02:00
Dennis Luxen 7250a82286 remove dead code 2014-05-26 13:08:10 +02:00
Dennis Luxen 984457f9c6 remove useless parantheses, straighten includes 2014-05-26 12:49:49 +02:00
Dennis Luxen 5db23f7e46 make short variable names more legible 2014-05-26 12:49:24 +02:00
Dennis Luxen f4f49b2b46 remove unused variable 2014-05-26 12:42:47 +02:00
Dennis Luxen 58b35f6e2d make short variable names more legible 2014-05-26 12:41:25 +02:00
Dennis Luxen b51ad16756 remove useless parantheses 2014-05-26 12:37:00 +02:00
Dennis Luxen d790bda7d2 implements #986, streamline error messages 2014-05-26 12:33:35 +02:00
Dennis Luxen 15ce232f61 partially fixes #1034 2014-05-26 11:59:13 +02:00
Dennis Luxen d999a47600 partially fixes #1034 2014-05-26 11:47:01 +02:00
Dennis Luxen 644286111f add test for #1034 2014-05-26 11:46:01 +02:00
Dennis Luxen 917b1cbd6c fix index of instructions 2014-05-26 11:38:35 +02:00
Dennis Luxen 6d1b585212 remove unneeded output 2014-05-26 10:19:45 +02:00
Dennis Luxen 6ca35a6264 remove debug output 2014-05-26 09:25:42 +02:00
Dennis Luxen 0290b1b4e0 Merge branch 'dmbreaker-develop' into develop 2014-05-23 14:50:23 +02:00
Dennis Luxen 1d86bf3e56 Merge branch 'develop' of https://github.com/dmbreaker/Project-OSRM into dmbreaker-develop 2014-05-23 14:50:05 +02:00
Dennis Luxen 3fd8ab8d3a use parallel sorting when loading OSRM data files 2014-05-23 14:49:50 +02:00
Dennis Luxen d240ae3b03 sort edges in StaticGraph in parallel 2014-05-23 14:32:40 +02:00
Emil Tin b875765c52 update test to avoid single ring 2014-05-23 12:52:32 +02:00
shipenok 2bdec31219 minor fix to open result in browser 2014-05-23 14:27:55 +04:00
Emil Tin a9eebdb1fa fix test related to via points and #1034 2014-05-23 11:45:18 +02:00
Emil Tin b25f3a9e91 update test related to via points and #1034 2014-05-23 11:42:44 +02:00
Emil Tin 06f3375a97 test showing bug related to via points. see #1034 2014-05-23 11:23:11 +02:00
Dennis Luxen 5057ae920c replace a couple of std::sort calls with tbb::parallel_sort 2014-05-22 19:07:29 +02:00
Dennis Luxen 6a03f13d55 fixes #1032:
- remove left-overs from OpenMP
- replace omp_* calls with TBB equivalents
2014-05-22 18:39:11 +02:00
Dennis Luxen 20cbfd95d6 remove OpenMP references from CMakeLists.txt 2014-05-22 18:39:11 +02:00
Dennis Luxen 885dbe1e65 Merge pull request #1028 from TheMarex/tbb-port
Port from OpenMP to TBB
2014-05-22 16:57:06 +02:00
Dennis Luxen 7d7cce5c72 add better and more precise comments to Restrictionmap 2014-05-22 14:53:53 +02:00
Dennis Luxen 0c66f84555 add static assertions to SearchEngine 2014-05-22 14:41:27 +02:00
Dennis Luxen 044e41c079 make temporary variables const 2014-05-22 14:41:02 +02:00
Dennis Luxen 8dc631e13c pull math functions from std namespace 2014-05-22 14:22:10 +02:00
Dennis Luxen d93b4feb99 add some static asserts to guard against memory usage regressions 2014-05-22 12:41:25 +02:00
Dennis Luxen 0b873f590c fix typo in error message 2014-05-22 12:24:34 +02:00
Dennis Luxen f52d637f58 do less work when compressing geometries 2014-05-22 11:41:32 +02:00
Patrick Niklaus e2daf5c2fc Make some temporary variables const 2014-05-21 21:49:22 +02:00
Patrick Niklaus bef113001a Add TBB to travis.ymk 2014-05-21 21:49:22 +02:00
Patrick Niklaus f0b403bc2e Set requested threads in TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus a21fb5fc89 Use append operator instead of function, because function is inplace. 2014-05-21 21:49:22 +02:00
Patrick Niklaus bbc0424563 Set number of threads in TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus f487845e9d Port Contractor to TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus 77641a9fce Port StaticRTree to use TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus 56d93eb18b Replace omp atomic with std variant 2014-05-21 21:49:22 +02:00
Patrick Niklaus da1fd96d4e Port extractor to TBB 2014-05-21 21:49:22 +02:00
Dennis Luxen d1fdc7061f fix signed/unsigned comparison 2014-05-21 14:23:09 +02:00
Dennis Luxen 2822382797 Merge pull request #1030 from DennisOSRM/features/json-generator
Distance tables and JSON generator
2014-05-21 14:10:03 +02:00
Dennis Luxen 35c9021bdf reduce debug verbosity in RestrictionMap 2014-05-21 12:39:52 +02:00
Dennis Luxen 493b13364f move geographical distance computation to floats 2014-05-21 12:33:54 +02:00
Dennis Luxen a8ff3231a8 reduce debug verbosity 2014-05-21 12:33:14 +02:00
Dennis Luxen c2a750a690 use 100 locations at max for dist table 2014-05-21 12:29:45 +02:00
Dennis Luxen 6a9541833a add a leg to roundabout to remove edge case 2014-05-21 10:47:34 +02:00
Dennis Luxen 9117b45899 move more distance calculations to float 2014-05-21 10:03:30 +02:00
Dennis Luxen 812cf36d52 use floats instead of doubles for distance computations 2014-05-20 19:29:09 +02:00
Dennis Luxen 4aa7420d6a remove unneeded includes 2014-05-20 18:54:03 +02:00
Dennis Luxen 1802839a22 add approximator for perpendicular distance 2014-05-20 16:23:47 +02:00
Dennis Luxen 9a2d701e2e fix issue #1025:
- add function to count directed outgoing edges
- generate correct instruction for staying on a roundabout
- move test from @bug namespace to the general one
2014-05-20 15:40:14 +02:00
Dennis Luxen 69ad3f3365 add curly braces to one line if 2014-05-20 15:37:18 +02:00
Dennis Luxen d53eb881c2 revert to old boost based regex as GCC does not properly implement it prior to GCC 4.90 2014-05-20 14:33:03 +02:00
Dennis Luxen e28e45f38e remove unused variable 2014-05-20 14:33:03 +02:00
Dennis Luxen bf6ca22b00 fix #1021, always check if files exist 2014-05-20 14:33:03 +02:00
Dennis Luxen b8acbae3e8 fix #1021, always check if files exist 2014-05-20 14:33:03 +02:00
Dennis Luxen 4ec9f2c00f fix #1021, always check if files exist 2014-05-20 14:33:03 +02:00
Dennis Luxen 4fc329a1eb remove superflous way in test setup 2014-05-20 14:33:02 +02:00
Dennis Luxen 0574a60bc2 replace boost::unordered_map, move hash function for pairs into its own header 2014-05-20 14:33:02 +02:00
Dennis Luxen e490c4afed use consistent typedef'ed types 2014-05-20 14:33:02 +02:00
Dennis Luxen d028a30f87 fixes issue #1019:
- fix ignored turn restriction on chains of degree-2 nodes
- add a cucumber test to test for potential regressions
2014-05-20 14:33:02 +02:00
Dennis Luxen 75a2d4d00a minor code refactoring, wip 2014-05-20 14:33:02 +02:00
Dennis Luxen a122a1e8c7 remove comment 2014-05-20 14:33:02 +02:00
Dennis Luxen 8fe09c85b6 move atan2 lookup into trig header 2014-05-20 14:33:02 +02:00
Dennis Luxen bc951de2a5 use trig functions from std namespace 2014-05-20 14:33:01 +02:00
Dennis Luxen c970cd13cc flip bearings by 180 2014-05-20 14:33:01 +02:00
Dennis Luxen 8983c0f927 move GetBearing(.) function into FixedPointCoordinate 2014-05-20 14:33:01 +02:00
Dennis Luxen a47467f29b store facade ptr in c'tor, save a param in sub-sequent function calls 2014-05-20 14:33:01 +02:00
Dennis Luxen ef206eb4d9 clean up code a bit 2014-05-20 14:33:01 +02:00
Dennis Luxen da5eec1c5f refactor route name extraction into its own class, fix name extraction 2014-05-20 14:33:01 +02:00
Dennis Luxen a69b3535a5 fix typo 2014-05-20 14:33:01 +02:00
Dennis Luxen f4c23f3259 fix comparison 2014-05-20 14:33:01 +02:00
Dennis Luxen e36e9fd629 make comparsion explicitly unsigned 2014-05-20 14:33:00 +02:00
Dennis Luxen d2f19353ed remove some debug output 2014-05-20 14:33:00 +02:00
Dennis Luxen 2d498cb88b adapt JSON parsing in tests to allow for omitted fields 2014-05-20 14:33:00 +02:00
Dennis Luxen a80815d57a implements output generation through a dedicated JSON container:
- JSON syntax is not scattered over several files, but one place
- Reduces code duplication
- breaking changes:
  - new property in json(p) formatted response: "found_alternative": True/False
  - returned filenames now response.js(on) or route.gpx
  - /hello plugin returns JSON now
2014-05-20 14:33:00 +02:00
Dennis Luxen acab77f4f8 add simple isValid() function to PhantomNodes 2014-05-20 14:33:00 +02:00
Emil Tin bddad0c57c add test for roundabout with oneone links 2014-05-20 13:27:32 +02:00
Dennis Luxen 3968349480 deactivate LTO on debug build 2014-05-16 15:00:31 +02:00
Dennis Luxen 3ae17761b3 rename variables 2014-05-14 08:54:36 +02:00
Dennis Luxen 9a28bdbf76 reorder some includes 2014-05-14 08:53:26 +02:00
Dennis Luxen e769821e0f use range based for loops to traverse graphs 2014-05-13 16:56:30 +02:00
Dennis Luxen 9b68821f05 move common code into its own header 2014-05-13 13:30:52 +02:00
Dennis Luxen b2adb22b2d remove whitespace 2014-05-13 12:41:40 +02:00
Dennis Luxen 981941edf4 leave early to reduce scope nesting 2014-05-13 12:22:42 +02:00
Dennis Luxen 111dea89a9 use std::abs instead of hand-rolled substitute 2014-05-13 12:22:14 +02:00
Dennis Luxen 2720f4de9c add parantheses to fix compiler warning 2014-05-13 10:22:54 +02:00
Dennis Luxen 21645643b0 minor reformatting 2014-05-13 10:20:39 +02:00
Dennis Luxen c6a07acd90 use std::packaged_task and std::future to simulate boost::thread::timed_join() 2014-05-13 10:03:37 +02:00
Dennis Luxen 1816e6607e remove boost::thread from Server 2014-05-13 10:02:36 +02:00
Dennis Luxen 37dd05a9b5 Merge branch 'TheMarex-atan-perf' into develop 2014-05-13 10:00:45 +02:00
Patrick Niklaus 529997de9b Add atan based on lookup table. Again 6% improvement. 2014-05-13 02:20:33 +02:00
Patrick Niklaus 4f37270300 Simple fix that improves runtime of edge based egde generation by 26% 2014-05-13 01:00:24 +02:00
Dennis Luxen faf9c96442 fix regression in debug build 2014-05-12 18:09:25 +02:00
236 changed files with 15245 additions and 10326 deletions
+3 -1
View File
@@ -36,8 +36,9 @@ Thumbs.db
# build related files #
#######################
/build/
/Util/UUID.cpp
/Util/FingerPrint.cpp
/Util/GitDescription.cpp
/cmake/postinst
# Eclipse related files #
#########################
@@ -79,6 +80,7 @@ stxxl.errlog
/osrm-prepare
/osrm-unlock-all
/osrm-cli
/osrm-check-hsgr
/nohup.out
# Sandbox folder #
+7 -4
View File
@@ -7,13 +7,15 @@ install:
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- sudo add-apt-repository -y ppa:boost-latest/ppa
- sudo apt-get update >/dev/null
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems
- sudo apt-get -q install g++-4.7
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
- sudo apt-get -q install g++-4.8
- sudo apt-get install libboost1.54-all-dev
#luabind
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
#osmosis
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
#cmake
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
before_script:
- rvm use 1.9.3
- gem install bundler
@@ -23,6 +25,7 @@ before_script:
- cmake .. $CMAKEOPTIONS
script:
- make -j 2
- make -j 2 tests
- cd ..
- cucumber -p verify
after_script:
@@ -36,8 +39,8 @@ cache:
- bundler
- apt
env:
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60
notifications:
irc:
channels:
+17 -10
View File
@@ -1,8 +1,7 @@
#ifndef __BFS_COMPONENT_EXPLORER_H__
#define __BFS_COMPONENT_EXPLORER_H__
#ifndef BFS_COMPONENT_EXPLORER_H_
#define BFS_COMPONENT_EXPLORER_H_
#include "../typedefs.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/RestrictionMap.h"
#include <queue>
@@ -13,10 +12,10 @@
template <typename GraphT> class BFSComponentExplorer
{
public:
BFSComponentExplorer(const GraphT &dynamicGraph,
BFSComponentExplorer(const GraphT &dynamic_graph,
const RestrictionMap &restrictions,
const std::unordered_set<NodeID> &barrier_nodes)
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
: m_graph(dynamic_graph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
{
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
}
@@ -24,14 +23,14 @@ template <typename GraphT> class BFSComponentExplorer
/*!
* Returns the size of the component that the node belongs to.
*/
inline unsigned int GetComponentSize(NodeID node)
unsigned int GetComponentSize(const NodeID node) const
{
BOOST_ASSERT(node < m_component_index_list.size());
return m_component_index_size[m_component_index_list[node]];
}
inline unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
/*!
* Computes the component sizes.
@@ -68,10 +67,18 @@ template <typename GraphT> class BFSComponentExplorer
/*!
* Explores the current component that starts at node using BFS.
*/
inline unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
NodeID node,
unsigned current_component)
{
/*
Graphical representation of variables:
u v w
*---------->*---------->*
e2
*/
bfs_queue.emplace(node, node);
// mark node as read
m_component_index_list[node] = current_component;
@@ -94,7 +101,7 @@ template <typename GraphT> class BFSComponentExplorer
const NodeID to_node_of_only_restriction =
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
for (auto e2 = m_graph.BeginEdges(v); e2 < m_graph.EndEdges(v); ++e2)
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
{
const NodeID w = m_graph.GetTarget(e2);
@@ -137,4 +144,4 @@ template <typename GraphT> class BFSComponentExplorer
const std::unordered_set<NodeID> &m_barrier_nodes;
};
#endif
#endif // BFS_COMPONENT_EXPLORER_H_
+101 -45
View File
@@ -25,49 +25,100 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <osrm/Coordinate.h>
#include "DouglasPeucker.h"
#include "../DataStructures/Range.h"
#include "../DataStructures/SegmentInformation.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <cmath>
#include <limits>
#include <algorithm>
namespace {
struct CoordinatePairCalculator
{
CoordinatePairCalculator() = delete;
CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
const FixedPointCoordinate &coordinate_b)
{
// initialize distance calculator with two fixed coordinates a, b
const float RAD = 0.017453292519943295769236907684886f;
first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
}
int operator()(FixedPointCoordinate &other) const
{
// set third coordinate c
const float RAD = 0.017453292519943295769236907684886f;
const float earth_radius = 6372797.560856f;
const float float_lat1 = (other.lat / COORDINATE_PRECISION) * RAD;
const float float_lon1 = (other.lon / COORDINATE_PRECISION) * RAD;
// compute distance (a,c)
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
const float y_value_1 = first_lat - float_lat1;
const float dist1 = sqrt(std::pow(x_value_1, 2) + std::pow(y_value_1, 2)) * earth_radius;
// compute distance (b,c)
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
const float y_value_2 = second_lat - float_lat1;
const float dist2 = sqrt(std::pow(x_value_2, 2) + std::pow(y_value_2, 2)) * earth_radius;
// return the minimum
return static_cast<int>(std::min(dist1, dist2));
}
float first_lat;
float first_lon;
float second_lat;
float second_lon;
};
}
DouglasPeucker::DouglasPeucker()
: douglas_peucker_thresholds({262144., // z0
131072., // z1
65536., // z2
32768., // z3
16384., // z4
8192., // z5
4096., // z6
2048., // z7
960., // z8
480., // z9
240., // z10
90., // z11
50., // z12
25., // z13
15., // z14
5., // z15
.65, // z16
.5, // z17
.35 // z18
: douglas_peucker_thresholds({512440, // z0
256720, // z1
122560, // z2
56780, // z3
28800, // z4
14400, // z5
7200, // z6
3200, // z7
2400, // z8
1000, // z9
600, // z10
120, // z11
60, // z12
45, // z13
36, // z14
20, // z15
8, // z16
6, // z17
4 // z18
})
{
}
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
{
// check if input data is invalid
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
if (input_geometry.size() <= 2)
if (input_geometry.size() < 2)
{
return;
}
input_geometry.front().necessary = true;
input_geometry.back().necessary = true;
{
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
unsigned left_border = 0;
@@ -75,55 +126,60 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
// Sweep over array and identify those ranges that need to be checked
do
{
BOOST_ASSERT_MSG(input_geometry[left_border].necessary,
"left border must be necessary");
BOOST_ASSERT_MSG(input_geometry.back().necessary, "right border must be necessary");
// traverse list until new border element found
if (input_geometry[right_border].necessary)
{
// sanity checks
BOOST_ASSERT(input_geometry[left_border].necessary);
BOOST_ASSERT(input_geometry[right_border].necessary);
recursion_stack.emplace(left_border, right_border);
left_border = right_border;
}
++right_border;
} while (right_border < input_geometry.size());
}
// mark locations as 'necessary' by divide-and-conquer
while (!recursion_stack.empty())
{
// pop next element
const GeometryRange pair = recursion_stack.top();
recursion_stack.pop();
// sanity checks
BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry");
BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
double max_distance = std::numeric_limits<double>::min();
unsigned farthest_element_index = pair.second;
// find index idx of element with max_distance
for (unsigned i = pair.first + 1; i < pair.second; ++i)
int max_int_distance = 0;
unsigned farthest_entry_index = pair.second;
const CoordinatePairCalculator dist_calc(input_geometry[pair.first].location,
input_geometry[pair.second].location);
// sweep over range to find the maximum
for (const auto i : osrm::irange(pair.first + 1, pair.second))
{
const double temp_dist = FixedPointCoordinate::ComputePerpendicularDistance(
input_geometry[i].location,
input_geometry[pair.first].location,
input_geometry[pair.second].location);
const double distance = std::abs(temp_dist);
if (distance > douglas_peucker_thresholds[zoom_level] && distance > max_distance)
const int distance = dist_calc(input_geometry[i].location);
// found new feasible maximum?
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
{
farthest_element_index = i;
max_distance = distance;
farthest_entry_index = i;
max_int_distance = distance;
}
}
if (max_distance > douglas_peucker_thresholds[zoom_level])
// check if maximum violates a zoom level dependent threshold
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
{
// mark idx as necessary
input_geometry[farthest_element_index].necessary = true;
if (1 < (farthest_element_index - pair.first))
input_geometry[farthest_entry_index].necessary = true;
if (1 < (farthest_entry_index - pair.first))
{
recursion_stack.emplace(pair.first, farthest_element_index);
recursion_stack.emplace(pair.first, farthest_entry_index);
}
if (1 < (pair.second - farthest_element_index))
if (1 < (pair.second - farthest_entry_index))
{
recursion_stack.emplace(farthest_element_index, pair.second);
recursion_stack.emplace(farthest_entry_index, pair.second);
}
}
}
+3 -7
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define DOUGLASPEUCKER_H_
#include <stack>
#include <utility>
#include <vector>
/* This class object computes the bitvector of indicating generalized input
@@ -38,22 +39,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* bit indicating if the points is present in the generalization.
* Note: points may also be pre-selected*/
struct FixedPointCoordinate;
struct SegmentInformation;
class DouglasPeucker
{
private:
std::vector<double> douglas_peucker_thresholds;
std::vector<int> douglas_peucker_thresholds;
typedef std::pair<unsigned, unsigned> GeometryRange;
using GeometryRange = std::pair<unsigned, unsigned>;
// Stack to simulate the recursion
std::stack<GeometryRange> recursion_stack;
double ComputeDistance(const FixedPointCoordinate &point,
const FixedPointCoordinate &segA,
const FixedPointCoordinate &segB) const;
public:
DouglasPeucker();
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
+169
View File
@@ -0,0 +1,169 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EXTRACT_ROUTE_NAMES_H
#define EXTRACT_ROUTE_NAMES_H
#include <boost/assert.hpp>
#include <algorithm>
#include <string>
#include <vector>
struct RouteNames
{
std::string shortest_path_name_1;
std::string shortest_path_name_2;
std::string alternative_path_name_1;
std::string alternative_path_name_2;
};
// construct routes names
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
{
private:
SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
const unsigned blocked_name_id) const
{
SegmentT result_segment;
result_segment.length = 0;
for (const SegmentT &segment : segment_list)
{
if (segment.name_id != blocked_name_id && segment.length > result_segment.length && segment.name_id != 0)
{
result_segment = segment;
}
}
return result_segment;
}
public:
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
std::vector<SegmentT> &alternative_path_segments,
const DataFacadeT *facade) const
{
RouteNames route_names;
SegmentT shortest_segment_1, shortest_segment_2;
SegmentT alternative_segment_1, alternative_segment_2;
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
{ return a.length > b.length; };
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
{ return a.name_id < b.name_id; };
if (shortest_path_segments.empty())
{
return route_names;
}
// pick the longest segment for the shortest path.
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
shortest_segment_1 = shortest_path_segments[0];
if (!alternative_path_segments.empty())
{
std::sort(alternative_path_segments.begin(),
alternative_path_segments.end(),
length_comperator);
// also pick the longest segment for the alternative path
alternative_segment_1 = alternative_path_segments[0];
}
// compute the set difference (for shortest path) depending on names between shortest and
// alternative
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), name_id_comperator);
std::set_difference(shortest_path_segments.begin(),
shortest_path_segments.end(),
alternative_path_segments.begin(),
alternative_path_segments.end(),
shortest_path_set_difference.begin(),
name_id_comperator);
std::sort(shortest_path_set_difference.begin(),
shortest_path_set_difference.end(),
length_comperator);
shortest_segment_2 =
PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id);
// compute the set difference (for alternative path) depending on names between shortest and
// alternative
// vectors are still sorted, no need to do again
BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(),
shortest_path_segments.end(),
name_id_comperator));
BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(),
alternative_path_segments.end(),
name_id_comperator));
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
std::set_difference(alternative_path_segments.begin(),
alternative_path_segments.end(),
shortest_path_segments.begin(),
shortest_path_segments.end(),
alternative_path_set_difference.begin(),
name_id_comperator);
std::sort(alternative_path_set_difference.begin(),
alternative_path_set_difference.end(),
length_comperator);
if (!alternative_path_segments.empty())
{
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
alternative_segment_1.name_id);
}
// move the segments into the order in which they occur.
if (shortest_segment_1.position > shortest_segment_2.position)
{
std::swap(shortest_segment_1, shortest_segment_2);
}
if (alternative_segment_1.position > alternative_segment_2.position)
{
std::swap(alternative_segment_1, alternative_segment_2);
}
// fetching names for the selected segments
route_names.shortest_path_name_1 =
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
route_names.shortest_path_name_2 =
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
route_names.alternative_path_name_1 =
facade->GetEscapedNameForNameID(alternative_segment_1.name_id);
route_names.alternative_path_name_2 =
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
return route_names;
}
};
#endif // EXTRACT_ROUTE_NAMES_H
+64 -62
View File
@@ -28,44 +28,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ITERATOR_BASED_CRC32_H
#define ITERATOR_BASED_CRC32_H
#include "../Util/SimpleLogger.h"
#include <iostream>
#if defined(__x86_64__)
#if defined(__x86_64__) && !defined(__MINGW64__)
#include <cpuid.h>
#else
#endif
#include <boost/crc.hpp> // for boost::crc_32_type
inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
#include <iterator>
class IteratorbasedCRC32
{
*ecx = 0;
}
#endif
public:
bool using_hardware() const { return use_hardware_implementation; }
template <class ContainerT> class IteratorbasedCRC32
{
private:
typedef typename ContainerT::iterator IteratorType;
unsigned crc;
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); }
bool use_SSE42_CRC_function;
#if !defined(__x86_64__)
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
#endif
unsigned SoftwareBasedCRC32(char *str, unsigned len)
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
{
#if !defined(__x86_64__)
CRC32_processor.process_bytes(str, len);
return CRC32_processor.checksum();
#else
return 0;
#endif
unsigned crc = 0;
while (iter != end)
{
using value_type = typename std::iterator_traits<Iterator>::value_type;
char *data = (char *)(&(*iter));
if (use_hardware_implementation)
{
crc = compute_in_hardware(data, sizeof(value_type));
}
else
{
crc = compute_in_software(data, sizeof(value_type));
}
++iter;
}
return crc;
}
private:
bool detect_hardware_support() const
{
static const int sse42_bit = 0x00100000;
const unsigned ecx = cpuid();
const bool sse42_found = (ecx & sse42_bit) != 0;
return sse42_found;
}
unsigned compute_in_software(char *str, unsigned len)
{
crc_processor.process_bytes(str, len);
return crc_processor.checksum();
}
// adapted from http://byteworm.com/2010/10/13/crc32/
unsigned SSE42BasedCRC32(char *str, unsigned len)
unsigned compute_in_hardware(char *str, unsigned len)
{
#if defined(__x86_64__)
unsigned q = len / sizeof(unsigned);
@@ -101,44 +116,31 @@ template <class ContainerT> class IteratorbasedCRC32
return ecx;
}
bool DetectNativeCRC32Support()
#if defined(__MINGW64__) || defined(_MSC_VER)
inline void
__get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const
{
static const int SSE42_BIT = 0x00100000;
const unsigned ecx = cpuid();
const bool has_SSE42 = ecx & SSE42_BIT;
if (has_SSE42)
{
SimpleLogger().Write() << "using hardware based CRC32 computation";
}
else
{
SimpleLogger().Write() << "using software based CRC32 computation";
}
return has_SSE42;
*ecx = 0;
}
#endif
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor;
unsigned crc;
bool use_hardware_implementation;
};
struct RangebasedCRC32
{
template<typename Iteratable>
unsigned operator()(const Iteratable &iterable)
{
return crc32(std::begin(iterable), std::end(iterable));
}
public:
IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
bool using_hardware() const { return crc32.using_hardware(); }
unsigned operator()(IteratorType iter, const IteratorType end)
{
unsigned crc = 0;
while (iter != end)
{
char *data = reinterpret_cast<char *>(&(*iter));
if (use_SSE42_CRC_function)
{
crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type));
}
else
{
crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type));
}
++iter;
}
return crc;
}
private:
IteratorbasedCRC32 crc32;
};
#endif /* ITERATOR_BASED_CRC32_H */
+48 -53
View File
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OBJECTTOBASE64_H_
#define OBJECTTOBASE64_H_
#ifndef OBJECT_TO_BASE64_H_
#define OBJECT_TO_BASE64_H_
#include "../Util/StringUtil.h"
@@ -39,61 +39,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
typedef
boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<const char *, 6, 8>
> base64_t;
struct ObjectEncoder
{
using base64_t = boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<const char *, 6, 8>>;
typedef
boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<
std::string::const_iterator>, 8, 6
> binary_t;
using binary_t = boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
8,
6>;
template<class ObjectT>
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
const char * char_ptr_to_object = (const char *)&object;
std::vector<unsigned char> data(sizeof(object));
std::copy(
char_ptr_to_object,
char_ptr_to_object + sizeof(ObjectT),
data.begin()
);
template <class ObjectT>
static void EncodeToBase64(const ObjectT &object, std::string &encoded)
{
const char *char_ptr_to_object = (const char *)&object;
std::vector<unsigned char> data(sizeof(object));
std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin());
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
while(data.size() % 3 != 0) {
++number_of_padded_chars;
data.push_back(0x00);
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
while (data.size() % 3 != 0)
{
++number_of_padded_chars;
data.push_back(0x00);
}
BOOST_ASSERT_MSG(0 == data.size() % 3, "base64 input data size is not a multiple of 3!");
encoded.resize(sizeof(ObjectT));
encoded.assign(base64_t(&data[0]),
base64_t(&data[0] + (data.size() - number_of_padded_chars)));
replaceAll(encoded, "+", "-");
replaceAll(encoded, "/", "_");
}
BOOST_ASSERT_MSG(
0 == data.size() % 3,
"base64 input data size is not a multiple of 3!"
);
encoded.resize(sizeof(ObjectT));
encoded.assign(
base64_t( &data[0] ),
base64_t( &data[0] + (data.size() - number_of_padded_chars) )
);
replaceAll(encoded, "+", "-");
replaceAll(encoded, "/", "_");
}
template <class ObjectT>
static void DecodeFromBase64(const std::string &input, ObjectT &object)
{
try
{
std::string encoded(input);
// replace "-" with "+" and "_" with "/"
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
template<class ObjectT>
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
try {
std::string encoded(input);
//replace "-" with "+" and "_" with "/"
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
std::copy(binary_t(encoded.begin()),
binary_t(encoded.begin() + encoded.length() - 1),
(char *)&object);
}
catch (...)
{
}
}
};
std::copy (
binary_t( encoded.begin() ),
binary_t( encoded.begin() + encoded.length() - 1),
(char *)&object
);
} catch(...) { }
}
#endif /* OBJECTTOBASE64_H_ */
#endif /* OBJECT_TO_BASE64_H_ */
+30 -80
View File
@@ -26,11 +26,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "PolylineCompressor.h"
#include "../DataStructures/SegmentInformation.h"
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
const
#include <osrm/Coordinate.h>
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers,
std::string &output) const
{
const unsigned end = numbers.size();
const unsigned end = static_cast<unsigned>(numbers.size());
for (unsigned i = 0; i < end; ++i)
{
numbers[i] <<= 1;
@@ -39,9 +42,9 @@ void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std
numbers[i] = ~(numbers[i]);
}
}
for (unsigned i = 0; i < end; ++i)
for (const int number : numbers)
{
encodeNumber(numbers[i], output);
encodeNumber(number, output);
}
}
@@ -49,7 +52,7 @@ void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output)
{
while (number_to_encode >= 0x20)
{
int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
output += static_cast<char>(next_value);
if (92 == next_value)
{
@@ -66,97 +69,44 @@ void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output)
}
}
void PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline,
std::string &output) const
JSON::String
PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
{
std::string output;
std::vector<int> delta_numbers;
output += "\"";
if (!polyline.empty())
{
FixedPointCoordinate last_coordinate = polyline[0].location;
delta_numbers.emplace_back(last_coordinate.lat);
delta_numbers.emplace_back(last_coordinate.lon);
for (unsigned i = 1; i < polyline.size(); ++i)
FixedPointCoordinate last_coordinate = {0, 0};
for (const auto &segment : polyline)
{
if (polyline[i].necessary)
if (segment.necessary)
{
int lat_diff = polyline[i].location.lat - last_coordinate.lat;
int lon_diff = polyline[i].location.lon - last_coordinate.lon;
const int lat_diff = segment.location.lat - last_coordinate.lat;
const int lon_diff = segment.location.lon - last_coordinate.lon;
delta_numbers.emplace_back(lat_diff);
delta_numbers.emplace_back(lon_diff);
last_coordinate = polyline[i].location;
last_coordinate = segment.location;
}
}
encodeVectorSignedNumber(delta_numbers, output);
}
output += "\"";
JSON::String return_value(output);
return return_value;
}
void PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordinate> &polyline,
std::string &output) const
JSON::Array
PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
{
std::vector<int> delta_numbers(2 * polyline.size());
output += "\"";
if (!polyline.empty())
JSON::Array json_geometry_array;
for (const auto &segment : polyline)
{
delta_numbers[0] = polyline[0].lat;
delta_numbers[1] = polyline[0].lon;
for (unsigned i = 1; i < polyline.size(); ++i)
if (segment.necessary)
{
int lat_diff = polyline[i].lat - polyline[i - 1].lat;
int lon_diff = polyline[i].lon - polyline[i - 1].lon;
delta_numbers[(2 * i)] = (lat_diff);
delta_numbers[(2 * i) + 1] = (lon_diff);
}
encodeVectorSignedNumber(delta_numbers, output);
}
output += "\"";
}
void PolylineCompressor::printUnencodedString(const std::vector<FixedPointCoordinate> &polyline,
std::string &output) const
{
output += "[";
std::string tmp;
for (unsigned i = 0; i < polyline.size(); i++)
{
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
output += "[";
output += tmp;
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
output += ", ";
output += tmp;
output += "]";
if (i < polyline.size() - 1)
{
output += ",";
JSON::Array json_coordinate;
json_coordinate.values.push_back(segment.location.lat / COORDINATE_PRECISION);
json_coordinate.values.push_back(segment.location.lon / COORDINATE_PRECISION);
json_geometry_array.values.push_back(json_coordinate);
}
}
output += "]";
}
void PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline,
std::string &output) const
{
output += "[";
std::string tmp;
for (unsigned i = 0; i < polyline.size(); i++)
{
if (!polyline[i].necessary)
{
continue;
}
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
output += "[";
output += tmp;
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", ";
output += tmp;
output += "]";
if (i < polyline.size() - 1)
{
output += ",";
}
}
output += "]";
return json_geometry_array;
}
+5 -12
View File
@@ -28,8 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_
#include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h"
struct SegmentInformation;
#include "../DataStructures/JSONContainer.h"
#include <string>
#include <vector>
@@ -42,17 +43,9 @@ class PolylineCompressor
void encodeNumber(int number_to_encode, std::string &output) const;
public:
void printEncodedString(const std::vector<SegmentInformation> &polyline,
std::string &output) const;
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
void printEncodedString(const std::vector<FixedPointCoordinate> &polyline,
std::string &output) const;
void printUnencodedString(const std::vector<FixedPointCoordinate> &polyline,
std::string &output) const;
void printUnencodedString(const std::vector<SegmentInformation> &polyline,
std::string &output) const;
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
};
#endif /* POLYLINECOMPRESSOR_H_ */
+125 -134
View File
@@ -34,16 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/Range.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include "../Util/OSRMException.h"
#include "../Util/simple_logger.hpp"
#include "../Util/StdHashExtensions.h"
#include "../Util/TimingUtil.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <tbb/parallel_sort.h>
#ifdef __APPLE__
#include <gdal.h>
#include <ogrsf_frmts.h>
@@ -60,23 +66,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_set>
#include <vector>
namespace std
{
template <> struct hash<std::pair<NodeID, NodeID>>
{
size_t operator()(const std::pair<NodeID, NodeID> &pair) const
{
return std::hash<int>()(pair.first) ^ std::hash<int>()(pair.second);
}
};
}
class TarjanSCC
{
private:
struct TarjanNode
{
TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
TarjanNode() : index(SPECIAL_NODEID), low_link(SPECIAL_NODEID), on_stack(false) {}
unsigned index;
unsigned low_link;
bool on_stack;
@@ -84,13 +79,10 @@ class TarjanSCC
struct TarjanEdgeData
{
TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
TarjanEdgeData(int distance, unsigned name_id) : distance(distance), name_id(name_id) {}
int distance;
unsigned name_id : 31;
bool shortcut : 1;
short type;
bool forward : 1;
bool backward : 1;
bool reversedEdge : 1;
unsigned name_id;
};
struct TarjanStackFrame
@@ -100,18 +92,18 @@ class TarjanSCC
NodeID parent;
};
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> restriction_target;
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
using TarjanDynamicGraph = DynamicGraph<TarjanEdgeData>;
using TarjanEdge = TarjanDynamicGraph::InputEdge;
using RestrictionSource = std::pair<NodeID, NodeID>;
using RestrictionTarget = std::pair<NodeID, bool>;
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
using RestrictionMap = std::unordered_map<RestrictionSource, unsigned>;
std::vector<NodeInfo> m_coordinate_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
std::unordered_set<NodeID> m_barrier_node_list;
std::unordered_set<NodeID> m_traffic_light_list;
std::unordered_set<NodeID> barrier_node_list;
std::unordered_set<NodeID> traffic_light_list;
unsigned m_restriction_counter;
RestrictionMap m_restriction_map;
@@ -124,18 +116,18 @@ class TarjanSCC
std::vector<NodeInfo> &nI)
: m_coordinate_list(nI), m_restriction_counter(irs.size())
{
TIMER_START(SCC_LOAD);
for (const TurnRestriction &restriction : irs)
{
std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
restriction.viaNode};
unsigned index;
RestrictionMap::iterator restriction_iterator =
m_restriction_map.find(restrictionSource);
std::pair<NodeID, NodeID> restriction_source = {restriction.fromNode,
restriction.viaNode};
unsigned index = 0;
const auto restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator == m_restriction_map.end())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restrictionSource, index);
m_restriction_map.emplace(restriction_source, index);
}
else
{
@@ -156,65 +148,48 @@ class TarjanSCC
.emplace_back(restriction.toNode, restriction.flags.isOnly);
}
m_barrier_node_list.insert(bn.begin(), bn.end());
m_traffic_light_list.insert(tl.begin(), tl.end());
barrier_node_list.insert(bn.begin(), bn.end());
traffic_light_list.insert(tl.begin(), tl.end());
DeallocatingVector<TarjanEdge> edge_list;
for (const NodeBasedEdge &input_edge : input_edges)
{
if (input_edge.source() == input_edge.target())
if (input_edge.source == input_edge.target)
{
continue;
}
TarjanEdge edge;
if (input_edge.isForward())
if (input_edge.forward)
{
edge.source = input_edge.source();
edge.target = input_edge.target();
edge.data.forward = input_edge.isForward();
edge.data.backward = input_edge.isBackward();
edge_list.emplace_back(input_edge.source,
input_edge.target,
(std::max)((int)input_edge.weight, 1),
input_edge.name_id);
}
else
if (input_edge.backward)
{
edge.source = input_edge.target();
edge.target = input_edge.source();
edge.data.backward = input_edge.isForward();
edge.data.forward = input_edge.isBackward();
}
edge.data.distance = (std::max)((int)input_edge.weight(), 1);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false;
// edge.data.roundabout = input_edge.isRoundabout();
// edge.data.ignoreInGrid = input_edge.ignoreInGrid();
edge.data.name_id = input_edge.name();
edge.data.type = input_edge.type();
// edge.data.isAccessRestricted = input_edge.isAccessRestricted();
edge.data.reversedEdge = false;
edge_list.push_back(edge);
if (edge.data.backward)
{
std::swap(edge.source, edge.target);
edge.data.forward = input_edge.isBackward();
edge.data.backward = input_edge.isForward();
edge.data.reversedEdge = true;
edge_list.push_back(edge);
edge_list.emplace_back(input_edge.target,
input_edge.source,
(std::max)((int)input_edge.weight, 1),
input_edge.name_id);
}
}
std::vector<NodeBasedEdge>().swap(input_edges);
input_edges.clear();
input_edges.shrink_to_fit();
BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
"input edge vector not properly deallocated");
std::sort(edge_list.begin(), edge_list.end());
tbb::parallel_sort(edge_list.begin(), edge_list.end());
m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
TIMER_STOP(SCC_LOAD);
SimpleLogger().Write() << "Loading data into SCC took " << TIMER_MSEC(SCC_LOAD)/1000. << "s";
}
~TarjanSCC() { m_node_based_graph.reset(); }
void Run()
{
TIMER_START(SCC_RUN_SETUP);
// remove files from previous run if exist
DeleteFileIfExists("component.dbf");
DeleteFileIfExists("component.shx");
@@ -227,53 +202,67 @@ class TarjanSCC
const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver *poDriver =
OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
if (NULL == poDriver)
if (nullptr == poDriver)
{
throw OSRMException("ESRI Shapefile driver not available");
}
OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", NULL);
OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
if (NULL == poDS)
if (nullptr == poDS)
{
throw OSRMException("Creation of output file failed");
}
OGRLayer *poLayer = poDS->CreateLayer("component", NULL, wkbLineString, NULL);
OGRSpatialReference *poSRS = new OGRSpatialReference();
poSRS->importFromEPSG(4326);
if (NULL == poLayer)
OGRLayer *poLayer = poDS->CreateLayer("component", poSRS, wkbLineString, nullptr);
if (nullptr == poLayer)
{
throw OSRMException("Layer creation failed.");
}
TIMER_STOP(SCC_RUN_SETUP);
SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP)/1000. << "s";
TIMER_START(SCC_RUN);
// The following is a hack to distinguish between stuff that happens
// before the recursive call and stuff that happens after
std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
std::stack<TarjanStackFrame> recursion_stack;
// true = stuff before, false = stuff after call
std::stack<NodeID> tarjan_stack;
std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(),
SPECIAL_NODEID);
std::vector<NodeID> component_size_vector;
std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
unsigned component_index = 0, size_of_current_component = 0;
int index = 0;
NodeID last_node = m_node_based_graph->GetNumberOfNodes();
for (NodeID node = 0; node < last_node; ++node)
const NodeID last_node = m_node_based_graph->GetNumberOfNodes();
std::vector<bool> processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), true);
for(const NodeID node : osrm::irange(0u, last_node))
{
if (UINT_MAX == components_index[node])
if (SPECIAL_NODEID == components_index[node])
{
recursion_stack.emplace(true, TarjanStackFrame(node, node));
recursion_stack.emplace(TarjanStackFrame(node, node));
}
while (!recursion_stack.empty())
{
const bool before_recursion = recursion_stack.top().first;
TarjanStackFrame currentFrame = recursion_stack.top().second;
NodeID v = currentFrame.v;
TarjanStackFrame currentFrame = recursion_stack.top();
const NodeID v = currentFrame.v;
recursion_stack.pop();
const bool before_recursion = processing_node_before_recursion[v];
if (before_recursion && tarjan_node_list[v].index != UINT_MAX)
{
continue;
}
if (before_recursion)
{
// Mark frame to handle tail of recursion
recursion_stack.emplace(false, currentFrame);
recursion_stack.emplace(currentFrame);
processing_node_before_recursion[v] = false;
// Mark essential information for SCC
tarjan_node_list[v].index = index;
@@ -283,14 +272,13 @@ class TarjanSCC
++index;
// Traverse outgoing edges
EdgeID end_edge = m_node_based_graph->EndEdges(v);
for (auto e2 = m_node_based_graph->BeginEdges(v); e2 < end_edge; ++e2)
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
{
const TarjanDynamicGraph::NodeIterator vprime =
m_node_based_graph->GetTarget(e2);
if (UINT_MAX == tarjan_node_list[vprime].index)
m_node_based_graph->GetTarget(current_edge);
if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
{
recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
recursion_stack.emplace(TarjanStackFrame(vprime, v));
}
else
{
@@ -304,6 +292,7 @@ class TarjanSCC
}
else
{
processing_node_before_recursion[v] = true;
tarjan_node_list[currentFrame.parent].low_link =
std::min(tarjan_node_list[currentFrame.parent].low_link,
tarjan_node_list[v].low_link);
@@ -336,60 +325,60 @@ class TarjanSCC
}
}
TIMER_STOP(SCC_RUN);
SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN)/1000. << "s";
SimpleLogger().Write() << "identified: " << component_size_vector.size()
<< " many components, marking small components";
// TODO/C++11: prime candidate for lambda function
unsigned size_one_counter = 0;
for (unsigned i = 0, end = component_size_vector.size(); i < end; ++i)
{
if (1 == component_size_vector[i])
{
++size_one_counter;
}
}
TIMER_START(SCC_OUTPUT);
const unsigned size_one_counter = std::count_if(component_size_vector.begin(),
component_size_vector.end(),
[](unsigned value)
{
return 1 == value;
});
SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
uint64_t total_network_distance = 0;
p.reinit(m_node_based_graph->GetNumberOfNodes());
NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
for (NodeID u = 0; u < last_u_node; ++u)
// const NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
for (const NodeID source : osrm::irange(0u, last_node))
{
p.printIncrement();
EdgeID last_edge = m_node_based_graph->EndEdges(u);
for (auto e1 = m_node_based_graph->BeginEdges(u); e1 < last_edge; ++e1)
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(source))
{
if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
{
continue;
}
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
const TarjanDynamicGraph::NodeIterator target =
m_node_based_graph->GetTarget(current_edge);
total_network_distance +=
100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
m_coordinate_list[u].lon,
m_coordinate_list[v].lat,
m_coordinate_list[v].lon);
if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
if (source < target ||
m_node_based_graph->EndEdges(target) ==
m_node_based_graph->FindEdge(target, source))
{
BOOST_ASSERT(e1 != UINT_MAX);
BOOST_ASSERT(u != UINT_MAX);
BOOST_ASSERT(v != UINT_MAX);
total_network_distance +=
100 * FixedPointCoordinate::ApproximateEuclideanDistance(
m_coordinate_list[source].lat,
m_coordinate_list[source].lon,
m_coordinate_list[target].lat,
m_coordinate_list[target].lon);
BOOST_ASSERT(current_edge != SPECIAL_EDGEID);
BOOST_ASSERT(source != SPECIAL_NODEID);
BOOST_ASSERT(target != SPECIAL_NODEID);
const unsigned size_of_containing_component =
std::min(component_size_vector[components_index[u]],
component_size_vector[components_index[v]]);
std::min(component_size_vector[components_index[source]],
component_size_vector[components_index[target]]);
// edges that end on bollard nodes may actually be in two distinct components
if (size_of_containing_component < 10)
{
OGRLineString lineString;
lineString.addPoint(m_coordinate_list[u].lon / COORDINATE_PRECISION,
m_coordinate_list[u].lat / COORDINATE_PRECISION);
lineString.addPoint(m_coordinate_list[v].lon / COORDINATE_PRECISION,
m_coordinate_list[v].lat / COORDINATE_PRECISION);
lineString.addPoint(m_coordinate_list[source].lon / COORDINATE_PRECISION,
m_coordinate_list[source].lat / COORDINATE_PRECISION);
lineString.addPoint(m_coordinate_list[target].lon / COORDINATE_PRECISION,
m_coordinate_list[target].lat / COORDINATE_PRECISION);
OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
@@ -404,24 +393,27 @@ class TarjanSCC
}
}
OGRDataSource::DestroyDataSource(poDS);
std::vector<NodeID>().swap(component_size_vector);
component_size_vector.clear();
component_size_vector.shrink_to_fit();
BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
"component_size_vector not properly deallocated");
std::vector<NodeID>().swap(components_index);
components_index.clear();
components_index.shrink_to_fit();
BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
"icomponents_index not properly deallocated");
"components_index not properly deallocated");
TIMER_STOP(SCC_OUTPUT);
SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT)/1000. << "s";
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
100 / 1000. << " km";
SimpleLogger().Write() << "total network distance: "
<< (uint64_t)total_network_distance / 100 / 1000. << " km";
}
private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
{
std::pair<NodeID, NodeID> restriction_source = {u, v};
RestrictionMap::const_iterator restriction_iterator =
m_restriction_map.find(restriction_source);
const auto restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
@@ -433,19 +425,18 @@ class TarjanSCC
}
}
}
return UINT_MAX;
return SPECIAL_NODEID;
}
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
{
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
std::pair<NodeID, NodeID> restriction_source = {u, v};
RestrictionMap::const_iterator restriction_iterator =
m_restriction_map.find(restriction_source);
const auto restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
for (const RestrictionTarget &restriction_target : m_restriction_bucket_list.at(index))
{
if (w == restriction_target.first)
{
+130
View File
@@ -0,0 +1,130 @@
#include "../DataStructures/OriginalEdgeData.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/SharedMemoryVectorWrapper.h"
#include "../DataStructures/StaticRTree.h"
#include "../Util/BoostFileSystemFix.h"
#include "../DataStructures/EdgeBasedNode.h"
#include <osrm/Coordinate.h>
#include <random>
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 13;
constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
using RTreeLeaf = EdgeBasedNode;
using FixedPointCoordinateListPtr = std::shared_ptr<std::vector<FixedPointCoordinate>>;
using BenchStaticRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>;
FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file)
{
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
NodeInfo current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
for (unsigned i = 0; i < number_of_coordinates; ++i)
{
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
}
nodes_input_stream.close();
return coords;
}
void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
{
std::mt19937 mt_rand(RANDOM_SEED);
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
std::vector<FixedPointCoordinate> queries;
for (unsigned i = 0; i < num_queries; i++)
{
queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand)));
}
const unsigned num_results = 5;
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
<< " phantom nodes"
<< "\n";
TIMER_START(query_phantom);
std::vector<PhantomNode> resulting_phantom_node_vector;
for (const auto &q : queries)
{
resulting_phantom_node_vector.clear();
rtree.IncrementalFindPhantomNodeForCoordinate(
q, resulting_phantom_node_vector, 3, num_results);
resulting_phantom_node_vector.clear();
rtree.IncrementalFindPhantomNodeForCoordinate(
q, resulting_phantom_node_vector, 17, num_results);
}
TIMER_STOP(query_phantom);
std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries."
<< "\n";
std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
<< "\n";
std::cout << "#### LocateClosestEndPointForCoordinate"
<< "\n";
TIMER_START(query_endpoint);
FixedPointCoordinate result;
for (const auto &q : queries)
{
rtree.LocateClosestEndPointForCoordinate(q, result, 3);
}
TIMER_STOP(query_endpoint);
std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries."
<< "\n";
std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query."
<< "\n";
std::cout << "#### FindPhantomNodeForCoordinate"
<< "\n";
TIMER_START(query_phantomnode);
for (const auto &q : queries)
{
PhantomNode phantom;
rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
}
TIMER_STOP(query_phantomnode);
std::cout << "Took " << TIMER_MSEC(query_phantomnode) << " msec for " << num_queries
<< " queries."
<< "\n";
std::cout << TIMER_MSEC(query_phantomnode) / ((double)num_queries) << " msec/query."
<< "\n";
}
int main(int argc, char **argv)
{
if (argc < 4)
{
std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes"
<< "\n";
return 1;
}
const char *ramPath = argv[1];
const char *filePath = argv[2];
const char *nodesPath = argv[3];
auto coords = LoadCoordinates(nodesPath);
BenchStaticRTree rtree(ramPath, filePath, coords);
Benchmark(rtree, 10000);
return 0;
}
+142 -94
View File
@@ -1,4 +1,11 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 2.8.8)
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
message(FATAL_ERROR "In-source builds are not allowed.
Please create a directory and run cmake from there, passing the path to this source directory as the last argument.
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
endif()
project(OSRM)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXCompilerFlag)
@@ -8,8 +15,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription)
git_describe(GIT_DESCRIPTION)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(bitness 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(bitness 64)
@@ -18,40 +23,54 @@ else()
message(WARNING "Building on a 32 bit system is unsupported")
endif()
if (WIN32 AND MSVC_VERSION LESS 1800)
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
endif()
OPTION(WITH_TOOLS "Build OSRM tools" OFF)
OPTION(BUILD_TOOLS "Build OSRM tools" OFF)
include_directories(${CMAKE_SOURCE_DIR}/Include/)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
DEPENDS
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
COMMENT "Configuring UUID.cpp"
${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp.in
COMMENT "Configuring FingerPrint.cpp"
VERBATIM)
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp)
add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp)
add_custom_target(tests DEPENDS datastructure-tests)
add_custom_target(benchmarks DEPENDS rtree-bench)
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
configure_file(
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
)
file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources})
file(GLOB ImporterGlob DataStructures/Import*.cpp)
add_library(IMPORT OBJECT ${ImporterGlob})
add_library(LOGGER OBJECT Util/simple_logger.cpp)
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>)
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp Util/compute_angle.cpp)
set(PrepareSources prepare.cpp ${PrepareGlob})
add_executable(osrm-prepare ${PrepareSources})
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>)
file(GLOB ServerGlob Server/*.cpp)
file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
list(REMOVE_ITEM DatastructureGlob DataStructures/Coordinate.cpp)
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
file(GLOB AlgorithmGlob Algorithms/*.cpp)
file(GLOB HttpGlob Server/Http/*.cpp)
file(GLOB LibOSRMGlob Library/*.cpp)
file(GLOB DataStructureTestsGlob UnitTests/DataStructures/*.cpp DataStructures/HilbertValue.cpp)
set(
OSRMSources
@@ -62,16 +81,20 @@ set(
${AlgorithmGlob}
${HttpGlob}
)
add_library(COORDLIB STATIC ${CoordinateGlob})
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp)
add_library(UUID STATIC Util/UUID.cpp)
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
add_dependencies(UUID UUIDConfigure)
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
add_library(COORDINATE OBJECT ${CoordinateGlob})
add_library(FINGERPRINT OBJECT Util/FingerPrint.cpp)
add_library(GITDESCRIPTION OBJECT Util/GitDescription.cpp)
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
add_dependencies(FINGERPRINT FingerPrintConfigure)
add_executable(osrm-routed routed.cpp ${ServerGlob})
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
add_executable(osrm-datastore datastore.cpp)
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
# Unit tests
add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
# Benchmarks
add_executable(rtree-bench EXCLUDE_FROM_ALL Benchmarks/StaticRTreeBench.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
# Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
@@ -86,56 +109,55 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
endif()
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
message(STATUS "Configuring OSRM in release mode")
# Check if LTO is available
set(LTO_FLAGS "")
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
if (HAS_LTO_FLAG)
set(LTO_FLAGS "${LTO_FLAGS} -flto")
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW)
message(STATUS "Using gcc specific binutils for LTO.")
set(CMAKE_AR "/usr/bin/gcc-ar")
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
endif()
endif (HAS_LTO_FLAG)
endif()
if (NOT WIN32)
add_definitions(-DBOOST_TEST_DYN_LINK)
endif()
# Configuring compilers
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
message(STATUS "OpenMP parallelization not available using clang++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fopenmp -pedantic -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC")
if (WIN32) # using mingw
add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc.
add_definitions(-DWIN32)
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
add_definitions(-D_WIN32_WINNT=0x0501)
endif()
# Check if LTO is available
set(LTO_FLAGS "")
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
if (HAS_LTO_FLAG)
set(LTO_FLAGS "${LTO_FLAGS} -flto")
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
message(STATUS "Using gcc specific binutils for LTO.")
set(CMAKE_AR "/usr/bin/gcc-ar")
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
endif()
endif (HAS_LTO_FLAG)
# disable partitioning of LTO process when possible (fixes Debian issues)
set(LTO_PARTITION_FLAGS "")
CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG)
if (HAS_LTO_PARTITION_FLAG)
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
endif (HAS_LTO_PARTITION_FLAG)
# Add Link-Time-Optimization flags, if supported (GCC >= 4.7) and enabled
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
# Activate C++11
ADD_DEFINITIONS(
-std=c++11 # Or -std=c++0x
# Other flags
)
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
ADD_DEFINITIONS(-std=c++11)
endif()
# Configuring other platform dependencies
if(APPLE)
@@ -143,10 +165,6 @@ if(APPLE)
message(STATUS "Set Architecture to x64 on OS X")
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
# if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
# message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# endif()
if(OSXLIBSTD)
message(STATUS "linking against ${OSXLIBSTD}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
@@ -157,6 +175,7 @@ if(APPLE)
endif()
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-prepare rt)
target_link_libraries(osrm-datastore rt)
target_link_libraries(OSRM rt)
endif()
@@ -169,26 +188,40 @@ if(NOT Boost_FOUND)
endif()
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries(OSRM ${Boost_LIBRARIES})
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
target_link_libraries(rtree-bench ${Boost_LIBRARIES})
find_package(Threads REQUIRED)
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
find_package(Lua52)
if(NOT LUA52_FOUND)
find_package(Lua51 REQUIRED)
if(NOT APPLE)
find_package(LuaJIT 5.1)
endif()
else()
if(NOT APPLE)
find_package(LuaJIT 5.2)
endif()
find_package(TBB REQUIRED)
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
endif()
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
target_link_libraries(datastructure-tests ${TBB_LIBRARIES})
target_link_libraries(rtree-bench ${TBB_LIBRARIES})
include_directories(${TBB_INCLUDE_DIR})
find_package( Luabind REQUIRED )
include(check_luabind)
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
if( LUAJIT_FOUND )
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
@@ -203,11 +236,6 @@ find_package(LibXml2 REQUIRED)
include_directories(${LIBXML2_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
find_package( Luabind REQUIRED )
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
find_package( STXXL REQUIRED )
include_directories(${STXXL_INCLUDE_DIR})
target_link_libraries(OSRM ${STXXL_LIBRARY})
@@ -233,25 +261,40 @@ include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
if(WITH_TOOLS)
if(WITH_TOOLS OR BUILD_TOOLS)
message(STATUS "Activating OSRM internal tools")
find_package(GDAL)
if(GDAL_FOUND)
add_executable(osrm-components Tools/components.cpp)
add_executable(osrm-components Tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-components ${TBB_LIBRARIES})
include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries(
osrm-components
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
install(TARGETS osrm-components DESTINATION bin)
else()
message(FATAL_ERROR "libgdal and/or development headers not found")
endif()
add_executable(osrm-cli Tools/simpleclient.cpp)
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-unlock-all rt)
endif()
add_executable(osrm-cli Tools/simpleclient.cpp $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-unlock-all rt)
endif()
add_executable(osrm-check-hsgr Tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
add_executable(osrm-springclean Tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION>)
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
install(TARGETS osrm-cli DESTINATION bin)
install(TARGETS osrm-io-benchmark DESTINATION bin)
install(TARGETS osrm-unlock-all DESTINATION bin)
install(TARGETS osrm-check-hsgr DESTINATION bin)
install(TARGETS osrm-springclean DESTINATION bin)
endif()
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
@@ -281,3 +324,8 @@ endforeach ()
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
if(BUILD_DEBIAN_PACKAGE)
include(CPackDebianConfig)
include(CPack)
endif()
+230 -233
View File
@@ -28,19 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CONTRACTOR_H
#define CONTRACTOR_H
#include "TemporaryStorage.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/Range.h"
#include "../DataStructures/XORFastHash.h"
#include "../DataStructures/XORFastHashStorage.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <stxxl/vector>
#include <tbb/enumerable_thread_specific.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <limits>
#include <vector>
@@ -56,15 +64,15 @@ class Contractor
is_original_via_node_ID(false)
{
}
ContractorEdgeData(unsigned _distance,
unsigned _originalEdges,
unsigned _id,
bool _shortcut,
bool _forward,
bool _backward)
: distance(_distance), id(_id),
originalEdges(std::min((unsigned)1 << 28, _originalEdges)), shortcut(_shortcut),
forward(_forward), backward(_backward), is_original_via_node_ID(false)
ContractorEdgeData(unsigned distance,
unsigned original_edges,
unsigned id,
bool shortcut,
bool forward,
bool backward)
: distance(distance), id(id),
originalEdges(std::min((unsigned)1 << 28, original_edges)), shortcut(shortcut),
forward(forward), backward(backward), is_original_via_node_ID(false)
{
}
unsigned distance;
@@ -84,19 +92,18 @@ class Contractor
ContractorHeapData(short h, bool t) : hop(h), target(t) {}
};
typedef DynamicGraph<ContractorEdgeData> ContractorGraph;
// typedef BinaryHeap< NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
// > ContractorHeap;
typedef BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>
ContractorHeap;
typedef ContractorGraph::InputEdge ContractorEdge;
using ContractorGraph = DynamicGraph<ContractorEdgeData>;
// using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
// >;
using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
using ContractorEdge = ContractorGraph::InputEdge;
struct ContractorThreadData
{
ContractorHeap heap;
std::vector<ContractorEdge> inserted_edges;
std::vector<NodeID> neighbours;
ContractorThreadData(NodeID nodes) : heap(nodes) {}
explicit ContractorThreadData(NodeID nodes) : heap(nodes) {}
};
struct NodePriorityData
@@ -125,45 +132,66 @@ class Contractor
bool is_independent : 1;
};
struct ThreadDataContainer
{
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
inline ContractorThreadData* getThreadData()
{
bool exists = false;
auto& ref = data.local(exists);
if (!exists)
{
ref = std::make_shared<ContractorThreadData>(number_of_nodes);
}
return ref.get();
}
int number_of_nodes;
using EnumerableThreadData = tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
EnumerableThreadData data;
};
public:
template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
{
std::vector<ContractorEdge> edges;
edges.reserve(input_edge_list.size() * 2);
temp_edge_counter = 0;
auto diter = input_edge_list.dbegin();
auto dend = input_edge_list.dend();
ContractorEdge new_edge;
while (diter != dend)
const auto dend = input_edge_list.dend();
for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter)
{
new_edge.source = diter->source();
new_edge.target = diter->target();
new_edge.data = ContractorEdgeData((std::max)((int)diter->weight(), 1),
1,
diter->id(),
false,
diter->isForward(),
diter->isBackward());
BOOST_ASSERT_MSG(new_edge.data.distance > 0, "edge distance < 1");
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0, "edge distance < 1");
#ifndef NDEBUG
if (new_edge.data.distance > 24 * 60 * 60 * 10)
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
{
SimpleLogger().Write(logWARNING) << "Edge weight large -> "
<< new_edge.data.distance;
<< static_cast<unsigned int>(std::max(diter->weight, 1));
}
#endif
edges.push_back(new_edge);
std::swap(new_edge.source, new_edge.target);
new_edge.data.forward = diter->isBackward();
new_edge.data.backward = diter->isForward();
edges.push_back(new_edge);
++diter;
edges.emplace_back(diter->source, diter->target,
static_cast<unsigned int>(std::max(diter->weight, 1)),
1,
diter->edge_id,
false,
diter->forward ? true : false,
diter->backward ? true : false);
edges.emplace_back(diter->target, diter->source,
static_cast<unsigned int>(std::max(diter->weight, 1)),
1,
diter->edge_id,
false,
diter->backward ? true : false,
diter->forward ? true : false);
}
// clear input vector and trim the current set of edges with the well-known swap trick
// clear input vector
input_edge_list.clear();
sort(edges.begin(), edges.end());
edges.shrink_to_fit();
tbb::parallel_sort(edges.begin(), edges.end());
NodeID edge = 0;
for (NodeID i = 0; i < edges.size();)
{
@@ -173,7 +201,7 @@ class Contractor
// remove eigenloops
if (source == target)
{
i++;
++i;
continue;
}
ContractorEdge forward_edge;
@@ -252,49 +280,58 @@ class Contractor
// << "); via: " << contractor_graph->GetEdgeData(i).via;
// }
// Create temporary file
edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
std::cout << "contractor finished initalization" << std::endl;
}
~Contractor() { TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot); }
~Contractor() { }
void Run()
{
// for the preperation we can use a big grain size, which is much faster (probably cache)
constexpr size_t InitGrainSize = 100000;
constexpr size_t PQGrainSize = 100000;
// auto_partitioner will automatically increase the blocksize if we have
// a lot of data. It is *important* for the last loop iterations
// (which have a very small dataset) that it is devisible.
constexpr size_t IndependentGrainSize = 1;
constexpr size_t ContractGrainSize = 1;
constexpr size_t NeighboursGrainSize = 1;
constexpr size_t DeleteGrainSize = 1;
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
Percent p(number_of_nodes);
const unsigned thread_count = omp_get_max_threads();
std::vector<ContractorThreadData *> thread_data_list;
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
{
thread_data_list.push_back(new ContractorThreadData(number_of_nodes));
}
std::cout << "Contractor is using " << thread_count << " threads" << std::endl;
ThreadDataContainer thread_data_list(number_of_nodes);
NodeID number_of_contracted_nodes = 0;
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
std::vector<float> node_priorities(number_of_nodes);
std::vector<NodePriorityData> node_data(number_of_nodes);
// initialize priorities in parallel
#pragma omp parallel for schedule(guided)
for (int x = 0; x < (int)number_of_nodes; ++x)
{
remaining_nodes[x].id = x;
}
// initialize priorities in parallel
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
[&remaining_nodes](const tbb::blocked_range<int>& range)
{
for (int x = range.begin(); x != range.end(); ++x)
{
remaining_nodes[x].id = x;
}
}
);
std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel
{
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp parallel for schedule(guided)
for (int x = 0; x < (int)number_of_nodes; ++x)
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
[this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
{
node_priorities[x] = EvaluateNodePriority(data, &node_data[x], x);
ContractorThreadData *data = thread_data_list.getThreadData();
for (int x = range.begin(); x != range.end(); ++x)
{
node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x);
}
}
}
);
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
<< std::flush;
@@ -309,11 +346,7 @@ class Contractor
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
// Delete old heap data to free memory that we need for the coming operations
for (ContractorThreadData *data : thread_data_list)
{
delete data;
}
thread_data_list.clear();
thread_data_list.data.clear();
// Create new priority array
std::vector<float> new_node_priority(remaining_nodes.size());
@@ -326,7 +359,7 @@ class Contractor
// build forward and backward renumbering map and remap ids in remaining_nodes and
// Priorities.
for (unsigned new_node_id = 0; new_node_id < remaining_nodes.size(); ++new_node_id)
for (const auto new_node_id : osrm::irange<std::size_t>(0, remaining_nodes.size()))
{
// create renumbering maps in both directions
orig_node_id_to_new_id_map[new_node_id] = remaining_nodes[new_node_id].id;
@@ -335,42 +368,32 @@ class Contractor
node_priorities[remaining_nodes[new_node_id].id];
remaining_nodes[new_node_id].id = new_node_id;
}
TemporaryStorage &temporary_storage = TemporaryStorage::GetInstance();
// walk over all nodes
for (unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i)
for (const auto i : osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
{
const NodeID start = i;
auto last_edge = contractor_graph->EndEdges(start);
for (auto current_edge = contractor_graph->BeginEdges(start);
current_edge < last_edge;
++current_edge)
const NodeID source = i;
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
{
ContractorGraph::EdgeData &data =
contractor_graph->GetEdgeData(current_edge);
const NodeID target = contractor_graph->GetTarget(current_edge);
if (UINT_MAX == new_node_id_from_orig_id_map[i])
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[i])
{
// Save edges of this node w/o renumbering.
temporary_storage.WriteToSlot(
edge_storage_slot, (char *)&start, sizeof(NodeID));
temporary_storage.WriteToSlot(
edge_storage_slot, (char *)&target, sizeof(NodeID));
temporary_storage.WriteToSlot(edge_storage_slot,
(char *)&data,
sizeof(ContractorGraph::EdgeData));
++temp_edge_counter;
external_edge_list.push_back({source, target, data});
}
else
{
// node is not yet contracted.
// add (renumbered) outgoing edges to new DynamicGraph.
ContractorEdge new_edge;
new_edge.source = new_node_id_from_orig_id_map[start];
new_edge.target = new_node_id_from_orig_id_map[target];
new_edge.data = data;
ContractorEdge new_edge = {
new_node_id_from_orig_id_map[source],
new_node_id_from_orig_id_map[target],
data
};
new_edge.data.is_original_via_node_ID = true;
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[start],
"new start id not resolveable");
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source],
"new source id not resolveable");
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target],
"new target id not resolveable");
new_edge_set.push_back(new_edge);
@@ -385,7 +408,8 @@ class Contractor
// Replace old priorities array by new one
node_priorities.swap(new_node_priority);
// Delete old node_priorities vector
std::vector<float>().swap(new_node_priority);
new_node_priority.clear();
new_node_priority.shrink_to_fit();
// old Graph is removed
contractor_graph.reset();
@@ -399,61 +423,69 @@ class Contractor
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
// reinitialize heaps and ThreadData objects with appropriate size
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
{
thread_data_list.push_back(
new ContractorThreadData(contractor_graph->GetNumberOfNodes()));
}
thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
}
const int last = (int)remaining_nodes.size();
#pragma omp parallel
{
// determine independent node set
ContractorThreadData *const data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided)
for (int i = 0; i < last; ++i)
tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
[this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
{
const NodeID node = remaining_nodes[i].id;
remaining_nodes[i].is_independent =
IsNodeIndependent(node_priorities, data, node);
ContractorThreadData *data = thread_data_list.getThreadData();
// determine independent node set
for (int i = range.begin(); i != range.end(); ++i)
{
const NodeID node = remaining_nodes[i].id;
remaining_nodes[i].is_independent =
this->IsNodeIndependent(node_priorities, data, node);
}
}
}
);
const auto first = stable_partition(remaining_nodes.begin(),
remaining_nodes.end(),
[](RemainingNodeData node_data)
{ return !node_data.is_independent; });
const int first_independent_node = first - remaining_nodes.begin();
// contract independent nodes
#pragma omp parallel
{
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided) nowait
for (int position = first_independent_node; position < last; ++position)
{
NodeID x = remaining_nodes[position].id;
ContractNode<false>(data, x);
}
const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
std::sort(data->inserted_edges.begin(), data->inserted_edges.end());
}
#pragma omp parallel
{
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided) nowait
for (int position = first_independent_node; position < last; ++position)
// contract independent nodes
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
{
NodeID x = remaining_nodes[position].id;
DeleteIncomingEdges(data, x);
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
{
const NodeID x = remaining_nodes[position].id;
this->ContractNode<false>(data, x);
}
}
}
// insert new edges
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
{
ContractorThreadData &data = *thread_data_list[thread_id];
for (const ContractorEdge &edge : data.inserted_edges)
);
// make sure we really sort each block
tbb::parallel_for(thread_data_list.data.range(),
[&](const ThreadDataContainer::EnumerableThreadData::range_type& range)
{
auto current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
for (auto& data : range)
std::sort(data->inserted_edges.begin(),
data->inserted_edges.end());
}
);
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
{
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
{
const NodeID x = remaining_nodes[position].id;
this->DeleteIncomingEdges(data, x);
}
}
);
// insert new edges
for (auto& data : thread_data_list.data)
{
for (const ContractorEdge &edge : data->inserted_edges)
{
const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
if (current_edge_ID < contractor_graph->EndEdges(edge.source))
{
ContractorGraph::EdgeData &current_data =
@@ -469,23 +501,25 @@ class Contractor
}
contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
}
data.inserted_edges.clear();
data->inserted_edges.clear();
}
// update priorities
#pragma omp parallel
{
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
#pragma omp for schedule(guided) nowait
for (int position = first_independent_node; position < last; ++position)
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
[this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
{
NodeID x = remaining_nodes[position].id;
UpdateNodeNeighbours(node_priorities, node_data, data, x);
ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position)
{
NodeID x = remaining_nodes[position].id;
this->UpdateNodeNeighbours(node_priorities, node_data, data, x);
}
}
}
);
// remove contracted nodes from the pool
number_of_contracted_nodes += last - first_independent_node;
remaining_nodes.resize(first_independent_node);
std::vector<RemainingNodeData>(remaining_nodes).swap(remaining_nodes);
remaining_nodes.shrink_to_fit();
// unsigned maxdegree = 0;
// unsigned avgdegree = 0;
// unsigned mindegree = UINT_MAX;
@@ -513,26 +547,22 @@ class Contractor
p.printStatus(number_of_contracted_nodes);
}
for (ContractorThreadData *data : thread_data_list)
{
delete data;
}
thread_data_list.clear();
thread_data_list.data.clear();
}
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
{
Percent p(contractor_graph->GetNumberOfNodes());
SimpleLogger().Write() << "Getting edges of minimized graph";
NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
if (contractor_graph->GetNumberOfNodes())
{
Edge new_edge;
for (NodeID node = 0; node < number_of_nodes; ++node)
for (const auto node : osrm::irange(0u, number_of_nodes))
{
p.printStatus(node);
auto endEdges = contractor_graph->EndEdges(node);
for (auto edge = contractor_graph->BeginEdges(node); edge < endEdges; ++edge)
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const NodeID target = contractor_graph->GetTarget(edge);
const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge);
@@ -571,29 +601,9 @@ class Contractor
orig_node_id_to_new_id_map.shrink_to_fit();
BOOST_ASSERT(0 == orig_node_id_to_new_id_map.capacity());
TemporaryStorage &temporary_storage = TemporaryStorage::GetInstance();
// loads edges of graph before renumbering, no need for further numbering action.
NodeID start;
NodeID target;
ContractorGraph::EdgeData data;
Edge restored_edge;
for (unsigned i = 0; i < temp_edge_counter; ++i)
{
temporary_storage.ReadFromSlot(edge_storage_slot, (char *)&start, sizeof(NodeID));
temporary_storage.ReadFromSlot(edge_storage_slot, (char *)&target, sizeof(NodeID));
temporary_storage.ReadFromSlot(
edge_storage_slot, (char *)&data, sizeof(ContractorGraph::EdgeData));
restored_edge.source = start;
restored_edge.target = target;
restored_edge.data.distance = data.distance;
restored_edge.data.shortcut = data.shortcut;
restored_edge.data.id = data.id;
restored_edge.data.forward = data.forward;
restored_edge.data.backward = data.backward;
edges.push_back(restored_edge);
}
temporary_storage.DeallocateSlot(edge_storage_slot);
edges.append(external_edge_list.begin(), external_edge_list.end());
external_edge_list.clear();
}
private:
@@ -608,7 +618,7 @@ class Contractor
int nodes = 0;
unsigned number_of_targets_found = 0;
while (heap.Size() > 0)
while (!heap.Empty())
{
const NodeID node = heap.DeleteMin();
const int distance = heap.GetKey(node);
@@ -618,12 +628,12 @@ class Contractor
{
return;
}
// Destination settled?
if (distance > max_distance)
{
return;
}
// Destination settled?
if (heap.GetData(node).target)
{
++number_of_targets_found;
@@ -634,8 +644,7 @@ class Contractor
}
// iterate over all edges of node
auto end_edges = contractor_graph->EndEdges(node);
for (auto edge = contractor_graph->BeginEdges(node); edge != end_edges; ++edge)
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge);
if (!data.forward)
@@ -677,14 +686,14 @@ class Contractor
float result;
if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
{
result = 1 * node_data->depth;
result = 1.f * node_data->depth;
}
else
{
result = 2 * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
4 * (((float)stats.original_edges_added_count) /
stats.original_edges_deleted_count) +
1 * node_data->depth;
result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
4.f * (((float)stats.original_edges_added_count) /
stats.original_edges_deleted_count) +
1.f * node_data->depth;
}
BOOST_ASSERT(result >= 0);
return result;
@@ -692,20 +701,19 @@ class Contractor
template <bool RUNSIMULATION>
inline bool
ContractNode(ContractorThreadData *data, NodeID node, ContractionStats *stats = NULL)
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
{
ContractorHeap &heap = data->heap;
int inserted_edges_size = data->inserted_edges.size();
std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
auto end_in_edges = contractor_graph->EndEdges(node);
for (auto in_edge = contractor_graph->BeginEdges(node); in_edge != end_in_edges; ++in_edge)
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
const NodeID source = contractor_graph->GetTarget(in_edge);
if (RUNSIMULATION)
{
BOOST_ASSERT(stats != NULL);
BOOST_ASSERT(stats != nullptr);
++stats->edges_deleted_count;
stats->original_edges_deleted_count += in_data.originalEdges;
}
@@ -719,9 +727,7 @@ class Contractor
int max_distance = 0;
unsigned number_of_targets = 0;
auto end_out_edges = contractor_graph->EndEdges(node);
for (auto out_edge = contractor_graph->BeginEdges(node); out_edge != end_out_edges;
++out_edge)
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
if (!out_data.forward)
@@ -746,10 +752,7 @@ class Contractor
{
Dijkstra(max_distance, number_of_targets, 2000, data, node);
}
for (auto out_edge = contractor_graph->BeginEdges(node),
endOutEdges = contractor_graph->EndEdges(node);
out_edge != endOutEdges;
++out_edge)
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
{
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
if (!out_data.forward)
@@ -763,29 +766,26 @@ class Contractor
{
if (RUNSIMULATION)
{
BOOST_ASSERT(stats != NULL);
BOOST_ASSERT(stats != nullptr);
stats->edges_added_count += 2;
stats->original_edges_added_count +=
2 * (out_data.originalEdges + in_data.originalEdges);
}
else
{
ContractorEdge new_edge;
new_edge.source = source;
new_edge.target = target;
new_edge.data =
ContractorEdgeData(path_distance,
out_data.originalEdges + in_data.originalEdges,
node /*, 0, in_data.turnInstruction*/,
true,
true,
false);
;
inserted_edges.push_back(new_edge);
std::swap(new_edge.source, new_edge.target);
new_edge.data.forward = false;
new_edge.data.backward = true;
inserted_edges.push_back(new_edge);
inserted_edges.emplace_back(source, target, path_distance,
out_data.originalEdges + in_data.originalEdges,
node,
true,
true,
false);
inserted_edges.emplace_back(target, source, path_distance,
out_data.originalEdges + in_data.originalEdges,
node,
true,
false,
true);
}
}
}
@@ -835,7 +835,7 @@ class Contractor
neighbours.clear();
// find all neighbours
for (auto e = contractor_graph->BeginEdges(node); e < contractor_graph->EndEdges(node); ++e)
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
{
const NodeID u = contractor_graph->GetTarget(e);
if (u != node)
@@ -847,7 +847,7 @@ class Contractor
std::sort(neighbours.begin(), neighbours.end());
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
for (int i = 0, e = (int)neighbours.size(); i < e; ++i)
for (const auto i : osrm::irange<std::size_t>(0, neighbours.size()))
{
contractor_graph->DeleteEdgesTo(neighbours[i], node);
}
@@ -862,8 +862,7 @@ class Contractor
neighbours.clear();
// find all neighbours
auto end_edges = contractor_graph->EndEdges(node);
for (auto e = contractor_graph->BeginEdges(node); e < end_edges; ++e)
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
{
const NodeID u = contractor_graph->GetTarget(e);
if (u == node)
@@ -886,7 +885,7 @@ class Contractor
}
inline bool IsNodeIndependent(
const std::vector<float> &priorities /*, const std::vector< NodePriorityData >& node_data*/,
const std::vector<float> &priorities,
ContractorThreadData *const data,
NodeID node) const
{
@@ -895,7 +894,7 @@ class Contractor
std::vector<NodeID> &neighbours = data->neighbours;
neighbours.clear();
for (auto e = contractor_graph->BeginEdges(node); e < contractor_graph->EndEdges(node); ++e)
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
{
const NodeID target = contractor_graph->GetTarget(e);
if (node == target)
@@ -924,8 +923,7 @@ class Contractor
// examine all neighbours that are at most 2 hops away
for (const NodeID u : neighbours)
{
auto end_edges = contractor_graph->EndEdges(u);
for (auto e = contractor_graph->BeginEdges(u); e < end_edges; ++e)
for (auto e : contractor_graph->GetAdjacentEdgeRange(u))
{
const NodeID target = contractor_graph->GetTarget(e);
if (node == target)
@@ -933,7 +931,7 @@ class Contractor
continue;
}
const float target_priority = priorities[target];
assert(target_priority >= 0);
BOOST_ASSERT(target_priority >= 0);
// found a neighbour with lower priority?
if (priority > target_priority)
{
@@ -953,8 +951,8 @@ class Contractor
// This bias function takes up 22 assembly instructions in total on X86
inline bool bias(const NodeID a, const NodeID b) const
{
unsigned short hasha = fast_hash(a);
unsigned short hashb = fast_hash(b);
const unsigned short hasha = fast_hash(a);
const unsigned short hashb = fast_hash(b);
// The compiler optimizes that to conditional register flags but without branching
// statements!
@@ -967,8 +965,7 @@ class Contractor
std::shared_ptr<ContractorGraph> contractor_graph;
std::vector<ContractorGraph::InputEdge> contracted_edge_list;
unsigned edge_storage_slot;
uint64_t temp_edge_counter;
stxxl::vector<QueryEdge> external_edge_list;
std::vector<NodeID> orig_node_id_to_new_id_map;
XORFastHash fast_hash;
};
+151 -151
View File
@@ -28,14 +28,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "EdgeBasedGraphFactory.h"
#include "../Algorithms/BFSComponentExplorer.h"
#include "../DataStructures/Percent.h"
#include "../Util/ComputeAngle.h"
#include "../DataStructures/Range.h"
#include "../Util/compute_angle.hpp"
#include "../Util/LuaUtil.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include "../Util/TimingUtil.h"
#include <boost/assert.hpp>
#include <fstream>
#include <iomanip>
#include <limits>
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
@@ -43,11 +45,11 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
std::unique_ptr<RestrictionMap> restriction_map,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
std::vector<NodeInfo> &m_node_info_list,
std::vector<NodeInfo> &node_info_list,
SpeedProfileProperties &speed_profile)
: speed_profile(speed_profile),
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
m_node_info_list(m_node_info_list), m_node_based_graph(node_based_graph),
m_node_info_list(node_info_list), m_node_based_graph(node_based_graph),
m_restriction_map(std::move(restriction_map)), max_id(0)
{
@@ -77,33 +79,29 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
}
void
EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongs_to_tiny_cc)
EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID node_v, const bool belongs_to_tiny_cc)
{
// merge edges together into one EdgeBasedNode
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(v != SPECIAL_NODEID);
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
#ifndef NDEBUG
// find forward edge id and
const EdgeID e1b = m_node_based_graph->FindEdge(u, v);
BOOST_ASSERT(e1 == e1b);
#endif
const EdgeID e1 = m_node_based_graph->FindEdge(node_u, node_v);
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(e1);
// find reverse edge id and
const EdgeID e2 = m_node_based_graph->FindEdge(v, u);
const EdgeID e2 = m_node_based_graph->FindEdge(node_v, node_u);
#ifndef NDEBUG
if (e2 == m_node_based_graph->EndEdges(v))
if (e2 == m_node_based_graph->EndEdges(node_v))
{
SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")";
SimpleLogger().Write(logWARNING) << "Did not find edge (" << node_v << "," << node_u << ")";
}
#endif
BOOST_ASSERT(e2 != SPECIAL_EDGEID);
BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(v));
BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(node_v));
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2);
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
@@ -125,6 +123,8 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
m_geometry_compressor.GetBucketReference(e2);
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
BOOST_ASSERT(0 != forward_geometry.size());
const unsigned geometry_size = forward_geometry.size();
BOOST_ASSERT(geometry_size > 1);
// reconstruct bidirectional edge with individual weights and put each into the NN index
@@ -135,7 +135,7 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
// TODO: move to lambda function with C++11
int temp_sum = 0;
for (unsigned i = 0; i < forward_geometry.size(); ++i)
for (const auto i : osrm::irange(0u, geometry_size))
{
forward_dist_prefix_sum[i] = temp_sum;
temp_sum += forward_geometry[i].second;
@@ -144,20 +144,16 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
}
temp_sum = 0;
for (unsigned i = 0; i < reverse_geometry.size(); ++i)
for (const auto i : osrm::irange(0u, geometry_size))
{
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
BOOST_ASSERT(reverse_data.distance >= temp_sum);
// BOOST_ASSERT(reverse_data.distance >= temp_sum);
}
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
NodeID current_edge_source_coordinate_id = node_u;
const unsigned geometry_size = forward_geometry.size();
BOOST_ASSERT(geometry_size > 1);
NodeID current_edge_start_coordinate_id = u;
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
if (SPECIAL_NODEID != forward_data.edgeBasedNodeID)
{
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
}
@@ -167,38 +163,40 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
}
// traverse arrays from start and end respectively
for (unsigned i = 0; i < geometry_size; ++i)
for (const auto i : osrm::irange(0u, geometry_size))
{
BOOST_ASSERT(current_edge_start_coordinate_id ==
BOOST_ASSERT(current_edge_source_coordinate_id ==
reverse_geometry[geometry_size - 1 - i].first);
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_start_coordinate_id);
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
// build edges
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
reverse_data.edgeBasedNodeID,
current_edge_start_coordinate_id,
current_edge_source_coordinate_id,
current_edge_target_coordinate_id,
forward_data.nameID,
forward_geometry[i].second,
reverse_geometry[i].second,
reverse_geometry[geometry_size - 1 - i].second,
forward_dist_prefix_sum[i],
reverse_dist_prefix_sum[i],
m_geometry_compressor.GetPositionForID(e1),
i,
belongs_to_tiny_cc);
current_edge_start_coordinate_id = current_edge_target_coordinate_id;
belongs_to_tiny_cc,
forward_data.travel_mode,
reverse_data.travel_mode);
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
BOOST_ASSERT(u != m_edge_based_node_list.back().u ||
v != m_edge_based_node_list.back().v);
BOOST_ASSERT(node_u != m_edge_based_node_list.back().u ||
node_v != m_edge_based_node_list.back().v);
BOOST_ASSERT(u != m_edge_based_node_list.back().v ||
v != m_edge_based_node_list.back().u);
BOOST_ASSERT(node_u != m_edge_based_node_list.back().v ||
node_v != m_edge_based_node_list.back().u);
}
BOOST_ASSERT(current_edge_start_coordinate_id == v);
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
}
else
@@ -225,18 +223,20 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
m_edge_based_node_list.emplace_back(EdgeBasedNode(forward_data.edgeBasedNodeID,
reverse_data.edgeBasedNodeID,
u,
v,
forward_data.nameID,
forward_data.distance,
reverse_data.distance,
0,
0,
SPECIAL_EDGEID,
0,
belongs_to_tiny_cc));
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
reverse_data.edgeBasedNodeID,
node_u,
node_v,
forward_data.nameID,
forward_data.distance,
reverse_data.distance,
0,
0,
SPECIAL_EDGEID,
0,
belongs_to_tiny_cc,
forward_data.travel_mode,
reverse_data.travel_mode);
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
}
}
@@ -244,6 +244,9 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
void EdgeBasedGraphFactory::FlushVectorToStream(
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
{
if (original_edge_data_vector.empty()) {
return;
}
edge_data_file.write((char *)&(original_edge_data_vector[0]),
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
original_edge_data_vector.clear();
@@ -273,10 +276,10 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
m_geometry_compressor.SerializeInternalVector(geometry_filename);
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
SimpleLogger().Write() << "Geometry compression: " << TIMER_MSEC(geometry)*0.001 << "s";
SimpleLogger().Write() << "Renumbering edges: " << TIMER_MSEC(renumber)*0.001 << "s";
SimpleLogger().Write() << "Generating nodes: " << TIMER_MSEC(generate_nodes)*0.001 << "s";
SimpleLogger().Write() << "Generating edges: " << TIMER_MSEC(generate_edges)*0.001 << "s";
SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
}
void EdgeBasedGraphFactory::CompressGeometry()
@@ -286,55 +289,61 @@ void EdgeBasedGraphFactory::CompressGeometry()
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
Percent p(original_number_of_nodes);
Percent progress(original_number_of_nodes);
unsigned removed_node_count = 0;
for (NodeID v = 0; v < original_number_of_nodes; ++v)
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
{
p.printStatus(v);
progress.printStatus(node_v);
// only contract degree 2 vertices
if (2 != m_node_based_graph->GetOutDegree(v))
if (2 != m_node_based_graph->GetOutDegree(node_v))
{
continue;
}
// don't contract barrier node
if (m_barrier_nodes.end() != m_barrier_nodes.find(v))
if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v))
{
continue;
}
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
if (m_restriction_map->IsViaNode(node_v))
{
continue;
}
const bool reverse_edge_order =
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward);
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order;
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order;
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
const NodeID w = m_node_based_graph->GetTarget(forward_e2);
BOOST_ASSERT(SPECIAL_NODEID != w);
BOOST_ASSERT(v != w);
const NodeID u = m_node_based_graph->GetTarget(reverse_e2);
BOOST_ASSERT(SPECIAL_NODEID != u);
BOOST_ASSERT(u != v);
const NodeID node_w = m_node_based_graph->GetTarget(forward_e2);
BOOST_ASSERT(SPECIAL_NODEID != node_w);
BOOST_ASSERT(node_v != node_w);
const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2);
BOOST_ASSERT(SPECIAL_NODEID != node_u);
BOOST_ASSERT(node_u != node_v);
const EdgeID forward_e1 = m_node_based_graph->FindEdge(u, v);
BOOST_ASSERT(m_node_based_graph->EndEdges(u) != forward_e1);
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
BOOST_ASSERT(m_node_based_graph->EndEdges(node_u) != forward_e1);
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
BOOST_ASSERT(v == m_node_based_graph->GetTarget(forward_e1));
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(w, v);
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
BOOST_ASSERT(v == m_node_based_graph->GetTarget(reverse_e1));
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(reverse_e1));
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
if ((m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u)) ||
(m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w)))
if ((m_node_based_graph->FindEdge(node_u, node_w) != m_node_based_graph->EndEdges(node_u)) ||
(m_node_based_graph->FindEdge(node_w, node_u) != m_node_based_graph->EndEdges(node_w)))
{
continue;
}
@@ -357,7 +366,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
BOOST_ASSERT(0 != forward_weight2);
const bool add_traffic_signal_penalty =
(m_traffic_lights.find(v) != m_traffic_lights.end());
(m_traffic_lights.find(node_v) != m_traffic_lights.end());
// add weight of e2's to e1
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
@@ -365,43 +374,43 @@ void EdgeBasedGraphFactory::CompressGeometry()
if (add_traffic_signal_penalty)
{
m_node_based_graph->GetEdgeData(forward_e1).distance +=
speed_profile.trafficSignalPenalty;
speed_profile.traffic_signal_penalty;
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
speed_profile.trafficSignalPenalty;
speed_profile.traffic_signal_penalty;
}
// extend e1's to targets of e2's
m_node_based_graph->SetTarget(forward_e1, w);
m_node_based_graph->SetTarget(reverse_e1, u);
m_node_based_graph->SetTarget(forward_e1, node_w);
m_node_based_graph->SetTarget(reverse_e1, node_u);
// remove e2's (if bidir, otherwise only one)
m_node_based_graph->DeleteEdge(v, forward_e2);
m_node_based_graph->DeleteEdge(v, reverse_e2);
m_node_based_graph->DeleteEdge(node_v, forward_e2);
m_node_based_graph->DeleteEdge(node_v, reverse_e2);
// update any involved turn restrictions
m_restriction_map->FixupStartingTurnRestriction(u, v, w);
m_restriction_map->FixupArrivingTurnRestriction(u, v, w);
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w);
m_restriction_map->FixupStartingTurnRestriction(w, v, u);
m_restriction_map->FixupArrivingTurnRestriction(w, v, u);
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u);
// store compressed geometry in container
m_geometry_compressor.CompressEdge(
forward_e1,
forward_e2,
v,
w,
node_v,
node_w,
forward_weight1 +
(add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0),
(add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0),
forward_weight2);
m_geometry_compressor.CompressEdge(
reverse_e1,
reverse_e2,
v,
u,
node_v,
node_u,
reverse_weight1,
reverse_weight2 +
(add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0));
(add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0));
++removed_node_count;
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
@@ -413,7 +422,8 @@ void EdgeBasedGraphFactory::CompressGeometry()
unsigned new_node_count = 0;
unsigned new_edge_count = 0;
for (unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i)
for(const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
if (m_node_based_graph->GetOutDegree(i) > 0)
{
@@ -429,7 +439,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
}
/**
* Writes the id of the edge in the edge expanded graph (into the egde in the node based graph)
* Writes the id of the edge in the edge expanded graph (into the edge in the node based graph)
*/
void EdgeBasedGraphFactory::RenumberEdges()
{
@@ -438,9 +448,7 @@ void EdgeBasedGraphFactory::RenumberEdges()
for (NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes();
++current_node)
{
for (EdgeID current_edge = m_node_based_graph->BeginEdges(current_node);
current_edge < m_node_based_graph->EndEdges(current_node);
++current_edge)
for (EdgeID current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
{
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
if (!edge_data.forward)
@@ -475,24 +483,17 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
<< " many components";
SimpleLogger().Write() << "generating edge-expanded nodes";
Percent p(m_node_based_graph->GetNumberOfNodes());
Percent progress(m_node_based_graph->GetNumberOfNodes());
// loop over all edges and generate new set of nodes
for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
{
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes());
p.printIncrement();
for (EdgeID e1 = m_node_based_graph->BeginEdges(u),
last_edge = m_node_based_graph->EndEdges(u);
e1 < last_edge;
++e1)
progress.printStatus(u);
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
{
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
{
// continue;
}
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
const NodeID v = m_node_based_graph->GetTarget(e1);
@@ -504,7 +505,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
}
BOOST_ASSERT(u < v);
BOOST_ASSERT(edge_data.type != SHRT_MAX);
// Note: edges that end on barrier nodes or on a turn restriction
// may actually be in two distinct components. We choose the smallest
@@ -512,7 +512,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
component_explorer.GetComponentSize(v));
const bool component_is_tiny = (size_of_component < 1000);
InsertEdgeBasedNode(u, v, e1, component_is_tiny);
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
{
InsertEdgeBasedNode(v, u, component_is_tiny);
}
else
{
InsertEdgeBasedNode(u, v, component_is_tiny);
}
}
}
@@ -548,14 +555,12 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
unsigned skipped_barrier_turns_counter = 0;
unsigned compressed = 0;
Percent p(m_node_based_graph->GetNumberOfNodes());
Percent progress(m_node_based_graph->GetNumberOfNodes());
for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
{
for (EdgeID e1 = m_node_based_graph->BeginEdges(u),
last_edge_u = m_node_based_graph->EndEdges(u);
e1 < last_edge_u;
++e1)
progress.printStatus(u);
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
{
if (!m_node_based_graph->GetEdgeData(e1).forward)
{
@@ -568,10 +573,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v);
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
for (EdgeID e2 = m_node_based_graph->BeginEdges(v),
last_edge_v = m_node_based_graph->EndEdges(v);
e2 < last_edge_v;
++e2)
for (EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
{
if (!m_node_based_graph->GetEdgeData(e2).forward)
{
@@ -610,6 +612,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
(to_node_of_only_restriction == SPECIAL_NODEID) &&
(w != to_node_of_only_restriction))
{
// We are at an only_-restriction but not at the right turn.
++restricted_turns_counter;
continue;
}
@@ -626,13 +629,27 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
unsigned distance = edge_data1.distance;
if (m_traffic_lights.find(v) != m_traffic_lights.end())
{
distance += speed_profile.trafficSignalPenalty;
distance += speed_profile.traffic_signal_penalty;
}
const int turn_penalty = GetTurnPenalty(u, v, w, lua_state);
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w);
// unpack last node of first segment if packed
const auto first_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e1) ?
m_geometry_compressor.GetLastNodeIDOfBucket(e1) :
u)];
// unpack first node of second segment if packed
const auto third_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e2) ?
m_geometry_compressor.GetFirstNodeIDOfBucket(e2) :
w)];
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
first_coordinate, m_node_info_list[v], third_coordinate);
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w, turn_angle);
if (turn_instruction == TurnInstruction::UTurn)
{
distance += speed_profile.uTurnPenalty;
distance += speed_profile.u_turn_penalty;
}
distance += turn_penalty;
@@ -647,7 +664,8 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
edge_data1.nameID,
turn_instruction,
edge_is_compressed);
edge_is_compressed,
edge_data2.travel_mode);
++original_edges_counter;
@@ -667,7 +685,6 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
false));
}
}
p.printIncrement();
}
FlushVectorToStream(edge_data_file, original_edge_data_vector);
@@ -686,13 +703,8 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
}
int EdgeBasedGraphFactory::GetTurnPenalty(const NodeID u,
const NodeID v,
const NodeID w,
lua_State *lua_state) const
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
{
const double angle = GetAngleBetweenThreeFixedPointCoordinates(
m_node_info_list[u], m_node_info_list[v], m_node_info_list[w]);
if (speed_profile.has_turn_penalty_function)
{
@@ -706,34 +718,28 @@ int EdgeBasedGraphFactory::GetTurnPenalty(const NodeID u,
return 0;
}
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w)
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
const NodeID node_v,
const NodeID node_w,
const double angle)
const
{
if (u == w)
if (node_u == node_w)
{
return TurnInstruction::UTurn;
}
const EdgeID edge1 = m_node_based_graph->FindEdge(u, v);
const EdgeID edge2 = m_node_based_graph->FindEdge(v, w);
const EdgeID edge1 = m_node_based_graph->FindEdge(node_u, node_v);
const EdgeID edge2 = m_node_based_graph->FindEdge(node_v, node_w);
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
if (!data1.contraFlow && data2.contraFlow)
{
return TurnInstruction::EnterAgainstAllowedDirection;
}
if (data1.contraFlow && !data2.contraFlow)
{
return TurnInstruction::LeaveAgainstAllowedDirection;
}
// roundabouts need to be handled explicitely
if (data1.roundabout && data2.roundabout)
{
// Is a turn possible? If yes, we stay on the roundabout!
if (1 == m_node_based_graph->GetOutDegree(v))
if (1 == m_node_based_graph->GetDirectedOutDegree(node_v))
{
// No turn possible.
return TurnInstruction::NoTurn;
@@ -761,18 +767,12 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID
{
// TODO: Here we should also do a small graph exploration to check for
// more complex situations
if (0 != data1.nameID)
{
return TurnInstruction::NoTurn;
}
else if (m_node_based_graph->GetOutDegree(v) <= 2)
if (0 != data1.nameID || m_node_based_graph->GetOutDegree(node_v) <= 2)
{
return TurnInstruction::NoTurn;
}
}
const double angle = GetAngleBetweenThreeFixedPointCoordinates(
m_node_info_list[u], m_node_info_list[v], m_node_info_list[w]);
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
}
+8 -10
View File
@@ -32,12 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/EdgeBasedNode.h"
#include "../DataStructures/OriginalEdgeData.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/NodeBasedGraph.h"
#include "../DataStructures/RestrictionMap.h"
#include "GeometryCompressor.h"
@@ -76,26 +74,26 @@ class EdgeBasedGraphFactory
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
int GetTurnPenalty(const NodeID u, const NodeID v, const NodeID w, lua_State *lua_state) const;
int GetTurnPenalty(double angle, lua_State *lua_state) const;
unsigned GetNumberOfEdgeBasedNodes() const;
struct SpeedProfileProperties
{
SpeedProfileProperties()
: trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
{
}
int trafficSignalPenalty;
int uTurnPenalty;
int traffic_signal_penalty;
int u_turn_penalty;
bool has_turn_penalty_function;
} speed_profile;
private:
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
using EdgeData = NodeBasedDynamicGraph::EdgeData;
unsigned m_number_of_edge_based_nodes;
@@ -117,12 +115,12 @@ class EdgeBasedGraphFactory
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
lua_State *lua_state);
void InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongsToTinyComponent);
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const bool belongsToTinyComponent);
void FlushVectorToStream(std::ofstream &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
unsigned max_id;
NodeID max_id;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
+30 -14
View File
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GeometryCompressor.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
@@ -35,8 +35,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits>
#include <string>
int current_free_list_maximum = 0;
int UniqueNumber() { return ++current_free_list_maximum; }
int free_list_maximum = 0;
int UniqueNumber() { return ++free_list_maximum; }
GeometryCompressor::GeometryCompressor()
{
@@ -49,14 +49,15 @@ void GeometryCompressor::IncreaseFreeList()
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
for (unsigned i = 100; i > 0; --i)
{
m_free_list.emplace_back(current_free_list_maximum);
++current_free_list_maximum;
m_free_list.emplace_back(free_list_maximum);
++free_list_maximum;
}
}
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
{
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
auto iter = m_edge_id_to_list_index_map.find(edge_id);
return iter != m_edge_id_to_list_index_map.end();
}
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
@@ -71,9 +72,9 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
{
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != number_of_compressed_geometries);
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
// write indices array
unsigned prefix_sum_of_list_indices = 0;
@@ -146,6 +147,7 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
m_free_list.pop_back();
}
// find bucket index
const auto iter = m_edge_id_to_list_index_map.find(edge_id_1);
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
const unsigned edge_bucket_id1 = iter->second;
@@ -197,23 +199,23 @@ void GeometryCompressor::PrintStatistics() const
BOOST_ASSERT(0 == compressed_edges % 2);
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
uint64_t number_of_compressed_geometries = 0;
uint64_t compressed_geometries = 0;
uint64_t longest_chain_length = 0;
for (const std::vector<CompressedNode> &current_vector : m_compressed_geometries)
{
number_of_compressed_geometries += current_vector.size();
compressed_geometries += current_vector.size();
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
}
SimpleLogger().Write() << "Geometry successfully removed:"
"\n compressed edges: " << compressed_edges
<< "\n compressed geometries: " << number_of_compressed_geometries
<< "\n compressed geometries: " << compressed_geometries
<< "\n longest chain length: " << longest_chain_length
<< "\n cmpr ratio: "
<< ((float)compressed_edges /
std::max(number_of_compressed_geometries, (uint64_t)1))
std::max(compressed_geometries, (uint64_t)1))
<< "\n avg chain length: "
<< (float)number_of_compressed_geometries /
<< (float)compressed_geometries /
std::max((uint64_t)1, compressed_edges);
}
@@ -223,3 +225,17 @@ GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
return m_compressed_geometries.at(index);
}
NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const
{
const auto &bucket = GetBucketReference(edge_id);
BOOST_ASSERT(bucket.size() >= 2);
return bucket[1].first;
}
NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const
{
const auto &bucket = GetBucketReference(edge_id);
BOOST_ASSERT(bucket.size() >= 2);
return bucket[bucket.size()-2].first;
}
+6 -4
View File
@@ -25,6 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GEOMETRY_COMPRESSOR_H
#define GEOMETRY_COMPRESSOR_H
#include "../typedefs.h"
#include <unordered_map>
@@ -32,13 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#ifndef GEOMETRY_COMPRESSOR_H
#define GEOMETRY_COMPRESSOR_H
class GeometryCompressor
{
public:
typedef std::pair<NodeID, EdgeWeight> CompressedNode;
using CompressedNode = std::pair<NodeID, EdgeWeight>;
GeometryCompressor();
void CompressEdge(const EdgeID surviving_edge_id,
@@ -54,6 +54,8 @@ class GeometryCompressor
unsigned GetPositionForID(const EdgeID edge_id) const;
const std::vector<GeometryCompressor::CompressedNode> &
GetBucketReference(const EdgeID edge_id) const;
NodeID GetFirstNodeIDOfBucket(const EdgeID edge_id) const;
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
private:
void IncreaseFreeList();
+575
View File
@@ -0,0 +1,575 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Prepare.h"
#include "Contractor.h"
#include "../Algorithms/IteratorBasedCRC32.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/Range.h"
#include "../DataStructures/StaticRTree.h"
#include "../DataStructures/RestrictionMap.h"
#include "../Util/GitDescription.h"
#include "../Util/LuaUtil.h"
#include "../Util/make_unique.hpp"
#include "../Util/OSRMException.h"
#include "../Util/simple_logger.hpp"
#include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include "../typedefs.h"
#include <boost/filesystem/fstream.hpp>
#include <boost/program_options.hpp>
#include <tbb/task_scheduler_init.h>
#include <tbb/parallel_sort.h>
#include <chrono>
#include <memory>
#include <string>
#include <thread>
#include <vector>
Prepare::Prepare() : requested_num_threads(1) {}
Prepare::~Prepare() {}
int Prepare::Process(int argc, char *argv[])
{
LogPolicy::GetInstance().Unmute();
TIMER_START(preparing);
TIMER_START(expansion);
if (!ParseArguments(argc, argv))
{
return 0;
}
if (!boost::filesystem::is_regular_file(input_path))
{
SimpleLogger().Write(logWARNING) << "Input file " << input_path.string() << " not found!";
return 1;
}
if (!boost::filesystem::is_regular_file(profile_path))
{
SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string() << " not found!";
return 1;
}
if (1 > requested_num_threads)
{
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
return 1;
}
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string();
SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
SimpleLogger().Write() << "Threads: " << requested_num_threads;
if (recommended_num_threads != requested_num_threads)
{
SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
<< recommended_num_threads
<< "! This setting may have performance side-effects.";
}
tbb::task_scheduler_init init(requested_num_threads);
LogPolicy::GetInstance().Unmute();
FingerPrint fingerprint_orig;
CheckRestrictionsFile(fingerprint_orig);
boost::filesystem::ifstream input_stream(input_path, std::ios::in | std::ios::binary);
node_filename = input_path.string() + ".nodes";
edge_out = input_path.string() + ".edges";
geometry_filename = input_path.string() + ".geometry";
graph_out = input_path.string() + ".hsgr";
rtree_nodes_path = input_path.string() + ".ramIndex";
rtree_leafs_path = input_path.string() + ".fileIndex";
/*** Setup Scripting Environment ***/
// Create a new lua state
lua_State *lua_state = luaL_newstate();
// Connect LuaBind to this lua state
luabind::open(lua_state);
EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
if (!SetupScriptingEnvironment(lua_state, speed_profile))
{
return 1;
}
#ifdef WIN32
#pragma message("Memory consumption on Windows can be higher due to different bit packing")
#else
static_assert(sizeof(ImportEdge) == 20,
"changing ImportEdge type has influence on memory consumption!");
#endif
NodeID number_of_node_based_nodes =
readBinaryOSRMGraphFromStream(input_stream,
edge_list,
barrier_node_list,
traffic_light_list,
&internal_to_external_node_map,
restriction_list);
input_stream.close();
if (edge_list.empty())
{
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
return 1;
}
SimpleLogger().Write() << restriction_list.size() << " restrictions, "
<< barrier_node_list.size() << " bollard nodes, "
<< traffic_light_list.size() << " traffic lights";
std::vector<EdgeBasedNode> node_based_edge_list;
unsigned number_of_edge_based_nodes = 0;
DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
// init node_based_edge_list, edge_based_edge_list by edgeList
number_of_edge_based_nodes = BuildEdgeExpandedGraph(lua_state,
number_of_node_based_nodes,
node_based_edge_list,
edge_based_edge_list,
speed_profile);
lua_close(lua_state);
TIMER_STOP(expansion);
BuildRTree(node_based_edge_list);
RangebasedCRC32 crc32;
if (crc32.using_hardware())
{
SimpleLogger().Write() << "using hardware based CRC32 computation";
}
else
{
SimpleLogger().Write() << "using software based CRC32 computation";
}
const unsigned crc32_value = crc32(node_based_edge_list);
node_based_edge_list.clear();
node_based_edge_list.shrink_to_fit();
SimpleLogger().Write() << "CRC32: " << crc32_value;
WriteNodeMapping();
/***
* Contracting the edge-expanded graph
*/
SimpleLogger().Write() << "initializing contractor";
auto contractor =
osrm::make_unique<Contractor>(number_of_edge_based_nodes, edge_based_edge_list);
TIMER_START(contraction);
contractor->Run();
TIMER_STOP(contraction);
SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
DeallocatingVector<QueryEdge> contracted_edge_list;
contractor->GetEdges(contracted_edge_list);
contractor.reset();
/***
* Sorting contracted edges in a way that the static query graph can read some in in-place.
*/
tbb::parallel_sort(contracted_edge_list.begin(), contracted_edge_list.end());
const unsigned contracted_edge_count = contracted_edge_list.size();
SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count
<< " edges";
boost::filesystem::ofstream hsgr_output_stream(graph_out, std::ios::binary);
hsgr_output_stream.write((char *)&fingerprint_orig, sizeof(FingerPrint));
const unsigned max_used_node_id = 1 + [&contracted_edge_list]
{
unsigned tmp_max = 0;
for (const QueryEdge &edge : contracted_edge_list)
{
BOOST_ASSERT(SPECIAL_NODEID != edge.source);
BOOST_ASSERT(SPECIAL_NODEID != edge.target);
tmp_max = std::max(tmp_max, edge.source);
tmp_max = std::max(tmp_max, edge.target);
}
return tmp_max;
}();
SimpleLogger().Write(logDEBUG) << "input graph has " << number_of_edge_based_nodes << " nodes";
SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
std::vector<StaticGraph<EdgeData>::NodeArrayEntry> node_array;
node_array.resize(number_of_edge_based_nodes + 1);
SimpleLogger().Write() << "Building node array";
StaticGraph<EdgeData>::EdgeIterator edge = 0;
StaticGraph<EdgeData>::EdgeIterator position = 0;
StaticGraph<EdgeData>::EdgeIterator last_edge = edge;
// initializing 'first_edge'-field of nodes:
for (const auto node : osrm::irange(0u, max_used_node_id))
{
last_edge = edge;
while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node))
{
++edge;
}
node_array[node].first_edge = position; //=edge
position += edge - last_edge; // remove
}
for (const auto sentinel_counter : osrm::irange<unsigned>(max_used_node_id, node_array.size()))
{
// sentinel element, guarded against underflow
node_array[sentinel_counter].first_edge = contracted_edge_count;
}
SimpleLogger().Write() << "Serializing node array";
const unsigned node_array_size = node_array.size();
// serialize crc32, aka checksum
hsgr_output_stream.write((char *)&crc32_value, sizeof(unsigned));
// serialize number of nodes
hsgr_output_stream.write((char *)&node_array_size, sizeof(unsigned));
// serialize number of edges
hsgr_output_stream.write((char *)&contracted_edge_count, sizeof(unsigned));
// serialize all nodes
if (node_array_size > 0)
{
hsgr_output_stream.write((char *)&node_array[0],
sizeof(StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size);
}
// serialize all edges
SimpleLogger().Write() << "Building edge array";
edge = 0;
int number_of_used_edges = 0;
StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
for (const auto edge : osrm::irange<std::size_t>(0, contracted_edge_list.size()))
{
// no eigen loops
BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target);
current_edge.target = contracted_edge_list[edge].target;
current_edge.data = contracted_edge_list[edge].data;
// every target needs to be valid
BOOST_ASSERT(current_edge.target < max_used_node_id);
#ifndef NDEBUG
if (current_edge.data.distance <= 0)
{
SimpleLogger().Write(logWARNING) << "Edge: " << edge
<< ",source: " << contracted_edge_list[edge].source
<< ", target: " << contracted_edge_list[edge].target
<< ", dist: " << current_edge.data.distance;
SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node "
<< contracted_edge_list[edge].source << "/"
<< node_array.size() - 1;
return 1;
}
#endif
hsgr_output_stream.write((char *)&current_edge,
sizeof(StaticGraph<EdgeData>::EdgeArrayEntry));
++number_of_used_edges;
}
hsgr_output_stream.close();
TIMER_STOP(preparing);
SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
SimpleLogger().Write() << "Expansion : " << (number_of_node_based_nodes / TIMER_SEC(expansion))
<< " nodes/sec and "
<< (number_of_edge_based_nodes / TIMER_SEC(expansion)) << " edges/sec";
SimpleLogger().Write() << "Contraction: "
<< (number_of_edge_based_nodes / TIMER_SEC(contraction))
<< " nodes/sec and " << number_of_used_edges / TIMER_SEC(contraction)
<< " edges/sec";
node_array.clear();
SimpleLogger().Write() << "finished preprocessing";
return 0;
}
/**
\brief Parses command line arguments
\param argc count of arguments
\param argv array of arguments
\param result [out] value for exit return value
\return true if everything is ok, false if need to terminate execution
*/
bool Prepare::ParseArguments(int argc, char *argv[])
{
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
"config,c",
boost::program_options::value<boost::filesystem::path>(&config_file_path)
->default_value("contractor.ini"),
"Path to a configuration file.");
// declare a group of options that will be allowed both on command line and in config file
boost::program_options::options_description config_options("Configuration");
config_options.add_options()(
"restrictions,r",
boost::program_options::value<boost::filesystem::path>(&restrictions_path),
"Restrictions file in .osrm.restrictions format")(
"profile,p",
boost::program_options::value<boost::filesystem::path>(&profile_path)
->default_value("profile.lua"),
"Path to LUA routing profile")(
"threads,t",
boost::program_options::value<unsigned int>(&requested_num_threads)
->default_value(tbb::task_scheduler_init::default_num_threads()),
"Number of threads to use");
// hidden options, will be allowed both on command line and in config file, but will not be
// shown to the user
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()(
"input,i",
boost::program_options::value<boost::filesystem::path>(&input_path),
"Input file in .osm, .osm.bz2 or .osm.pbf format");
// positional option
boost::program_options::positional_options_description positional_options;
positional_options.add("input", 1);
// combine above options for parsing
boost::program_options::options_description cmdline_options;
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
boost::program_options::options_description config_file_options;
config_file_options.add(config_options).add(hidden_options);
boost::program_options::options_description visible_options(
"Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
visible_options.add(generic_options).add(config_options);
// parse command line options
boost::program_options::variables_map option_variables;
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
.options(cmdline_options)
.positional(positional_options)
.run(),
option_variables);
if (option_variables.count("version"))
{
SimpleLogger().Write() << g_GIT_DESCRIPTION;
return false;
}
if (option_variables.count("help"))
{
SimpleLogger().Write() << "\n" << visible_options;
return false;
}
boost::program_options::notify(option_variables);
if (!option_variables.count("restrictions"))
{
restrictions_path = std::string(input_path.string() + ".restrictions");
}
if (!option_variables.count("input"))
{
SimpleLogger().Write() << "\n" << visible_options;
return false;
}
return true;
}
/**
\brief Loads and checks file UUIDs
*/
void Prepare::CheckRestrictionsFile(FingerPrint &fingerprint_orig)
{
boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary);
FingerPrint fingerprint_loaded;
unsigned number_of_usable_restrictions = 0;
restriction_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
if (!fingerprint_loaded.TestPrepare(fingerprint_orig))
{
SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
restriction_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
restriction_list.resize(number_of_usable_restrictions);
if (number_of_usable_restrictions > 0)
{
restriction_stream.read((char *)&(restriction_list[0]),
number_of_usable_restrictions * sizeof(TurnRestriction));
}
restriction_stream.close();
}
/**
\brief Setups scripting environment (lua-scripting)
Also initializes speed profile.
*/
bool
Prepare::SetupScriptingEnvironment(lua_State *lua_state,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
{
// open utility libraries string library;
luaL_openlibs(lua_state);
// adjust lua load path
luaAddScriptFolderToLoadPath(lua_state, profile_path.string().c_str());
// Now call our function in a lua script
if (0 != luaL_dofile(lua_state, profile_path.string().c_str()))
{
std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
return false;
}
if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
{
std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
return false;
}
speed_profile.traffic_signal_penalty = 10 * lua_tointeger(lua_state, -1);
SimpleLogger().Write(logDEBUG)
<< "traffic_signal_penalty: " << speed_profile.traffic_signal_penalty;
if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
{
std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
return false;
}
speed_profile.u_turn_penalty = 10 * lua_tointeger(lua_state, -1);
speed_profile.has_turn_penalty_function = lua_function_exists(lua_state, "turn_function");
return true;
}
/**
\brief Building an edge-expanded graph from node-based input and turn restrictions
*/
std::size_t
Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
NodeID number_of_node_based_nodes,
std::vector<EdgeBasedNode> &node_based_edge_list,
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
{
SimpleLogger().Write() << "Generating edge-expanded graph representation";
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
std::unique_ptr<RestrictionMap> restriction_map =
std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
std::shared_ptr<EdgeBasedGraphFactory> edge_based_graph_factory =
std::make_shared<EdgeBasedGraphFactory>(node_based_graph,
std::move(restriction_map),
barrier_node_list,
traffic_light_list,
internal_to_external_node_map,
speed_profile);
edge_list.clear();
edge_list.shrink_to_fit();
edge_based_graph_factory->Run(edge_out, geometry_filename, lua_state);
restriction_list.clear();
restriction_list.shrink_to_fit();
barrier_node_list.clear();
barrier_node_list.shrink_to_fit();
traffic_light_list.clear();
traffic_light_list.shrink_to_fit();
const std::size_t number_of_edge_based_nodes =
edge_based_graph_factory->GetNumberOfEdgeBasedNodes();
BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits<unsigned>::max());
#ifndef WIN32
static_assert(sizeof(EdgeBasedEdge) == 16,
"changing ImportEdge type has influence on memory consumption!");
#endif
edge_based_graph_factory->GetEdgeBasedEdges(edge_based_edge_list);
edge_based_graph_factory->GetEdgeBasedNodes(node_based_edge_list);
edge_based_graph_factory.reset();
node_based_graph.reset();
return number_of_edge_based_nodes;
}
/**
\brief Writing info on original (node-based) nodes
*/
void Prepare::WriteNodeMapping()
{
SimpleLogger().Write() << "writing node map ...";
boost::filesystem::ofstream node_stream(node_filename, std::ios::binary);
const unsigned size_of_mapping = internal_to_external_node_map.size();
node_stream.write((char *)&size_of_mapping, sizeof(unsigned));
if (size_of_mapping > 0)
{
node_stream.write((char *)&(internal_to_external_node_map[0]),
size_of_mapping * sizeof(NodeInfo));
}
node_stream.close();
internal_to_external_node_map.clear();
internal_to_external_node_map.shrink_to_fit();
}
/**
\brief Building rtree-based nearest-neighbor data structure
Saves info to files: '.ramIndex' and '.fileIndex'.
*/
void Prepare::BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list)
{
SimpleLogger().Write() << "building r-tree ...";
StaticRTree<EdgeBasedNode>(node_based_edge_list,
rtree_nodes_path.c_str(),
rtree_leafs_path.c_str(),
internal_to_external_node_map);
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef PREPARE_H
#define PREPARE_H
#include "EdgeBasedGraphFactory.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/StaticGraph.h"
#include "../Util/GraphLoader.h"
#include <boost/filesystem.hpp>
#include <luabind/luabind.hpp>
#include <vector>
/**
\brief class of 'prepare' utility.
*/
class Prepare
{
public:
using EdgeData = QueryEdge::EdgeData;
using InputEdge = DynamicGraph<EdgeData>::InputEdge;
using StaticEdge = StaticGraph<EdgeData>::InputEdge;
explicit Prepare();
Prepare(const Prepare &) = delete;
~Prepare();
int Process(int argc, char *argv[]);
protected:
bool ParseArguments(int argc, char *argv[]);
void CheckRestrictionsFile(FingerPrint &fingerprint_orig);
bool SetupScriptingEnvironment(lua_State *myLuaState,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
std::size_t BuildEdgeExpandedGraph(lua_State *myLuaState,
NodeID nodeBasedNodeNumber,
std::vector<EdgeBasedNode> &nodeBasedEdgeList,
DeallocatingVector<EdgeBasedEdge> &edgeBasedEdgeList,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
void WriteNodeMapping();
void BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list);
private:
std::vector<NodeInfo> internal_to_external_node_map;
std::vector<TurnRestriction> restriction_list;
std::vector<NodeID> barrier_node_list;
std::vector<NodeID> traffic_light_list;
std::vector<ImportEdge> edge_list;
unsigned requested_num_threads;
boost::filesystem::path config_file_path;
boost::filesystem::path input_path;
boost::filesystem::path restrictions_path;
boost::filesystem::path preinfo_path;
boost::filesystem::path profile_path;
std::string node_filename;
std::string edge_out;
std::string info_out;
std::string geometry_filename;
std::string graph_out;
std::string rtree_nodes_path;
std::string rtree_leafs_path;
};
#endif // PREPARE_H
-172
View File
@@ -1,172 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TemporaryStorage.h"
StreamData::StreamData()
: write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory.append(
TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
temp_file(new boost::filesystem::fstream(
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(std::make_shared<boost::mutex>())
{
if (temp_file->fail())
{
throw OSRMException("temporary file could not be created");
}
}
TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
TemporaryStorage &TemporaryStorage::GetInstance()
{
static TemporaryStorage static_instance;
return static_instance;
}
TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
void TemporaryStorage::RemoveAll()
{
boost::mutex::scoped_lock lock(mutex);
for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
{
DeallocateSlot(slot_id);
}
stream_data_list.clear();
}
int TemporaryStorage::AllocateSlot()
{
boost::mutex::scoped_lock lock(mutex);
try { stream_data_list.push_back(StreamData()); }
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
CheckIfTemporaryDeviceFull();
return stream_data_list.size() - 1;
}
void TemporaryStorage::DeallocateSlot(const int slot_id)
{
try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if (!boost::filesystem::exists(data.temp_path))
{
return;
}
if (data.temp_file->is_open())
{
data.temp_file->close();
}
boost::filesystem::remove(data.temp_path);
}
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
}
void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
{
try
{
StreamData &data = stream_data_list[slot_id];
BOOST_ASSERT(data.write_mode);
boost::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
if (1073741824 < data.buffer.size())
{
data.temp_file->write(&data.buffer[0], data.buffer.size());
// data.temp_file->write(pointer, size);
data.buffer.clear();
CheckIfTemporaryDeviceFull();
}
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
}
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
}
void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
{
try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if (data.write_mode)
{
data.write_mode = false;
data.temp_file->write(&data.buffer[0], data.buffer.size());
data.buffer.clear();
data.temp_file->seekg(data.temp_file->beg);
BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg());
}
BOOST_ASSERT(!data.write_mode);
data.temp_file->read(pointer, size);
}
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
}
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
{
uint64_t value = -1;
try
{
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space(p);
value = s.free;
}
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
return value;
}
void TemporaryStorage::CheckIfTemporaryDeviceFull()
{
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space(p);
if ((1024 * 1024) > s.free)
{
throw OSRMException("temporary device is full");
}
}
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
{
boost::filesystem::fstream::pos_type position;
try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.temp_file->tellp();
}
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
return position;
}
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &e)
{
RemoveAll();
throw OSRMException(e.what());
}
-96
View File
@@ -1,96 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TEMPORARYSTORAGE_H_
#define TEMPORARYSTORAGE_H_
#include "../Util/BoostFileSystemFix.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdint>
#include <vector>
#include <fstream>
#include <memory>
struct StreamData
{
bool write_mode;
boost::filesystem::path temp_path;
std::shared_ptr<boost::filesystem::fstream> temp_file;
std::shared_ptr<boost::mutex> readWriteMutex;
std::vector<char> buffer;
StreamData();
};
// This class implements a singleton file storage for temporary data.
// temporary slots can be accessed by other objects through an int
// On deallocation every slot gets deallocated
//
// Access is sequential, which means, that there is no random access
// -> Data is written in first phase and reread in second.
static boost::filesystem::path temp_directory;
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage
{
public:
static TemporaryStorage &GetInstance();
virtual ~TemporaryStorage();
int AllocateSlot();
void DeallocateSlot(const int slot_id);
void WriteToSlot(const int slot_id, char *pointer, const std::size_t size);
void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size);
// returns the number of free bytes
uint64_t GetFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type Tell(const int slot_id);
void RemoveAll();
private:
TemporaryStorage();
TemporaryStorage(TemporaryStorage const &) {};
TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
void Abort(const boost::filesystem::filesystem_error &e);
void CheckIfTemporaryDeviceFull();
// vector of file streams that is used to store temporary data
boost::mutex mutex;
std::vector<StreamData> stream_data_list;
};
#endif /* TEMPORARYSTORAGE_H_ */
+3 -2
View File
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <cstring>
template <typename NodeID, typename Key> class ArrayStorage
{
@@ -99,8 +100,8 @@ class BinaryHeap
void operator=(const BinaryHeap &right);
public:
typedef Weight WeightType;
typedef Data DataType;
using WeightType = Weight;
using DataType = Data;
explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
-5
View File
@@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CONCURRENT_QUEUE_H
#define CONCURRENT_QUEUE_H
#include "../typedefs.h"
#include <boost/circular_buffer.hpp>
#include <condition_variable>
#include <mutex>
@@ -46,7 +44,6 @@ template <typename Data> class ConcurrentQueue
[this]
{ return m_internal_queue.size() < m_internal_queue.capacity(); });
m_internal_queue.push_back(data);
m_mutex.unlock();
m_not_empty.notify_one();
}
@@ -60,7 +57,6 @@ template <typename Data> class ConcurrentQueue
{ return !m_internal_queue.empty(); });
popped_value = m_internal_queue.front();
m_internal_queue.pop_front();
m_mutex.unlock();
m_not_full.notify_one();
}
@@ -73,7 +69,6 @@ template <typename Data> class ConcurrentQueue
}
popped_value = m_internal_queue.front();
m_internal_queue.pop_front();
m_mutex.unlock();
m_not_full.notify_one();
return true;
}
+483 -331
View File
@@ -1,331 +1,483 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <osrm/Coordinate.h>
#include "../Util/MercatorUtil.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#ifndef NDEBUG
#include <bitset>
#endif
#include <iostream>
#include <limits>
FixedPointCoordinate::FixedPointCoordinate()
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
{
}
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
{
#ifndef NDEBUG
if (0 != (std::abs(lat) >> 30))
{
std::bitset<32> y(lat);
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
}
if (0 != (std::abs(lon) >> 30))
{
std::bitset<32> x(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
}
#endif
}
void FixedPointCoordinate::Reset()
{
lat = std::numeric_limits<int>::min();
lon = std::numeric_limits<int>::min();
}
bool FixedPointCoordinate::isSet() const
{
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
}
bool FixedPointCoordinate::isValid() const
{
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
{
return false;
}
return true;
}
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
{
return lat == other.lat && lon == other.lon;
}
double FixedPointCoordinate::ApproximateDistance(const int lat1,
const int lon1,
const int lat2,
const int lon2)
{
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1 / COORDINATE_PRECISION;
double ln1 = lon1 / COORDINATE_PRECISION;
double lt2 = lat2 / COORDINATE_PRECISION;
double ln2 = lon2 / COORDINATE_PRECISION;
double dlat1 = lt1 * (RAD);
double dlong1 = ln1 * (RAD);
double dlat2 = lt2 * (RAD);
double dlong2 = ln2 * (RAD);
double dLong = dlong1 - dlong2;
double dLat = dlat1 - dlat2;
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const double earth = 6372797.560856;
return earth * cHarv;
}
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2)
{
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
}
double FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2)
{
return ApproximateEuclideanDistance(c1.lat, c1.lon, c2.lat, c2.lon);
}
double FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
const int lon1,
const int lat2,
const int lon2)
{
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
const double RAD = 0.017453292519943295769236907684886;
const double float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
const double x = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.);
const double y = (float_lat2 - float_lat1);
const double earth_radius = 6372797.560856;
return sqrt(x * x + y * y) * earth_radius;
}
// Yuck! Code duplication. This function is also in EgdeBasedNode.h
double FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &point,
const FixedPointCoordinate &segA,
const FixedPointCoordinate &segB)
{
const double x = lat2y(point.lat / COORDINATE_PRECISION);
const double y = point.lon / COORDINATE_PRECISION;
const double a = lat2y(segA.lat / COORDINATE_PRECISION);
const double b = segA.lon / COORDINATE_PRECISION;
const double c = lat2y(segB.lat / COORDINATE_PRECISION);
const double d = segB.lon / COORDINATE_PRECISION;
double p, q, nY;
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
{
const double m = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
q = b + m * (p - a);
}
else
{
p = c;
q = y;
}
nY = (d * p - c * q) / (a * d - b * c);
// discretize the result to coordinate precision. it's a hack!
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
{
nY = 0.;
}
double r = (p - nY * a) / c;
if (std::isnan(r))
{
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
}
else if (std::abs(r) <= std::numeric_limits<double>::epsilon())
{
r = 0.;
}
else if (std::abs(r - 1.) <= std::numeric_limits<double>::epsilon())
{
r = 1.;
}
FixedPointCoordinate nearest_location;
BOOST_ASSERT(!std::isnan(r));
if (r <= 0.)
{ // point is "left" of edge
nearest_location.lat = segA.lat;
nearest_location.lon = segA.lon;
}
else if (r >= 1.)
{ // point is "right" of edge
nearest_location.lat = segB.lat;
nearest_location.lon = segB.lon;
}
else
{ // point lies in between
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
nearest_location.lon = q * COORDINATE_PRECISION;
}
BOOST_ASSERT(nearest_location.isValid());
const double approximated_distance =
FixedPointCoordinate::ApproximateDistance(point, nearest_location);
BOOST_ASSERT(0. <= approximated_distance);
return approximated_distance;
}
double FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
const FixedPointCoordinate &coord_b,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
double &r)
{
BOOST_ASSERT(query_location.isValid());
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
const double y = query_location.lon / COORDINATE_PRECISION;
const double a = lat2y(coord_a.lat / COORDINATE_PRECISION);
const double b = coord_a.lon / COORDINATE_PRECISION;
const double c = lat2y(coord_b.lat / COORDINATE_PRECISION);
const double d = coord_b.lon / COORDINATE_PRECISION;
double p, q /*,mX*/, nY;
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
{
const double m = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
q = b + m * (p - a);
}
else
{
p = c;
q = y;
}
nY = (d * p - c * q) / (a * d - b * c);
// discretize the result to coordinate precision. it's a hack!
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
{
nY = 0.;
}
r = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if (std::isnan(r))
{
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
}
else if (std::abs(r) <= std::numeric_limits<double>::epsilon())
{
r = 0.;
}
else if (std::abs(r - 1.) <= std::numeric_limits<double>::epsilon())
{
r = 1.;
}
BOOST_ASSERT(!std::isnan(r));
if (r <= 0.)
{
nearest_location.lat = coord_a.lat;
nearest_location.lon = coord_a.lon;
}
else if (r >= 1.)
{
nearest_location.lat = coord_b.lat;
nearest_location.lon = coord_b.lon;
}
else
{
// point lies in between
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
nearest_location.lon = q * COORDINATE_PRECISION;
}
BOOST_ASSERT(nearest_location.isValid());
// TODO: Replace with euclidean approximation when k-NN search is done
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
const double approximated_distance =
FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
BOOST_ASSERT(0. <= approximated_distance);
return approximated_distance;
}
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
{
char buffer[12];
buffer[11] = 0; // zero termination
output = printInt<11, 6>(buffer, value);
}
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lon, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
}
void
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
}
void FixedPointCoordinate::Output(std::ostream &out) const
{
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
}
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <osrm/Coordinate.h>
#include "../Util/MercatorUtil.h"
#ifndef NDEBUG
#include "../Util/simple_logger.hpp"
#endif
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#ifndef NDEBUG
#include <bitset>
#endif
#include <iostream>
#include <limits>
FixedPointCoordinate::FixedPointCoordinate()
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
{
}
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
{
#ifndef NDEBUG
if (0 != (std::abs(lat) >> 30))
{
std::bitset<32> y_coordinate_vector(lat);
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
<< ", bits: " << y_coordinate_vector;
}
if (0 != (std::abs(lon) >> 30))
{
std::bitset<32> x_coordinate_vector(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
<< ", bits: " << x_coordinate_vector;
}
#endif
}
void FixedPointCoordinate::Reset()
{
lat = std::numeric_limits<int>::min();
lon = std::numeric_limits<int>::min();
}
bool FixedPointCoordinate::isSet() const
{
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
}
bool FixedPointCoordinate::isValid() const
{
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
{
return false;
}
return true;
}
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
{
return lat == other.lat && lon == other.lon;
}
double FixedPointCoordinate::ApproximateDistance(const int lat1,
const int lon1,
const int lat2,
const int lon2)
{
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1 / COORDINATE_PRECISION;
double ln1 = lon1 / COORDINATE_PRECISION;
double lt2 = lat2 / COORDINATE_PRECISION;
double ln2 = lon2 / COORDINATE_PRECISION;
double dlat1 = lt1 * (RAD);
double dlong1 = ln1 * (RAD);
double dlat2 = lt2 * (RAD);
double dlong2 = ln2 * (RAD);
double dLong = dlong1 - dlong2;
double dLat = dlat1 - dlat2;
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const double earth = 6372797.560856;
return earth * cHarv;
}
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
const FixedPointCoordinate &coordinate_2)
{
return ApproximateDistance(
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
}
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
const FixedPointCoordinate &coordinate_2)
{
return ApproximateEuclideanDistance(
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
}
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
const int lon1,
const int lat2,
const int lon2)
{
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
const float RAD = 0.017453292519943295769236907684886f;
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
const float y_value = float_lat2 - float_lat1;
const float earth_radius = 6372797.560856f;
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
}
float
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
const FixedPointCoordinate &target_coordinate,
const FixedPointCoordinate &point)
{
// initialize values
const float x_value = static_cast<float>(lat2y(point.lat / COORDINATE_PRECISION));
const float y_value = point.lon / COORDINATE_PRECISION;
float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
float b = source_coordinate.lon / COORDINATE_PRECISION;
float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
float d = target_coordinate.lon / COORDINATE_PRECISION;
float p, q;
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
{
const float slope = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
(1.f + slope * slope);
q = b + slope * (p - a);
}
else
{
p = c;
q = y_value;
}
float ratio;
bool inverse_ratio = false;
// straight line segment on equator
if (std::abs(c) < std::numeric_limits<float>::epsilon() &&
std::abs(a) < std::numeric_limits<float>::epsilon())
{
ratio = (q - b) / (d - b);
}
else
{
if (std::abs(c) < std::numeric_limits<float>::epsilon())
{
// swap start/end
std::swap(a, c);
std::swap(b, d);
inverse_ratio = true;
}
float nY = (d * p - c * q) / (a * d - b * c);
// discretize the result to coordinate precision. it's a hack!
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
{
nY = 0.f;
}
// compute ratio
ratio = (p - nY * a) / c;
}
if (std::isnan(ratio))
{
ratio = (target_coordinate == point ? 1.f : 0.f);
}
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
{
ratio = 0.f;
}
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
{
ratio = 1.f;
}
// we need to do this, if we switched start/end coordinates
if (inverse_ratio)
{
ratio = 1.0f - ratio;
}
// compute the nearest location
FixedPointCoordinate nearest_location;
BOOST_ASSERT(!std::isnan(ratio));
if (ratio <= 0.f)
{ // point is "left" of edge
nearest_location = source_coordinate;
}
else if (ratio >= 1.f)
{ // point is "right" of edge
nearest_location = target_coordinate;
}
else
{ // point lies in between
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
}
BOOST_ASSERT(nearest_location.isValid());
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
}
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
float &ratio)
{
BOOST_ASSERT(query_location.isValid());
// initialize values
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
const double y = query_location.lon / COORDINATE_PRECISION;
const double a = lat2y(segment_source.lat / COORDINATE_PRECISION);
const double b = segment_source.lon / COORDINATE_PRECISION;
const double c = lat2y(segment_target.lat / COORDINATE_PRECISION);
const double d = segment_target.lon / COORDINATE_PRECISION;
double p, q /*,mX*/, nY;
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
{
const double m = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
q = b + m * (p - a);
}
else
{
p = c;
q = y;
}
nY = (d * p - c * q) / (a * d - b * c);
// discretize the result to coordinate precision. it's a hack!
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
{
nY = 0.f;
}
// compute ratio
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if (std::isnan(ratio))
{
ratio = (segment_target == query_location ? 1.f : 0.f);
}
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
{
ratio = 0.f;
}
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
{
ratio = 1.f;
}
// compute nearest location
BOOST_ASSERT(!std::isnan(ratio));
if (ratio <= 0.f)
{
nearest_location = segment_source;
}
else if (ratio >= 1.f)
{
nearest_location = segment_target;
}
else
{
// point lies in between
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
}
BOOST_ASSERT(nearest_location.isValid());
const float approximate_distance =
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
BOOST_ASSERT(0. <= approximate_distance);
return approximate_distance;
}
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
{
char buffer[12];
buffer[11] = 0; // zero termination
output = printInt<11, 6>(buffer, value);
}
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lon, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
}
void
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
}
void FixedPointCoordinate::Output(std::ostream &out) const
{
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
}
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate)
{
const float lon_diff =
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
const float lon_delta = DegreeToRadian(lon_diff);
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
const float y = sin(lon_delta) * cos(lat2);
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
float result = RadianToDegree(std::atan2(y, x));
while (result < 0.f)
{
result += 360.f;
}
while (result >= 360.f)
{
result -= 360.f;
}
return result;
}
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
{
const float lon_delta =
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
const float y_value = std::sin(lon_delta) * std::cos(lat2);
const float x_value =
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
float result = RadianToDegree(std::atan2(y_value, x_value));
while (result < 0.f)
{
result += 360.f;
}
while (result >= 360.f)
{
result -= 360.f;
}
return result;
}
float FixedPointCoordinate::DegreeToRadian(const float degree)
{
return degree * (static_cast<float>(M_PI) / 180.f);
}
float FixedPointCoordinate::RadianToDegree(const float radian)
{
return radian * (180.f * static_cast<float>(M_1_PI));
}
// This distance computation does integer arithmetic only and is a lot faster than
// the other distance function which are numerically correct('ish).
// It preserves some order among the elements that make it useful for certain purposes
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
const FixedPointCoordinate &input_point,
const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target)
{
// initialize values
const float x = static_cast<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
const float y = input_point.lon / COORDINATE_PRECISION;
const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
const float b = segment_source.lon / COORDINATE_PRECISION;
const float c = static_cast<float>(lat2y(segment_target.lat / COORDINATE_PRECISION));
const float d = segment_target.lon / COORDINATE_PRECISION;
float p, q;
if (a == c)
{
p = c;
q = y;
}
else
{
const float m = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
q = b + m * (p - a);
}
const float nY = (d * p - c * q) / (a * d - b * c);
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if (std::isnan(ratio))
{
ratio = (segment_target == input_point) ? 1.f : 0.f;
}
// compute target quasi-location
int dx, dy;
if (ratio < 0.f)
{
dx = input_point.lon - segment_source.lon;
dy = input_point.lat - segment_source.lat;
}
else if (ratio > 1.f)
{
dx = input_point.lon - segment_target.lon;
dy = input_point.lat - segment_target.lat;
}
else
{
// point lies in between
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
}
// return an approximation in the plane
return static_cast<int>(sqrt(dx * dx + dy * dy));
}
+173 -261
View File
@@ -28,250 +28,154 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include <boost/assert.hpp>
#include <cstring>
#include "Range.h"
#include <boost/iterator/iterator_facade.hpp>
#include <utility>
#include <vector>
template <typename ElementT,
std::size_t bucketSizeC = 8388608 / sizeof(ElementT),
bool DeallocateC = false>
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT>
template <typename ElementT> struct DeallocatingVectorIteratorState
{
protected:
class DeallocatingVectorIteratorState
{
private:
// make constructors explicit, so we do not mix random access and deallocation iterators.
DeallocatingVectorIteratorState();
public:
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
: index(r.index), bucket_list(r.bucket_list)
{
}
explicit DeallocatingVectorIteratorState(const std::size_t idx,
std::vector<ElementT *> &input_list)
: index(idx), bucket_list(input_list)
{
}
std::size_t index;
std::vector<ElementT *> &bucket_list;
inline bool operator!=(const DeallocatingVectorIteratorState &other)
{
return index != other.index;
}
inline bool operator==(const DeallocatingVectorIteratorState &other)
{
return index == other.index;
}
bool operator<(const DeallocatingVectorIteratorState &other) const
{
return index < other.index;
}
bool operator>(const DeallocatingVectorIteratorState &other) const
{
return index > other.index;
}
bool operator>=(const DeallocatingVectorIteratorState &other) const
{
return index >= other.index;
}
// This is a hack to make assignment operator possible with reference member
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &a)
{
if (this != &a)
{
this->DeallocatingVectorIteratorState::
~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
new (this) DeallocatingVectorIteratorState(a); // placement new
}
return *this;
}
};
DeallocatingVectorIteratorState current_state;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type
value_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type
difference_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
DeallocatingVectorIterator() {}
template <typename T2>
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> &r)
: current_state(r.current_state)
DeallocatingVectorIteratorState() : index(-1), bucket_list(nullptr) {}
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
: index(r.index), bucket_list(r.bucket_list)
{
}
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> &input_list)
: current_state(idx, input_list)
explicit DeallocatingVectorIteratorState(const std::size_t idx,
std::vector<ElementT *> *input_list)
: index(idx), bucket_list(input_list)
{
}
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState &r) : current_state(r) {}
std::size_t index;
std::vector<ElementT *> *bucket_list;
template <typename T2>
DeallocatingVectorIterator &operator=(const DeallocatingVectorIterator<T2> &r)
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
{
if (DeallocateC)
{
BOOST_ASSERT(false);
}
current_state = r.current_state;
index = other.index;
bucket_list = other.bucket_list;
return *this;
}
inline DeallocatingVectorIterator &operator++()
{ // prefix
++current_state.index;
return *this;
}
inline DeallocatingVectorIterator &operator--()
{ // prefix
if (DeallocateC)
{
BOOST_ASSERT(false);
}
--current_state.index;
return *this;
}
inline DeallocatingVectorIterator operator++(int)
{ // postfix
DeallocatingVectorIteratorState my_state(current_state);
current_state.index++;
return DeallocatingVectorIterator(my_state);
}
inline DeallocatingVectorIterator operator--(int)
{ // postfix
if (DeallocateC)
{
BOOST_ASSERT(false);
}
DeallocatingVectorIteratorState my_state(current_state);
current_state.index--;
return DeallocatingVectorIterator(my_state);
}
inline DeallocatingVectorIterator operator+(const difference_type &n) const
{
DeallocatingVectorIteratorState my_state(current_state);
my_state.index += n;
return DeallocatingVectorIterator(my_state);
}
inline DeallocatingVectorIterator &operator+=(const difference_type &n)
{
current_state.index += n;
return *this;
}
inline DeallocatingVectorIterator operator-(const difference_type &n) const
{
if (DeallocateC)
{
BOOST_ASSERT(false);
}
DeallocatingVectorIteratorState my_state(current_state);
my_state.index -= n;
return DeallocatingVectorIterator(my_state);
}
inline DeallocatingVectorIterator &operator-=(const difference_type &n) const
{
if (DeallocateC)
{
BOOST_ASSERT(false);
}
current_state.index -= n;
return *this;
}
inline reference operator*() const
{
std::size_t current_bucket = current_state.index / bucketSizeC;
std::size_t current_index = current_state.index % bucketSizeC;
return (current_state.bucket_list[current_bucket][current_index]);
}
inline pointer operator->() const
{
std::size_t current_bucket = current_state.index / bucketSizeC;
std::size_t current_index = current_state.index % bucketSizeC;
return &(current_state.bucket_list[current_bucket][current_index]);
}
inline bool operator!=(const DeallocatingVectorIterator &other)
{
return current_state != other.current_state;
}
inline bool operator==(const DeallocatingVectorIterator &other)
{
return current_state == other.current_state;
}
inline bool operator<(const DeallocatingVectorIterator &other) const
{
return current_state < other.current_state;
}
inline bool operator>(const DeallocatingVectorIterator &other) const
{
return current_state > other.current_state;
}
inline bool operator>=(const DeallocatingVectorIterator &other) const
{
return current_state >= other.current_state;
}
difference_type operator-(const DeallocatingVectorIterator &other)
{
if (DeallocateC)
{
BOOST_ASSERT(false);
}
return current_state.index - other.current_state.index;
}
};
template <typename ElementT, std::size_t bucketSizeC = 8388608 / sizeof(ElementT)>
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
class DeallocatingVectorIterator
: public boost::iterator_facade<DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
ElementT,
std::random_access_iterator_tag>
{
DeallocatingVectorIteratorState<ElementT> current_state;
public:
DeallocatingVectorIterator() {}
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> *input_list)
: current_state(idx, input_list)
{
}
friend class boost::iterator_core_access;
void advance(std::size_t n) { current_state.index += n; }
void increment() { advance(1); }
void decrement() { advance(-1); }
bool equal(DeallocatingVectorIterator const &other) const
{
return current_state.index == other.current_state.index;
}
std::ptrdiff_t distance_to(DeallocatingVectorIterator const &other) const
{
// it is important to implement it 'other minus this'. otherwise sorting breaks
return other.current_state.index - current_state.index;
}
ElementT &dereference() const
{
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
return (current_state.bucket_list->at(current_bucket)[current_index]);
}
ElementT &operator[](const std::size_t index) const
{
const std::size_t current_bucket = (index + current_state.index) / ELEMENTS_PER_BLOCK;
const std::size_t current_index = (index + current_state.index) % ELEMENTS_PER_BLOCK;
return (current_state.bucket_list->at(current_bucket)[current_index]);
}
};
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
class DeallocatingVectorRemoveIterator
: public boost::iterator_facade<DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>,
ElementT,
boost::forward_traversal_tag>
{
DeallocatingVectorIteratorState<ElementT> current_state;
public:
DeallocatingVectorRemoveIterator(std::size_t idx, std::vector<ElementT *> *input_list)
: current_state(idx, input_list)
{
}
friend class boost::iterator_core_access;
void increment()
{
const std::size_t old_bucket = current_state.index / ELEMENTS_PER_BLOCK;
++current_state.index;
const std::size_t new_bucket = current_state.index / ELEMENTS_PER_BLOCK;
if (old_bucket != new_bucket)
{
// delete old bucket entry
if (nullptr != current_state.bucket_list->at(old_bucket))
{
delete[] current_state.bucket_list->at(old_bucket);
current_state.bucket_list->at(old_bucket) = nullptr;
}
}
}
bool equal(DeallocatingVectorRemoveIterator const &other) const
{
return current_state.index == other.current_state.index;
}
std::ptrdiff_t distance_to(DeallocatingVectorRemoveIterator const &other) const
{
return other.current_state.index - current_state.index;
}
ElementT &dereference() const
{
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
return (current_state.bucket_list->at(current_bucket)[current_index]);
}
};
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK = 8388608 / sizeof(ElementT)>
class DeallocatingVector
{
private:
std::size_t current_size;
std::vector<ElementT *> bucket_list;
public:
typedef ElementT value_type;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
using iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
using const_iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
// this iterator deallocates all buckets that have been visited. Iterators to visited objects
// become invalid.
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
// this forward-only iterator deallocates all buckets that have been visited
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
DeallocatingVector() : current_size(0)
{
// initial bucket
bucket_list.emplace_back(new ElementT[bucketSizeC]);
}
DeallocatingVector() : current_size(0) { bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]); }
~DeallocatingVector() { clear(); }
inline void swap(DeallocatingVector<ElementT, bucketSizeC> &other)
inline void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
{
std::swap(current_size, other.current_size);
bucket_list.swap(other.bucket_list);
@@ -280,16 +184,15 @@ class DeallocatingVector
inline void clear()
{
// Delete[]'ing ptr's to all Buckets
for (unsigned i = 0; i < bucket_list.size(); ++i)
for (auto bucket : bucket_list)
{
if (nullptr != bucket_list[i])
if (nullptr != bucket)
{
delete[] bucket_list[i];
bucket_list[i] = nullptr;
delete[] bucket;
bucket = nullptr;
}
}
// Removing all ptrs from vector
std::vector<ElementT *>().swap(bucket_list);
bucket_list.clear(); bucket_list.shrink_to_fit();
current_size = 0;
}
@@ -298,104 +201,113 @@ class DeallocatingVector
const std::size_t current_capacity = capacity();
if (current_size == current_capacity)
{
bucket_list.push_back(new ElementT[bucketSizeC]);
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
}
std::size_t current_index = size() % bucketSizeC;
std::size_t current_index = size() % ELEMENTS_PER_BLOCK;
bucket_list.back()[current_index] = element;
++current_size;
}
inline void emplace_back(const ElementT &&element)
template <typename... Ts> inline void emplace_back(Ts &&... element)
{
const std::size_t current_capacity = capacity();
if (current_size == current_capacity)
{
bucket_list.push_back(new ElementT[bucketSizeC]);
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
}
const std::size_t current_index = size() % bucketSizeC;
bucket_list.back()[current_index] = element;
const std::size_t current_index = size() % ELEMENTS_PER_BLOCK;
bucket_list.back()[current_index] = ElementT(std::forward<Ts>(element)...);
++current_size;
}
inline void reserve(const std::size_t) const
{
// don't do anything
}
inline void reserve(const std::size_t) const { /* don't do anything */ }
inline void resize(const std::size_t new_size)
{
if (new_size > current_size)
if (new_size >= current_size)
{
while (capacity() < new_size)
{
bucket_list.push_back(new ElementT[bucketSizeC]);
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
}
current_size = new_size;
}
if (new_size < current_size)
{
const std::size_t number_of_necessary_buckets = 1 + (new_size / bucketSizeC);
for (unsigned i = number_of_necessary_buckets; i < bucket_list.size(); ++i)
else
{ // down-size
const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK);
for (const auto bucket_index : osrm::irange(number_of_necessary_buckets, bucket_list.size()))
{
delete[] bucket_list[i];
if (nullptr != bucket_list[bucket_index])
{
delete[] bucket_list[bucket_index];
}
}
bucket_list.resize(number_of_necessary_buckets);
current_size = new_size;
}
current_size = new_size;
}
inline std::size_t size() const { return current_size; }
inline std::size_t capacity() const { return bucket_list.size() * bucketSizeC; }
inline std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; }
inline iterator begin() { return iterator(static_cast<std::size_t>(0), bucket_list); }
inline iterator begin() { return iterator(static_cast<std::size_t>(0), &bucket_list); }
inline iterator end() { return iterator(size(), bucket_list); }
inline iterator end() { return iterator(size(), &bucket_list); }
inline deallocation_iterator dbegin()
{
return deallocation_iterator(static_cast<std::size_t>(0), bucket_list);
return deallocation_iterator(static_cast<std::size_t>(0), &bucket_list);
}
inline deallocation_iterator dend() { return deallocation_iterator(size(), bucket_list); }
inline deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); }
inline const_iterator begin() const
{
return const_iterator(static_cast<std::size_t>(0), bucket_list);
return const_iterator(static_cast<std::size_t>(0), &bucket_list);
}
inline const_iterator end() const { return const_iterator(size(), bucket_list); }
inline const_iterator end() const { return const_iterator(size(), &bucket_list); }
inline ElementT &operator[](const std::size_t index)
{
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
return (bucket_list[_bucket][_index]);
}
const inline ElementT &operator[](const std::size_t index) const
{
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
return (bucket_list[_bucket][_index]);
}
inline ElementT &back()
{
std::size_t _bucket = current_size / bucketSizeC;
std::size_t _index = current_size % bucketSizeC;
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
return (bucket_list[_bucket][_index]);
}
const inline ElementT &back() const
{
std::size_t _bucket = current_size / bucketSizeC;
std::size_t _index = current_size % bucketSizeC;
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
return (bucket_list[_bucket][_index]);
}
template<class InputIterator>
const inline void append(InputIterator first, const InputIterator last)
{
InputIterator position = first;
while (position != last)
{
push_back(*position);
++position;
}
}
};
#endif /* DEALLOCATINGVECTOR_H_ */
+104 -70
View File
@@ -28,7 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DYNAMICGRAPH_H
#define DYNAMICGRAPH_H
#include "../DataStructures/DeallocatingVector.h"
#include "DeallocatingVector.h"
#include "Range.h"
#include <boost/assert.hpp>
@@ -37,13 +38,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <limits>
#include <vector>
#include <atomic>
template <typename EdgeDataT> class DynamicGraph
{
public:
typedef EdgeDataT EdgeData;
typedef unsigned NodeIterator;
typedef unsigned EdgeIterator;
using EdgeData = EdgeDataT;
using NodeIterator = unsigned;
using EdgeIterator = unsigned;
using EdgeRange = osrm::range<EdgeIterator>;
class InputEdge
{
@@ -51,57 +54,62 @@ template <typename EdgeDataT> class DynamicGraph
NodeIterator source;
NodeIterator target;
EdgeDataT data;
InputEdge() : source(std::numeric_limits<NodeIterator>::max()), target(std::numeric_limits<NodeIterator>::max()) { }
template<typename... Ts>
InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
bool operator<(const InputEdge &right) const
{
if (source != right.source)
{
return source < right.source;
}
return target < right.target;
}
};
// Constructs an empty graph with a given number of nodes.
explicit DynamicGraph(int32_t nodes) : m_numNodes(nodes), m_numEdges(0)
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
{
m_nodes.reserve(m_numNodes);
m_nodes.resize(m_numNodes);
node_list.reserve(number_of_nodes);
node_list.resize(number_of_nodes);
m_edges.reserve(m_numNodes * 1.1);
m_edges.resize(m_numNodes);
edge_list.reserve(number_of_nodes * 1.1);
edge_list.resize(number_of_nodes);
}
template <class ContainerT> DynamicGraph(const int32_t nodes, const ContainerT &graph)
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
{
m_numNodes = nodes;
m_numEdges = (EdgeIterator)graph.size();
m_nodes.reserve(m_numNodes + 1);
m_nodes.resize(m_numNodes + 1);
number_of_nodes = nodes;
number_of_edges = (EdgeIterator)graph.size();
node_list.reserve(number_of_nodes + 1);
node_list.resize(number_of_nodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for (NodeIterator node = 0; node < m_numNodes; ++node)
for (const auto node : osrm::irange(0u, number_of_nodes))
{
EdgeIterator lastEdge = edge;
while (edge < m_numEdges && graph[edge].source == node)
while (edge < number_of_edges && graph[edge].source == node)
{
++edge;
}
m_nodes[node].firstEdge = position;
m_nodes[node].edges = edge - lastEdge;
position += m_nodes[node].edges;
node_list[node].firstEdge = position;
node_list[node].edges = edge - lastEdge;
position += node_list[node].edges;
}
m_nodes.back().firstEdge = position;
m_edges.reserve(position * 1.1);
m_edges.resize(position);
node_list.back().firstEdge = position;
edge_list.reserve((std::size_t)edge_list.size() * 1.1);
edge_list.resize(position);
edge = 0;
for (NodeIterator node = 0; node < m_numNodes; ++node)
for (const auto node : osrm::irange(0u, number_of_nodes))
{
for (EdgeIterator i = m_nodes[node].firstEdge,
e = m_nodes[node].firstEdge + m_nodes[node].edges;
i != e;
++i)
for (const auto i : osrm::irange(node_list[node].firstEdge,
node_list[node].firstEdge + node_list[node].edges))
{
m_edges[i].target = graph[edge].target;
m_edges[i].data = graph[edge].data;
BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
edge_list[i].target = graph[edge].target;
edge_list[i].data = graph[edge].data;
++edge;
}
}
@@ -109,67 +117,95 @@ template <typename EdgeDataT> class DynamicGraph
~DynamicGraph() {}
unsigned GetNumberOfNodes() const { return m_numNodes; }
unsigned GetNumberOfNodes() const { return number_of_nodes; }
unsigned GetNumberOfEdges() const { return m_numEdges; }
unsigned GetNumberOfEdges() const { return number_of_edges; }
unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
unsigned GetOutDegree(const NodeIterator n) const { return node_list[n].edges; }
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
unsigned GetDirectedOutDegree(const NodeIterator n) const
{
unsigned degree = 0;
for (const auto edge : osrm::irange(BeginEdges(n), EndEdges(n)))
{
if (GetEdgeData(edge).forward)
{
++degree;
}
}
return degree;
}
void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(edge_list[e].target); }
EdgeDataT &GetEdgeData(const EdgeIterator e) { return m_edges[e].data; }
void SetTarget(const EdgeIterator e, const NodeIterator n) { edge_list[e].target = n; }
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return m_edges[e].data; }
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_list[e].data; }
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_list[e].data; }
EdgeIterator BeginEdges(const NodeIterator n) const
{
return EdgeIterator(m_nodes[n].firstEdge);
return EdgeIterator(node_list[n].firstEdge);
}
EdgeIterator EndEdges(const NodeIterator n) const
{
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
return EdgeIterator(node_list[n].firstEdge + node_list[n].edges);
}
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
{
return osrm::irange(BeginEdges(node), EndEdges(node));
}
NodeIterator InsertNode()
{
node_list.emplace_back(node_list.back());
number_of_nodes += 1;
return number_of_nodes;
}
// adds an edge. Invalidates edge iterators for the source node
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
{
Node &node = m_nodes[from];
Node &node = node_list[from];
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
if (newFirstEdge >= m_edges.size() || !isDummy(newFirstEdge))
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge))
{
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
{
node.firstEdge--;
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
edge_list[node.firstEdge] = edge_list[node.firstEdge + node.edges];
}
else
{
EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
EdgeIterator newFirstEdge = (EdgeIterator)edge_list.size();
unsigned newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
EdgeIterator requiredCapacity = newSize + edge_list.size();
EdgeIterator oldCapacity = edge_list.capacity();
if (requiredCapacity >= oldCapacity)
{
m_edges.reserve(requiredCapacity * 1.1);
edge_list.reserve(requiredCapacity * 1.1);
}
m_edges.resize(m_edges.size() + newSize);
for (EdgeIterator i = 0; i < node.edges; ++i)
edge_list.resize(edge_list.size() + newSize);
for (const auto i : osrm::irange(0u, node.edges))
{
m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
edge_list[newFirstEdge + i] = edge_list[node.firstEdge + i];
makeDummy(node.firstEdge + i);
}
for (EdgeIterator i = node.edges + 1; i < newSize; ++i)
for (const auto i : osrm::irange(node.edges + 1, newSize))
{
makeDummy(newFirstEdge + i);
}
node.firstEdge = newFirstEdge;
}
}
Edge &edge = m_edges[node.firstEdge + node.edges];
Edge &edge = edge_list[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
++m_numEdges;
++number_of_edges;
++node.edges;
return EdgeIterator(node.firstEdge + node.edges);
}
@@ -177,15 +213,14 @@ template <typename EdgeDataT> class DynamicGraph
// removes an edge. Invalidates edge iterators for the source node
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
{
Node &node = m_nodes[source];
#pragma omp atomic
--m_numEdges;
Node &node = node_list[source];
--number_of_edges;
--node.edges;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
const unsigned last = node.firstEdge + node.edges;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
// swap with last edge
m_edges[e] = m_edges[last];
edge_list[e] = edge_list[last];
makeDummy(last);
}
@@ -195,20 +230,19 @@ template <typename EdgeDataT> class DynamicGraph
int32_t deleted = 0;
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
{
if (m_edges[i].target == target)
if (edge_list[i].target == target)
{
do
{
deleted++;
m_edges[i] = m_edges[iend - deleted];
edge_list[i] = edge_list[iend - deleted];
makeDummy(iend - deleted);
} while (i < iend - deleted && m_edges[i].target == target);
} while (i < iend - deleted && edge_list[i].target == target);
}
}
#pragma omp atomic
m_numEdges -= deleted;
m_nodes[source].edges -= deleted;
number_of_edges -= deleted;
node_list[source].edges -= deleted;
return deleted;
}
@@ -216,9 +250,9 @@ template <typename EdgeDataT> class DynamicGraph
// searches for a specific edge
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
{
for (EdgeIterator i = BeginEdges(from), iend = EndEdges(from); i != iend; ++i)
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
{
if (to == m_edges[i].target)
if (to == edge_list[i].target)
{
return i;
}
@@ -229,12 +263,12 @@ template <typename EdgeDataT> class DynamicGraph
protected:
bool isDummy(const EdgeIterator edge) const
{
return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
return edge_list[edge].target == (std::numeric_limits<NodeIterator>::max)();
}
void makeDummy(const EdgeIterator edge)
{
m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
edge_list[edge].target = (std::numeric_limits<NodeIterator>::max)();
}
struct Node
@@ -251,11 +285,11 @@ template <typename EdgeDataT> class DynamicGraph
EdgeDataT data;
};
NodeIterator m_numNodes;
EdgeIterator m_numEdges;
NodeIterator number_of_nodes;
std::atomic_uint number_of_edges;
std::vector<Node> m_nodes;
DeallocatingVector<Edge> m_edges;
std::vector<Node> node_list;
DeallocatingVector<Edge> edge_list;
};
#endif // DYNAMICGRAPH_H
+12 -4
View File
@@ -1,7 +1,7 @@
#ifndef EDGE_BASED_NODE_H
#define EDGE_BASED_NODE_H
#include "../Util/SimpleLogger.h"
#include "../DataStructures/TravelMode.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
@@ -25,7 +25,9 @@ struct EdgeBasedNode
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
is_in_tiny_cc(false)
is_in_tiny_cc(false),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
{ }
explicit EdgeBasedNode(
@@ -40,7 +42,9 @@ struct EdgeBasedNode
int reverse_offset,
unsigned packed_geometry_id,
unsigned short fwd_segment_position,
bool belongs_to_tiny_component
bool belongs_to_tiny_component,
TravelMode forward_travel_mode,
TravelMode backward_travel_mode
) :
forward_edge_based_node_id(forward_edge_based_node_id),
reverse_edge_based_node_id(reverse_edge_based_node_id),
@@ -53,7 +57,9 @@ struct EdgeBasedNode
reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id),
fwd_segment_position(fwd_segment_position),
is_in_tiny_cc(belongs_to_tiny_component)
is_in_tiny_cc(belongs_to_tiny_component),
forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
{
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
(reverse_edge_based_node_id != SPECIAL_NODEID));
@@ -85,6 +91,8 @@ struct EdgeBasedNode
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
unsigned short fwd_segment_position; // segment id in a compressed geometry
bool is_in_tiny_cc;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
};
#endif //EDGE_BASED_NODE_H
+216
View File
@@ -0,0 +1,216 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OSRM_FIXED_POINT_NUMBER_H
#define OSRM_FIXED_POINT_NUMBER_H
#include <cmath>
#include <cstdint>
#include <iostream>
#include <limits>
#include <type_traits>
#include <utility>
namespace osrm
{
// implements an binary based fixed point number type
template <unsigned FractionalBitSize,
bool use_64_bits = false,
bool is_unsigned = false,
bool truncate_results = false>
class FixedPointNumber
{
static_assert(FractionalBitSize > 0, "FractionalBitSize must be greater than 0");
static_assert(FractionalBitSize <= 32, "FractionalBitSize must at most 32");
typename std::conditional<use_64_bits, int64_t, int32_t>::type m_fixed_point_state;
constexpr static const decltype(m_fixed_point_state) PRECISION = 1 << FractionalBitSize;
// state signage encapsulates whether the state should either represent a
// signed or an unsigned floating point number
using state_signage =
typename std::conditional<is_unsigned,
typename std::make_unsigned<decltype(m_fixed_point_state)>::type,
decltype(m_fixed_point_state)>::type;
public:
FixedPointNumber() : m_fixed_point_state(0) {}
// the type is either initialized with a floating point value or an
// integral state. Anything else will throw at compile-time.
template <class T>
constexpr FixedPointNumber(const T &&input) noexcept
: m_fixed_point_state(static_cast<decltype(m_fixed_point_state)>(
std::round(std::forward<const T>(input) * PRECISION)))
{
static_assert(
std::is_floating_point<T>::value || std::is_integral<T>::value,
"FixedPointNumber needs to be initialized with floating point or integral value");
}
// get max value
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
constexpr static auto max() noexcept -> T
{
return static_cast<T>(std::numeric_limits<state_signage>::max()) / PRECISION;
}
// get min value
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
constexpr static auto min() noexcept -> T
{
return static_cast<T>(1) / PRECISION;
}
// get lowest value
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
constexpr static auto lowest() noexcept -> T
{
return static_cast<T>(std::numeric_limits<state_signage>::min()) / PRECISION;
}
// cast to floating point type T, return value
template <typename T,
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
explicit operator const T() const noexcept
{
// casts to external type (signed or unsigned) and then to float
return static_cast<T>(static_cast<state_signage>(m_fixed_point_state)) / PRECISION;
}
// warn about cast to integral type T, its disabled for good reason
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
explicit operator T() const
{
static_assert(std::is_integral<T>::value,
"casts to integral types have been disabled on purpose");
}
// compare, ie. sort fixed-point numbers
bool operator<(const FixedPointNumber &other) const noexcept
{
return m_fixed_point_state < other.m_fixed_point_state;
}
// equality, ie. sort fixed-point numbers
bool operator==(const FixedPointNumber &other) const noexcept
{
return m_fixed_point_state == other.m_fixed_point_state;
}
bool operator!=(const FixedPointNumber &other) const { return !(*this == other); }
bool operator>(const FixedPointNumber &other) const { return other < *this; }
bool operator<=(const FixedPointNumber &other) const { return !(other < *this); }
bool operator>=(const FixedPointNumber &other) const { return !(*this < other); }
// arithmetic operators
FixedPointNumber operator+(const FixedPointNumber &other) const noexcept
{
FixedPointNumber tmp = *this;
tmp.m_fixed_point_state += other.m_fixed_point_state;
return tmp;
}
FixedPointNumber &operator+=(const FixedPointNumber &other) noexcept
{
this->m_fixed_point_state += other.m_fixed_point_state;
return *this;
}
FixedPointNumber operator-(const FixedPointNumber &other) const noexcept
{
FixedPointNumber tmp = *this;
tmp.m_fixed_point_state -= other.m_fixed_point_state;
return tmp;
}
FixedPointNumber &operator-=(const FixedPointNumber &other) noexcept
{
this->m_fixed_point_state -= other.m_fixed_point_state;
return *this;
}
FixedPointNumber operator*(const FixedPointNumber &other) const noexcept
{
int64_t temp = this->m_fixed_point_state;
temp *= other.m_fixed_point_state;
// rounding!
if (!truncate_results)
{
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
}
temp >>= FractionalBitSize;
FixedPointNumber tmp;
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
return tmp;
}
FixedPointNumber &operator*=(const FixedPointNumber &other) noexcept
{
int64_t temp = this->m_fixed_point_state;
temp *= other.m_fixed_point_state;
// rounding!
if (!truncate_results)
{
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
}
temp >>= FractionalBitSize;
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
return *this;
}
FixedPointNumber operator/(const FixedPointNumber &other) const noexcept
{
int64_t temp = this->m_fixed_point_state;
temp <<= FractionalBitSize;
temp /= static_cast<int64_t>(other.m_fixed_point_state);
FixedPointNumber tmp;
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
return tmp;
}
FixedPointNumber &operator/=(const FixedPointNumber &other) noexcept
{
int64_t temp = this->m_fixed_point_state;
temp <<= FractionalBitSize;
temp /= static_cast<int64_t>(other.m_fixed_point_state);
FixedPointNumber tmp;
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
return *this;
}
};
static_assert(4 == sizeof(FixedPointNumber<1>), "FP19 has wrong size != 4");
}
#endif // OSRM_FIXED_POINT_NUMBER_H
+26 -13
View File
@@ -28,37 +28,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#include <unordered_map>
#include <vector>
template <typename Key, typename Value> class HashTable : public std::unordered_map<Key, Value>
template <typename Key, typename Value>
class HashTable
{
private:
typedef std::unordered_map<Key, Value> super;
using KeyValPair = std::pair<Key, Value>;
std::vector<KeyValPair> table;
public:
HashTable() : super() {}
HashTable() {}
explicit HashTable(const unsigned size) : super(size) {}
inline void Add(Key const &key, Value const &value)
{
table.emplace_back(std::move(key), std::move(value));
}
inline void Add(Key const &key, Value const &value) { super::emplace(key, value); }
inline void Clear()
{
table.clear();
}
inline const Value Find(Key const &key) const
{
auto iter = super::find(key);
if (iter == super::end())
for (const auto &key_val_pair : table)
{
return Value();
if (key_val_pair.first == key)
{
return key_val_pair.second;
}
}
return iter->second;
return Value();
}
inline const bool Holds(Key const &key) const
{
if (super::find(key) == super::end())
for (const auto &key_val_pair : table)
{
return false;
if (key_val_pair.first == key)
{
return true;
}
}
return true;
return false;
}
};
+2 -2
View File
@@ -32,8 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
uint64_t HilbertCode::operator()(const FixedPointCoordinate &current_coordinate) const
{
unsigned location[2];
location[0] = current_coordinate.lat + (90 * COORDINATE_PRECISION);
location[1] = current_coordinate.lon + (180 * COORDINATE_PRECISION);
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
TransposeCoordinate(location);
return BitInterleaving(location[0], location[1]);
+105
View File
@@ -0,0 +1,105 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ImportEdge.h"
#include <boost/assert.hpp>
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{
if (source == other.source)
{
if (target == other.target)
{
if (weight == other.weight)
{
return forward && backward && ((!other.forward) || (!other.backward));
}
return weight < other.weight;
}
return target < other.target;
}
return source < other.source;
}
NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
bool roundabout,
bool in_tiny_cc,
bool access_restricted,
TravelMode travel_mode,
bool is_split)
: source(source), target(target), name_id(name_id), weight(weight),
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode)
{
}
bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
{
if (source == other.source)
{
if (target == other.target)
{
if (weight == other.weight)
{
return forward && backward && ((!other.forward) || (!other.backward));
}
return weight < other.weight;
}
return target < other.target;
}
return source < other.source;
}
template <class EdgeT>
EdgeBasedEdge::EdgeBasedEdge(const EdgeT &other)
: source(other.source), target(other.target), edge_id(other.data.via),
weight(other.data.distance), forward(other.data.forward), backward(other.data.backward)
{
}
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge::EdgeBasedEdge()
: source(0), target(0), edge_id(0), weight(0), forward(false), backward(false)
{
}
EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID target,
const NodeID edge_id,
const EdgeWeight weight,
const bool forward,
const bool backward)
: source(source), target(target), edge_id(edge_id), weight(weight), forward(forward),
backward(backward)
{
}
+40 -127
View File
@@ -28,151 +28,64 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef IMPORT_EDGE_H
#define IMPORT_EDGE_H
#include "../Util/OSRMException.h"
#include "../DataStructures/TravelMode.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
class NodeBasedEdge
struct NodeBasedEdge
{
bool operator<(const NodeBasedEdge &e) const;
public:
bool operator<(const NodeBasedEdge &e) const
{
if (source() == e.source())
{
if (target() == e.target())
{
if (weight() == e.weight())
{
return (isForward() && isBackward() && ((!e.isForward()) || (!e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
explicit NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
bool roundabout,
bool in_tiny_cc,
bool access_restricted,
TravelMode travel_mode,
bool is_split);
explicit NodeBasedEdge(NodeID s,
NodeID t,
NodeID n,
EdgeWeight w,
bool f,
bool b,
short ty,
bool ra,
bool ig,
bool ar,
bool cf,
bool is_split)
: _source(s), _target(t), _name(n), _weight(w), _type(ty), forward(f), backward(b),
_roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf),
is_split(is_split)
{
if (ty < 0)
{
throw OSRMException("negative edge type");
}
}
NodeID target() const { return _target; }
NodeID source() const { return _source; }
NodeID name() const { return _name; }
EdgeWeight weight() const { return _weight; }
short type() const
{
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
return _type;
}
bool isBackward() const { return backward; }
bool isForward() const { return forward; }
bool isLocatable() const { return _type != 14; }
bool isRoundabout() const { return _roundabout; }
bool ignoreInGrid() const { return _ignoreInGrid; }
bool isAccessRestricted() const { return _accessRestricted; }
bool isContraFlow() const { return _contraFlow; }
bool IsSplit() const { return is_split; }
// TODO: names need to be fixed.
NodeID _source;
NodeID _target;
NodeID _name;
EdgeWeight _weight;
short _type;
NodeID source;
NodeID target;
NodeID name_id;
EdgeWeight weight;
bool forward : 1;
bool backward : 1;
bool _roundabout : 1;
bool _ignoreInGrid : 1;
bool _accessRestricted : 1;
bool _contraFlow : 1;
bool roundabout : 1;
bool in_tiny_cc : 1;
bool access_restricted : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
private:
NodeBasedEdge() {}
NodeBasedEdge() = delete;
};
class EdgeBasedEdge
struct EdgeBasedEdge
{
public:
bool operator<(const EdgeBasedEdge &e) const
{
if (source() == e.source())
{
if (target() == e.target())
{
if (weight() == e.weight())
{
return (isForward() && isBackward() && ((!e.isForward()) || (!e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
bool operator<(const EdgeBasedEdge &e) const;
template <class EdgeT>
explicit EdgeBasedEdge(const EdgeT &myEdge)
: m_source(myEdge.source), m_target(myEdge.target), m_edgeID(myEdge.data.via),
m_weight(myEdge.data.distance), m_forward(myEdge.data.forward),
m_backward(myEdge.data.backward)
{
}
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge()
: m_source(0), m_target(0), m_edgeID(0), m_weight(0), m_forward(false), m_backward(false)
{
}
EdgeBasedEdge();
explicit EdgeBasedEdge(const NodeID s,
const NodeID t,
const NodeID v,
const EdgeWeight w,
const bool f,
const bool b)
: m_source(s), m_target(t), m_edgeID(v), m_weight(w), m_forward(f), m_backward(b)
{
}
NodeID target() const { return m_target; }
NodeID source() const { return m_source; }
EdgeWeight weight() const { return m_weight; }
NodeID id() const { return m_edgeID; }
bool isBackward() const { return m_backward; }
bool isForward() const { return m_forward; }
private:
NodeID m_source;
NodeID m_target;
NodeID m_edgeID;
EdgeWeight m_weight : 30;
bool m_forward : 1;
bool m_backward : 1;
explicit EdgeBasedEdge(const NodeID source,
const NodeID target,
const NodeID edge_id,
const EdgeWeight weight,
const bool forward,
const bool backward);
NodeID source;
NodeID target;
NodeID edge_id;
EdgeWeight weight : 30;
bool forward : 1;
bool backward : 1;
};
typedef NodeBasedEdge ImportEdge;
using ImportEdge = NodeBasedEdge;
#endif /* IMPORT_EDGE_H */
+64
View File
@@ -0,0 +1,64 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ImportNode.h"
#include <limits>
ExternalMemoryNode::ExternalMemoryNode(
int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
: NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
{
}
ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
{
}
ExternalMemoryNode ExternalMemoryNode::min_value()
{
return ExternalMemoryNode(0, 0, 0, false, false);
}
ExternalMemoryNode ExternalMemoryNode::max_value()
{
return ExternalMemoryNode(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(),
false,
false);
}
void ImportNode::Clear()
{
keyVals.Clear();
lat = 0;
lon = 0;
node_id = 0;
bollard = false;
trafficLight = false;
}
+5 -26
View File
@@ -31,30 +31,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "QueryNode.h"
#include "../DataStructures/HashTable.h"
#include <limits>
#include <string>
struct ExternalMemoryNode : NodeInfo
{
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light)
: NodeInfo(lat, lon, id), bollard(bollard), trafficLight(traffic_light)
{
}
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
ExternalMemoryNode();
static ExternalMemoryNode min_value() { return ExternalMemoryNode(0, 0, 0, false, false); }
static ExternalMemoryNode min_value();
static ExternalMemoryNode max_value()
{
return ExternalMemoryNode(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(),
false,
false);
}
NodeID key() const { return id; }
static ExternalMemoryNode max_value();
bool bollard;
bool trafficLight;
@@ -64,15 +51,7 @@ struct ImportNode : public ExternalMemoryNode
{
HashTable<std::string, std::string> keyVals;
inline void Clear()
{
keyVals.clear();
lat = 0;
lon = 0;
id = 0;
bollard = false;
trafficLight = false;
}
inline void Clear();
};
#endif /* IMPORTNODE_H_ */
+6 -6
View File
@@ -44,8 +44,8 @@ struct BZ2Context
int readFromBz2Stream(void *pointer, char *buffer, int len)
{
void *unusedTmpVoid = NULL;
char *unusedTmp = NULL;
void *unusedTmpVoid = nullptr;
char *unusedTmp = nullptr;
BZ2Context *context = (BZ2Context *)pointer;
int read = 0;
while (0 == read &&
@@ -76,7 +76,7 @@ int readFromBz2Stream(void *pointer, char *buffer, int len)
{
context->bz2 = BZ2_bzReadOpen(
&context->error, context->file, 0, 0, context->unused, context->nUnused);
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
}
}
else
@@ -107,12 +107,12 @@ xmlTextReaderPtr inputReaderFactory(const char *name)
int error;
context->bz2 =
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
if (context->bz2 == NULL || context->file == NULL)
if (context->bz2 == nullptr || context->file == nullptr)
{
delete context;
return NULL;
return nullptr;
}
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, NULL, NULL, 0);
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
}
else
{
+236
View File
@@ -0,0 +1,236 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// based on
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
#ifndef JSON_CONTAINER_H
#define JSON_CONTAINER_H
#include "../ThirdParty/variant/variant.hpp"
#include "../Util/cast.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
namespace JSON
{
struct Object;
struct Array;
struct String
{
String() {}
String(const char *value) : value(value) {}
String(const std::string &value) : value(value) {}
std::string value;
};
struct Number
{
Number() {}
Number(double value) : value(value) {}
double value;
};
struct True
{
};
struct False
{
};
struct Null
{
};
using Value = mapbox::util::variant<String,
Number,
mapbox::util::recursive_wrapper<Object>,
mapbox::util::recursive_wrapper<Array>,
True,
False,
Null>;
struct Object
{
std::unordered_map<std::string, Value> values;
};
struct Array
{
std::vector<Value> values;
};
struct Renderer : mapbox::util::static_visitor<>
{
explicit Renderer(std::ostream &_out) : out(_out) {}
void operator()(const String &string) const { out << "\"" << string.value << "\""; }
void operator()(const Number &number) const
{
out.precision(10);
out << number.value;
}
void operator()(const Object &object) const
{
out << "{";
auto iterator = object.values.begin();
while (iterator != object.values.end())
{
out << "\"" << (*iterator).first << "\":";
mapbox::util::apply_visitor(Renderer(out), (*iterator).second);
if (++iterator != object.values.end())
{
out << ",";
}
}
out << "}";
}
void operator()(const Array &array) const
{
out << "[";
std::vector<Value>::const_iterator iterator;
iterator = array.values.begin();
while (iterator != array.values.end())
{
mapbox::util::apply_visitor(Renderer(out), *iterator);
if (++iterator != array.values.end())
{
out << ",";
}
}
out << "]";
}
void operator()(const True &) const { out << "true"; }
void operator()(const False &) const { out << "false"; }
void operator()(const Null &) const { out << "null"; }
private:
std::ostream &out;
};
struct ArrayRenderer : mapbox::util::static_visitor<>
{
explicit ArrayRenderer(std::vector<char> &_out) : out(_out) {}
void operator()(const String &string) const
{
out.push_back('\"');
out.insert(out.end(), string.value.begin(), string.value.end());
out.push_back('\"');
}
void operator()(const Number &number) const
{
const std::string number_string = cast::double_fixed_to_string(number.value);
out.insert(out.end(), number_string.begin(), number_string.end());
}
void operator()(const Object &object) const
{
out.push_back('{');
auto iterator = object.values.begin();
while (iterator != object.values.end())
{
out.push_back('\"');
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
out.push_back('\"');
out.push_back(':');
mapbox::util::apply_visitor(ArrayRenderer(out), (*iterator).second);
if (++iterator != object.values.end())
{
out.push_back(',');
}
}
out.push_back('}');
}
void operator()(const Array &array) const
{
out.push_back('[');
std::vector<Value>::const_iterator iterator;
iterator = array.values.begin();
while (iterator != array.values.end())
{
mapbox::util::apply_visitor(ArrayRenderer(out), *iterator);
if (++iterator != array.values.end())
{
out.push_back(',');
}
}
out.push_back(']');
}
void operator()(const True &) const
{
const std::string temp("true");
out.insert(out.end(), temp.begin(), temp.end());
}
void operator()(const False &) const
{
const std::string temp("false");
out.insert(out.end(), temp.begin(), temp.end());
}
void operator()(const Null &) const
{
const std::string temp("null");
out.insert(out.end(), temp.begin(), temp.end());
}
private:
std::vector<char> &out;
};
inline void render(std::ostream &out, const Object &object)
{
Value value = object;
mapbox::util::apply_visitor(Renderer(out), value);
}
inline void render(std::vector<char> &out, const Object &object)
{
Value value = object;
mapbox::util::apply_visitor(ArrayRenderer(out), value);
}
} // namespace JSON
#endif // JSON_CONTAINER_H
+169 -34
View File
@@ -1,8 +1,11 @@
#ifndef __NODE_BASED_GRAPH_H__
#define __NODE_BASED_GRAPH_H__
#ifndef NODE_BASED_GRAPH_H_
#define NODE_BASED_GRAPH_H_
#include "DynamicGraph.h"
#include "ImportEdge.h"
#include "../Util/simple_logger.hpp"
#include <tbb/parallel_sort.h>
#include <memory>
@@ -10,23 +13,22 @@ struct NodeBasedEdgeData
{
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
nameID(std::numeric_limits<unsigned>::max()),
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
roundabout(false), ignore_in_grid(false), contraFlow(false)
roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
short type;
bool isAccessRestricted : 1;
bool shortcut : 1;
bool forward : 1;
bool backward : 1;
bool roundabout : 1;
bool ignore_in_grid : 1;
bool contraFlow : 1;
TravelMode travel_mode : 4;
void SwapDirectionFlags()
{
@@ -39,37 +41,42 @@ struct NodeBasedEdgeData
{
return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
(contraFlow == other.contraFlow);
(travel_mode == other.travel_mode);
}
};
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
struct SimpleEdgeData
{
SimpleEdgeData() : capacity(0) {}
EdgeWeight capacity;
};
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
// Factory method to create NodeBasedDynamicGraph from ImportEdges
inline std::shared_ptr<NodeBasedDynamicGraph>
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
{
std::sort(input_edge_list.begin(), input_edge_list.end());
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
// TODO: remove duplicate edges
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
NodeBasedDynamicGraph::InputEdge edge;
for (const ImportEdge &import_edge : input_edge_list)
{
// TODO: give ImportEdge a proper c'tor to use emplace_back's below
if (!import_edge.isForward())
if (import_edge.forward)
{
edge.source = import_edge.target();
edge.target = import_edge.source();
edge.data.backward = import_edge.isForward();
edge.data.forward = import_edge.isBackward();
edge.source = import_edge.source;
edge.target = import_edge.target;
edge.data.forward = import_edge.forward;
edge.data.backward = import_edge.backward;
}
else
{
edge.source = import_edge.source();
edge.target = import_edge.target();
edge.data.forward = import_edge.isForward();
edge.data.backward = import_edge.isBackward();
edge.source = import_edge.target;
edge.target = import_edge.source;
edge.data.backward = import_edge.forward;
edge.data.forward = import_edge.backward;
}
if (edge.source == edge.target)
@@ -77,18 +84,18 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
continue;
}
edge.data.distance = (std::max)((int)import_edge.weight(), 1);
edge.data.distance = (std::max)((int)import_edge.weight, 1);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false;
edge.data.roundabout = import_edge.isRoundabout();
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
edge.data.nameID = import_edge.name();
edge.data.type = import_edge.type();
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
edge.data.contraFlow = import_edge.isContraFlow();
edge.data.roundabout = import_edge.roundabout;
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
edge.data.nameID = import_edge.name_id;
edge.data.isAccessRestricted = import_edge.access_restricted;
edge.data.travel_mode = import_edge.travel_mode;
edges_list.push_back(edge);
if (!import_edge.IsSplit())
if (!import_edge.is_split)
{
using std::swap; // enable ADL
swap(edge.source, edge.target);
@@ -97,13 +104,141 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
}
}
std::sort(edges_list.begin(), edges_list.end());
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
edges_list.clear();
BOOST_ASSERT(0 == edges_list.size());
// remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
NodeID edge_count = 0;
for (NodeID i = 0; i < edges_list.size(); )
{
const NodeID source = edges_list[i].source;
const NodeID target = edges_list[i].target;
// remove eigenloops
if (source == target)
{
i++;
continue;
}
NodeBasedDynamicGraph::InputEdge forward_edge;
NodeBasedDynamicGraph::InputEdge reverse_edge;
forward_edge = reverse_edge = edges_list[i];
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
forward_edge.data.distance = reverse_edge.data.distance =
std::numeric_limits<int>::max();
// remove parallel edges
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
{
if (edges_list[i].data.forward)
{
forward_edge.data.distance =
std::min(edges_list[i].data.distance, forward_edge.data.distance);
}
if (edges_list[i].data.backward)
{
reverse_edge.data.distance =
std::min(edges_list[i].data.distance, reverse_edge.data.distance);
}
++i;
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.distance == reverse_edge.data.distance)
{
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
{
forward_edge.data.backward = true;
edges_list[edge_count++] = forward_edge;
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
{
edges_list[edge_count++] = forward_edge;
}
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
{
edges_list[edge_count++] = reverse_edge;
}
}
}
edges_list.resize(edge_count);
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
auto graph = std::make_shared<NodeBasedDynamicGraph>(static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
return graph;
}
#endif // __NODE_BASED_GRAPH_H__
template<class SimpleEdgeT>
inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &input_edge_list)
{
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
DeallocatingVector<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
SimpleNodeBasedDynamicGraph::InputEdge edge;
edge.data.capacity = 1;
for (const SimpleEdgeT &import_edge : input_edge_list)
{
if (import_edge.source == import_edge.target)
{
continue;
}
edge.source = import_edge.source;
edge.target = import_edge.target;
edges_list.push_back(edge);
std::swap(edge.source, edge.target);
edges_list.push_back(edge);
}
// remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
NodeID edge_count = 0;
for (NodeID i = 0; i < edges_list.size(); )
{
const NodeID source = edges_list[i].source;
const NodeID target = edges_list[i].target;
// remove eigenloops
if (source == target)
{
i++;
continue;
}
SimpleNodeBasedDynamicGraph::InputEdge forward_edge;
SimpleNodeBasedDynamicGraph::InputEdge reverse_edge;
forward_edge = reverse_edge = edges_list[i];
forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
// remove parallel edges
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
{
forward_edge.data.capacity = std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
reverse_edge.data.capacity = std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
++i;
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.capacity == reverse_edge.data.capacity)
{
if ((int)forward_edge.data.capacity != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = forward_edge;
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = forward_edge;
}
if ((int)reverse_edge.data.capacity != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = reverse_edge;
}
}
}
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
return graph;
}
#endif // NODE_BASED_GRAPH_H_
+7 -3
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ORIGINAL_EDGE_DATA_H
#include "TurnInstructions.h"
#include "../DataStructures/TravelMode.h"
#include "../typedefs.h"
#include <limits>
@@ -38,16 +39,18 @@ struct OriginalEdgeData
explicit OriginalEdgeData(NodeID via_node,
unsigned name_id,
TurnInstruction turn_instruction,
bool compressed_geometry)
bool compressed_geometry,
TravelMode travel_mode)
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
compressed_geometry(compressed_geometry)
compressed_geometry(compressed_geometry), travel_mode(travel_mode)
{
}
OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()),
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false)
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
@@ -55,6 +58,7 @@ struct OriginalEdgeData
unsigned name_id;
TurnInstruction turn_instruction;
bool compressed_geometry;
TravelMode travel_mode;
};
#endif // ORIGINAL_EDGE_DATA_H
+2 -4
View File
@@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef PERCENT_H
#define PERCENT_H
#include "../Util/OpenMPWrapper.h"
#include <iostream>
#include <atomic>
class Percent
{
@@ -61,20 +61,18 @@ class Percent
void printIncrement()
{
#pragma omp atomic
++m_current_value;
printStatus(m_current_value);
}
void printAddition(const unsigned addition)
{
#pragma omp atomic
m_current_value += addition;
printStatus(m_current_value);
}
private:
unsigned m_current_value;
std::atomic_uint m_current_value;
unsigned m_max_value;
unsigned m_percent_interval;
unsigned m_next_threshold;
+42 -35
View File
@@ -29,11 +29,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define PHANTOM_NODES_H
#include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h"
#include "../DataStructures/TravelMode.h"
#include "../Util/simple_logger.hpp"
#include "../typedefs.h"
#include <vector>
struct PhantomNode
{
PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
unsigned packed_geometry_id, FixedPointCoordinate &location,
unsigned short fwd_segment_position,
TravelMode forward_travel_mode, TravelMode backward_travel_mode) :
forward_node_id(forward_node_id),
reverse_node_id(reverse_node_id),
name_id(name_id),
forward_weight(forward_weight),
reverse_weight(reverse_weight),
forward_offset(forward_offset),
reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id),
location(location),
fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
{ }
PhantomNode() :
forward_node_id(SPECIAL_NODEID),
reverse_node_id(SPECIAL_NODEID),
@@ -43,7 +65,9 @@ struct PhantomNode
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position(0)
fwd_segment_position(0),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
{ }
NodeID forward_node_id;
@@ -56,6 +80,8 @@ struct PhantomNode
unsigned packed_geometry_id;
FixedPointCoordinate location;
unsigned short fwd_segment_position;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
int GetForwardWeightPlusOffset() const
{
@@ -77,17 +103,6 @@ struct PhantomNode
return result;
}
void Reset()
{
forward_node_id = SPECIAL_NODEID;
name_id = SPECIAL_NODEID;
forward_weight = INVALID_EDGE_WEIGHT;
reverse_weight = INVALID_EDGE_WEIGHT;
forward_offset = 0;
reverse_offset = 0;
location.Reset();
}
bool isBidirected() const
{
return (forward_node_id != SPECIAL_NODEID) &&
@@ -115,38 +130,30 @@ struct PhantomNode
);
}
bool isValid() const
{
return location.isValid() &&
(name_id != std::numeric_limits<unsigned>::max());
}
bool operator==(const PhantomNode & other) const
{
return location == other.location;
}
};
using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
struct PhantomNodeLists
{
std::vector<PhantomNode> source_phantom_list;
std::vector<PhantomNode> target_phantom_list;
};
struct PhantomNodes
{
PhantomNode source_phantom;
PhantomNode target_phantom;
void Reset()
{
source_phantom.Reset();
target_phantom.Reset();
}
bool PhantomsAreOnSameNodeBasedEdge() const
{
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
}
bool AtLeastOnePhantomNodeIsInvalid() const
{
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
}
bool PhantomNodesHaveEqualLocation() const
{
return source_phantom == target_phantom;
}
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
+17
View File
@@ -36,6 +36,16 @@ struct QueryEdge
NodeID target;
struct EdgeData
{
EdgeData() : id(0), shortcut(false), distance(0), forward(false), backward(false) {}
template <class OtherT> EdgeData(const OtherT &other)
{
distance = other.distance;
shortcut = other.shortcut;
id = other.id;
forward = other.forward;
backward = other.backward;
}
NodeID id : 31;
bool shortcut : 1;
int distance : 30;
@@ -43,6 +53,13 @@ struct QueryEdge
bool backward : 1;
} data;
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
QueryEdge(NodeID source, NodeID target, EdgeData data)
: source(source), target(target), data(data)
{
}
bool operator<(const QueryEdge &right) const
{
if (source != right.source)
+9 -9
View File
@@ -38,31 +38,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct NodeInfo
{
typedef NodeID key_type; // type of NodeID
typedef int value_type; // type of lat,lons
using key_type = NodeID; // type of NodeID
using value_type = int; // type of lat,lons
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) {}
explicit NodeInfo(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
NodeInfo()
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
id(std::numeric_limits<unsigned>::max())
node_id(std::numeric_limits<unsigned>::max())
{
}
int lat;
int lon;
NodeID id;
NodeID node_id;
static NodeInfo min_value()
{
return NodeInfo(-90 * COORDINATE_PRECISION,
-180 * COORDINATE_PRECISION,
return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
static_cast<int>(-180 * COORDINATE_PRECISION),
std::numeric_limits<NodeID>::min());
}
static NodeInfo max_value()
{
return NodeInfo(90 * COORDINATE_PRECISION,
180 * COORDINATE_PRECISION,
return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
static_cast<int>(180 * COORDINATE_PRECISION),
std::numeric_limits<NodeID>::max());
}
+67
View File
@@ -0,0 +1,67 @@
/*
Copyright (c) 2013,2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RANGE_H
#define RANGE_H
#include <type_traits>
namespace osrm
{
template <typename Integer> class range
{
private:
Integer last;
Integer iter;
public:
range(Integer start, Integer end) : last(end), iter(start)
{
static_assert(std::is_integral<Integer>::value, "range type must be integral");
}
// Iterable functions
const range &begin() const { return *this; }
const range &end() const { return *this; }
Integer front() const { return iter; }
Integer back() const { return last - 1; }
// Iterator functions
bool operator!=(const range &) const { return iter < last; }
void operator++() { ++iter; }
Integer operator*() const { return iter; }
};
// convenience function to construct an integer range with type deduction
template <typename Integer> range<Integer> irange(Integer first, Integer last)
{
return range<Integer>(first, last);
}
}
#endif // RANGE_H
+231
View File
@@ -0,0 +1,231 @@
#ifndef RANGE_TABLE_H_
#define RANGE_TABLE_H_
#include "Range.h"
#include "SharedMemoryFactory.h"
#include "SharedMemoryVectorWrapper.h"
#include <fstream>
#include <vector>
#include <array>
/*
* These pre-declarations are needed because parsing C++ is hard
* and otherwise the compiler gets confused.
*/
template<unsigned BLOCK_SIZE=16, bool USE_SHARED_MEMORY = false> class RangeTable;
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
/**
* Stores adjacent ranges in a compressed format.
*
* Maximum supported length of a range is 255.
*
* Note: BLOCK_SIZE is the number of differential encodoed values.
* But each block consists of an absolute value and BLOCK_SIZE differential values.
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
*/
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
class RangeTable
{
public:
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
using RangeT = osrm::range<unsigned>;
friend std::ostream& operator<< <>(std::ostream &out, const RangeTable &table);
friend std::istream& operator>> <>(std::istream &in, RangeTable &table);
RangeTable() : sum_lengths(0) {}
// for loading from shared memory
explicit RangeTable(OffsetContainerT& external_offsets, BlockContainerT& external_blocks, const unsigned sum_lengths)
: sum_lengths(sum_lengths)
{
block_offsets.swap(external_offsets);
diff_blocks.swap(external_blocks);
}
// construct table from length vector
explicit RangeTable(const std::vector<unsigned>& lengths)
{
const unsigned number_of_blocks = [&lengths]() {
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
{
num += 1;
}
return num;
}();
block_offsets.reserve(number_of_blocks);
diff_blocks.reserve(number_of_blocks);
unsigned last_length = 0;
unsigned lengths_prefix_sum = 0;
unsigned block_idx = 0;
unsigned block_counter = 0;
BlockT block;
unsigned block_sum = 0;
for (const unsigned l : lengths)
{
// first entry of a block: encode absolute offset
if (block_idx == 0)
{
block_offsets.push_back(lengths_prefix_sum);
block_sum = 0;
}
else
{
block[block_idx - 1] = last_length;
block_sum += last_length;
}
BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum)
|| lengths_prefix_sum == (block_offsets[block_counter]+block_sum));
// block is full
if (BLOCK_SIZE == block_idx)
{
diff_blocks.push_back(block);
block_counter++;
}
// we can only store strings with length 255
BOOST_ASSERT(l <= 255);
lengths_prefix_sum += l;
last_length = l;
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
}
// Last block can't be finished because we didn't add the sentinel
BOOST_ASSERT (block_counter == (number_of_blocks - 1));
// one block missing: starts with guard value
if (0 == block_idx)
{
// the last value is used as sentinel
block_offsets.push_back(lengths_prefix_sum);
block_idx = 1;
last_length = 0;
}
while (0 != block_idx)
{
block[block_idx - 1] = last_length;
last_length = 0;
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
}
diff_blocks.push_back(block);
BOOST_ASSERT(diff_blocks.size() == number_of_blocks && block_offsets.size() == number_of_blocks);
sum_lengths = lengths_prefix_sum;
}
inline RangeT GetRange(const unsigned id) const
{
BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
// internal_idx 0 is implicitly stored in block_offsets[block_idx]
const unsigned internal_idx = id % (BLOCK_SIZE + 1);
const unsigned block_idx = id / (BLOCK_SIZE + 1);
BOOST_ASSERT(block_idx < diff_blocks.size());
unsigned begin_idx = 0;
unsigned end_idx = 0;
begin_idx = block_offsets[block_idx];
const BlockT& block = diff_blocks[block_idx];
if (internal_idx > 0)
{
begin_idx += PrefixSumAtIndex(internal_idx - 1, block);
}
// next index inside current block
if (internal_idx < BLOCK_SIZE)
{
// note internal_idx - 1 is the *current* index for uint8_blocks
end_idx = begin_idx + block[internal_idx];
}
else
{
BOOST_ASSERT(block_idx < block_offsets.size() - 1);
end_idx = block_offsets[block_idx + 1];
}
BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
BOOST_ASSERT(begin_idx <= end_idx);
return osrm::irange(begin_idx, end_idx);
}
private:
inline unsigned PrefixSumAtIndex(int index, const BlockT& block) const;
// contains offset for each differential block
OffsetContainerT block_offsets;
// blocks of differential encoded offsets, should be aligned
BlockContainerT diff_blocks;
unsigned sum_lengths;
};
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index, const BlockT& block) const
{
// this loop looks inefficent, but a modern compiler
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
unsigned sum = 0;
for (int i = 0; i <= index; ++i)
{
sum += block[i];
}
return sum;
}
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
{
// write number of block
const unsigned number_of_blocks = table.diff_blocks.size();
out.write((char *) &number_of_blocks, sizeof(unsigned));
// write total length
out.write((char *) &table.sum_lengths, sizeof(unsigned));
// write block offsets
out.write((char *) table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
// write blocks
out.write((char *) table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
return out;
}
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
{
// read number of block
unsigned number_of_blocks;
in.read((char *) &number_of_blocks, sizeof(unsigned));
// read total length
in.read((char *) &table.sum_lengths, sizeof(unsigned));
table.block_offsets.resize(number_of_blocks);
table.diff_blocks.resize(number_of_blocks);
// read block offsets
in.read((char *) table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
// read blocks
in.read((char *) table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
return in;
}
#endif //RANGE_TABLE_H_
+26 -17
View File
@@ -29,32 +29,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define RAW_ROUTE_DATA_H
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/TravelMode.h"
#include "../DataStructures/TurnInstructions.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <limits>
#include <vector>
struct PathData
{
PathData()
: node(std::numeric_limits<unsigned>::max()), name_id(std::numeric_limits<unsigned>::max()),
segment_duration(std::numeric_limits<unsigned>::max()),
turn_instruction(TurnInstruction::NoTurn)
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
segment_duration(INVALID_EDGE_WEIGHT),
turn_instruction(TurnInstruction::NoTurn),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, unsigned segment_duration)
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction)
PathData(NodeID node,
unsigned name_id,
TurnInstruction turn_instruction,
EdgeWeight segment_duration,
TravelMode travel_mode)
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction),
travel_mode(travel_mode)
{
}
NodeID node;
unsigned name_id;
unsigned segment_duration;
EdgeWeight segment_duration;
TurnInstruction turn_instruction;
TravelMode travel_mode : 4;
};
struct RawRouteData
@@ -63,20 +69,23 @@ struct RawRouteData
std::vector<PathData> unpacked_alternative;
std::vector<PhantomNodes> segment_end_coordinates;
std::vector<FixedPointCoordinate> raw_via_node_coordinates;
std::vector<bool> source_traversed_in_reverse;
std::vector<bool> target_traversed_in_reverse;
std::vector<bool> alt_source_traversed_in_reverse;
std::vector<bool> alt_target_traversed_in_reverse;
unsigned check_sum;
int shortest_path_length;
int alternative_path_length;
bool source_traversed_in_reverse;
bool target_traversed_in_reverse;
bool alt_source_traversed_in_reverse;
bool alt_target_traversed_in_reverse;
bool is_via_leg(const std::size_t leg) const
{
return (leg != unpacked_path_segments.size() - 1);
}
RawRouteData()
: check_sum(std::numeric_limits<unsigned>::max()),
shortest_path_length(std::numeric_limits<int>::max()),
alternative_path_length(std::numeric_limits<int>::max()),
source_traversed_in_reverse(false), target_traversed_in_reverse(false),
alt_source_traversed_in_reverse(false), alt_target_traversed_in_reverse(false)
: check_sum(SPECIAL_NODEID),
shortest_path_length(INVALID_EDGE_WEIGHT),
alternative_path_length(INVALID_EDGE_WEIGHT)
{
}
};
+2 -2
View File
@@ -101,7 +101,7 @@ struct InputRestrictionContainer
struct CmpRestrictionContainerByFrom
{
typedef InputRestrictionContainer value_type;
using value_type = InputRestrictionContainer;
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
const
{
@@ -113,7 +113,7 @@ struct CmpRestrictionContainerByFrom
struct CmpRestrictionContainerByTo
{
typedef InputRestrictionContainer value_type;
using value_type = InputRestrictionContainer;
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
const
{
+122 -71
View File
@@ -1,16 +1,51 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "RestrictionMap.h"
#include "NodeBasedGraph.h"
bool RestrictionMap::IsViaNode(const NodeID node) const
{
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
}
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &input_restrictions_list)
const std::vector<TurnRestriction> &restriction_list)
: m_count(0), m_graph(graph)
{
// decompose restirction consisting of a start, via and end note into a start-edge
// and all end-nodes
for (auto &restriction : input_restrictions_list)
// decompose restriction consisting of a start, via and end node into a
// a pair of starting edge and a list of all end nodes
for (auto &restriction : restriction_list)
{
std::pair<NodeID, NodeID> restriction_source =
std::make_pair(restriction.fromNode, restriction.viaNode);
m_restriction_start_nodes.insert(restriction.fromNode);
m_no_turn_via_node_set.insert(restriction.viaNode);
RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
unsigned index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
@@ -23,7 +58,7 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->second)
if (m_restriction_bucket_list.at(index).begin()->is_only)
{
continue;
}
@@ -36,133 +71,149 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
}
++m_count;
m_restriction_bucket_list.at(index)
.push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
.emplace_back(restriction.toNode, restriction.flags.isOnly);
}
}
/**
* Replace end v with w in each turn restriction containing u as via node
*
* Note: We need access to node based graph.
*/
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
// Replace end v with w in each turn restriction containing u as via node
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
const NodeID node_v,
const NodeID node_w)
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
// find all possible start edges
// it is more efficent to get a (small) list of potential start edges
// than iterating over all buckets
std::vector<NodeID> predecessors;
for (EdgeID current_edge_id = m_graph->BeginEdges(u); current_edge_id < m_graph->EndEdges(u);
++current_edge_id)
if (!IsViaNode(node_u))
{
return;
}
// find all potential start edges. It is more efficent to get a (small) list
// of potential start edges than iterating over all buckets
std::vector<NodeID> predecessors;
for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(node_u))
{
const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
const NodeID target = m_graph->GetTarget(current_edge_id);
if (edge_data.backward && (v != target))
if (node_v != target)
{
predecessors.push_back(target);
}
}
for (const NodeID x : predecessors)
for (const NodeID node_x : predecessors)
{
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x, u);
auto restriction_iterator = m_restriction_map.find(restr_start);
const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
if (restriction_iterator == m_restriction_map.end())
{
continue;
}
const unsigned index = restriction_iterator->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (RestrictionTarget &restriction_target : bucket)
{
if (v == restriction_target.first)
if (node_v == restriction_target.target_node)
{
restriction_target.first = w;
restriction_target.target_node = node_w;
}
}
}
}
/**
* Replaces the start edge (v, w) with (u, w), only start node changes.
*/
void RestrictionMap::FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
// Replaces start edge (v, w) with (u, w). Only start node changes.
void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
const NodeID node_v,
const NodeID node_w)
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
const std::pair<NodeID, NodeID> old_start = std::make_pair(v, w);
if (!IsSourceNode(node_v))
{
return;
}
auto restriction_iterator = m_restriction_map.find(old_start);
const auto restriction_iterator = m_restriction_map.find({node_v, node_w});
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
// remove old restriction start (v,w)
m_restriction_map.erase(restriction_iterator);
// insert new restriction start (u,w) (point to index)
const std::pair<NodeID, NodeID> new_start = std::make_pair(u, w);
m_restriction_map.insert(std::make_pair(new_start, index));
m_restriction_start_nodes.emplace(node_u);
// insert new restriction start (u,w) (pointing to index)
RestrictionSource new_source = {node_u, node_w};
m_restriction_map.emplace(new_source, index);
}
}
/*
* Check if the edge (u, v) is contained in any turn restriction.
* If so returns id of first target node.
*/
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
// Check if edge (u, v) is the start of any turn restriction.
// If so returns id of first target node.
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
auto restriction_iter = m_restriction_map.find(restriction_source);
if (!IsSourceNode(node_u))
{
return SPECIAL_NODEID;
}
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionSource &restriction_target : bucket)
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if (restriction_target.second)
if (restriction_target.is_only)
{
return restriction_target.first;
return restriction_target.target_node;
}
}
}
return std::numeric_limits<unsigned>::max();
return SPECIAL_NODEID;
}
/**
* Checks if the turn described by start u, via v and targed w is covert by any turn restriction.
*/
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
// Checks if turn <u,v,w> is actually a turn restriction.
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
const NodeID node_v,
const NodeID node_w) const
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
auto restriction_iter = m_restriction_map.find(restriction_source);
if (!IsSourceNode(node_u))
{
return false;
}
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
auto &bucket = m_restriction_bucket_list.at(index);
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if ((w == restriction_target.first) && // target found
(!restriction_target.second) // and not an only_-restr.
if ((node_w == restriction_target.target_node) && // target found
(!restriction_target.is_only) // and not an only_-restr.
)
{
return true;
}
}
}
return false;
}
// check of node is the start of any restriction
bool RestrictionMap::IsSourceNode(const NodeID node) const
{
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
{
return false;
}
return true;
}
+72 -17
View File
@@ -25,22 +25,73 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RESTRICTION_MAP_H__
#define __RESTRICTION_MAP_H__
#ifndef RESTRICTION_MAP_H_
#define RESTRICTION_MAP_H_
#include <memory>
#include "../typedefs.h"
#include "DynamicGraph.h"
#include "Restriction.h"
#include "NodeBasedGraph.h"
#include "../Util/StdHashExtensions.h"
#include "../typedefs.h"
#include <boost/unordered_map.hpp>
#include <unordered_map>
#include <unordered_set>
/*!
* Makee it efficent to look up if an edge is the start + via node of a TurnRestriction.
* Is needed by EdgeBasedGraphFactory.
*/
struct RestrictionSource
{
NodeID start_node;
NodeID via_node;
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via)
{
}
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
{
return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
}
};
struct RestrictionTarget
{
NodeID target_node;
bool is_only;
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only)
{
}
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
{
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
}
};
namespace std
{
template <> struct hash<RestrictionSource>
{
size_t operator()(const RestrictionSource &r_source) const
{
return hash_val(r_source.start_node, r_source.via_node);
}
};
template <> struct hash<RestrictionTarget>
{
size_t operator()(const RestrictionTarget &r_target) const
{
return hash_val(r_target.target_node, r_target.is_only);
}
};
}
/**
\brief Efficent look up if an edge is the start + via node of a TurnRestriction
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
*/
class RestrictionMap
{
public:
@@ -51,21 +102,25 @@ class RestrictionMap
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
unsigned size() { return m_count; }
bool IsViaNode(const NodeID node) const;
std::size_t size()
{
return m_count;
}
private:
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
bool IsSourceNode(const NodeID node) const;
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
using EdgeData = NodeBasedDynamicGraph::EdgeData;
unsigned m_count;
std::size_t m_count;
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
//! index -> list of (target, isOnly)
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
//! maps (start, via) -> bucket index
boost::unordered_map<RestrictionSource, unsigned> m_restriction_map;
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
std::unordered_set<NodeID> m_restriction_start_nodes;
std::unordered_set<NodeID> m_no_turn_via_node_set;
};
#endif
#endif //RESTRICTION_MAP_H_
+42 -7
View File
@@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
RouteParameters::RouteParameters()
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
compression(true), deprecatedAPI(false), check_sum(-1)
compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1)
{
}
@@ -45,8 +45,36 @@ void RouteParameters::setZoomLevel(const short level)
}
}
void RouteParameters::setNumberOfResults(const short number)
{
if (number > 0 && number <= 100)
{
num_results = number;
}
}
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
void RouteParameters::setUTurn(const bool flag)
{
uturns.resize(coordinates.size(), uturn_default);
if (!uturns.empty())
{
uturns.back() = flag;
}
}
void RouteParameters::setAllUTurns(const bool flag)
{
// if the flag flips the default, then we erase everything.
if (flag)
{
uturn_default = flag;
uturns.clear();
uturns.resize(coordinates.size(), uturn_default);
}
}
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
@@ -57,7 +85,10 @@ void RouteParameters::setService(const std::string &service_string) { service =
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
void RouteParameters::setJSONpParameter(const std::string &parameter) { jsonp_parameter = parameter; }
void RouteParameters::setJSONpParameter(const std::string &parameter)
{
jsonp_parameter = parameter;
}
void RouteParameters::addHint(const std::string &hint)
{
@@ -68,15 +99,19 @@ void RouteParameters::addHint(const std::string &hint)
}
}
void RouteParameters::setLanguage(const std::string &language_string) { language = language_string; }
void RouteParameters::setLanguage(const std::string &language_string)
{
language = language_string;
}
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
void RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
void
RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
{
int lat = COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates);
int lon = COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates);
coordinates.emplace_back(lat, lon);
coordinates.emplace_back(
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
}
+7 -1
View File
@@ -30,8 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SearchEngineData.h"
#include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/ManyToManyRouting.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h"
#include <type_traits>
template <class DataFacadeT> class SearchEngine
{
private:
@@ -41,11 +44,14 @@ template <class DataFacadeT> class SearchEngine
public:
ShortestPathRouting<DataFacadeT> shortest_path;
AlternativeRouting<DataFacadeT> alternative_path;
ManyToManyRouting<DataFacadeT> distance_table;
explicit SearchEngine(DataFacadeT *facade)
: facade(facade), shortest_path(facade, engine_working_data),
alternative_path(facade, engine_working_data)
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
{
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
}
~SearchEngine() {}
+2
View File
@@ -27,6 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SearchEngineData.h"
#include "BinaryHeap.h"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
{
if (forwardHeap.get())
+4 -9
View File
@@ -28,15 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SEARCH_ENGINE_DATA_H
#define SEARCH_ENGINE_DATA_H
#include "BinaryHeap.h"
#include "QueryEdge.h"
#include "StaticGraph.h"
#include <boost/thread/tss.hpp>
#include "../typedefs.h"
#include <boost/thread.hpp>
#include <vector>
#include "BinaryHeap.h"
struct HeapData
{
@@ -46,8 +41,8 @@ struct HeapData
struct SearchEngineData
{
typedef BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>> QueryHeap;
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
static SearchEngineHeapPtr forwardHeap;
static SearchEngineHeapPtr backwardHeap;
+18 -10
View File
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TurnInstructions.h"
#include "../DataStructures/TravelMode.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
@@ -39,30 +40,37 @@ struct SegmentInformation
{
FixedPointCoordinate location;
NodeID name_id;
unsigned duration;
double length;
EdgeWeight duration;
float length;
short bearing; // more than enough [0..3600] fits into 12 bits
TurnInstruction turn_instruction;
TravelMode travel_mode;
bool necessary;
bool is_via_location;
explicit SegmentInformation(const FixedPointCoordinate &location,
const NodeID name_id,
const unsigned duration,
const double length,
const EdgeWeight duration,
const float length,
const TurnInstruction turn_instruction,
const bool necessary)
const bool necessary,
const bool is_via_location,
const TravelMode travel_mode)
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
turn_instruction(turn_instruction), necessary(necessary)
turn_instruction(turn_instruction), travel_mode(travel_mode), necessary(necessary),
is_via_location(is_via_location)
{
}
explicit SegmentInformation(const FixedPointCoordinate &location,
const NodeID name_id,
const unsigned duration,
const double length,
const TurnInstruction turn_instruction)
const EdgeWeight duration,
const float length,
const TurnInstruction turn_instruction,
const TravelMode travel_mode)
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn)
turn_instruction(turn_instruction), travel_mode(travel_mode),
necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
{
}
};
+140 -2
View File
@@ -29,12 +29,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SHARED_MEMORY_FACTORY_H
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/mapped_region.hpp>
#ifndef WIN32
#include <boost/interprocess/xsi_shared_memory.hpp>
#else
#include <boost/interprocess/shared_memory_object.hpp>
#endif
#ifdef __linux__
#include <sys/ipc.h>
@@ -57,6 +61,7 @@ struct OSRMLockFile
}
};
#ifndef WIN32
class SharedMemory
{
@@ -189,6 +194,139 @@ class SharedMemory
boost::interprocess::mapped_region region;
shm_remove remover;
};
#else
// Windows - specific code
class SharedMemory
{
SharedMemory(const SharedMemory&) = delete;
// Remove shared memory on destruction
class shm_remove
{
private:
shm_remove(const shm_remove&) = delete;
char *m_shmid;
bool m_initialized;
public:
void SetID(char *shmid)
{
m_shmid = shmid;
m_initialized = true;
}
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
~shm_remove()
{
if (m_initialized)
{
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
{
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
}
}
}
};
public:
void *Ptr() const { return region.get_address(); }
SharedMemory(const boost::filesystem::path &lock_file,
const int id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true)
{
sprintf(key, "%s.%d", "osrm.lock", id);
if (0 == size)
{ // read_only
shm = boost::interprocess::shared_memory_object(
boost::interprocess::open_only,
key,
read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
region = boost::interprocess::mapped_region(
shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
}
else
{ // writeable pointer
// remove previously allocated mem
if (remove_prev)
{
Remove(key);
}
shm = boost::interprocess::shared_memory_object(
boost::interprocess::open_or_create, key, boost::interprocess::read_write);
shm.truncate(size);
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
remover.SetID(key);
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
}
}
static bool RegionExists(const int id)
{
bool result = true;
try
{
char k[500];
build_key(id, k);
result = RegionExists(k);
}
catch (...) { result = false; }
return result;
}
static bool Remove(const int id)
{
char k[500];
build_key(id, k);
return Remove(k);
}
private:
static void build_key(int id, char *key)
{
sprintf(key, "%s.%d", "osrm.lock", id);
}
static bool RegionExists(const char *key)
{
bool result = true;
try
{
boost::interprocess::shared_memory_object shm(
boost::interprocess::open_only, key, boost::interprocess::read_write);
}
catch (...) { result = false; }
return result;
}
static bool Remove(char *key)
{
bool ret = false;
try
{
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
ret = boost::interprocess::shared_memory_object::remove(key);
}
catch (const boost::interprocess::interprocess_exception &e)
{
if (e.get_error_code() != boost::interprocess::not_found_error)
{
throw;
}
}
return ret;
}
char key[500];
boost::interprocess::shared_memory_object shm;
boost::interprocess::mapped_region region;
shm_remove remover;
};
#endif
template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
{
@@ -228,6 +366,6 @@ template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
};
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
using SharedMemoryFactory = SharedMemoryFactory_tmpl<>;
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
+6 -8
View File
@@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
#define SHARED_MEMORY_VECTOR_WRAPPER_H
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <algorithm>
@@ -78,7 +76,7 @@ template <typename DataT> class SharedMemoryWrapper
void swap(SharedMemoryWrapper<DataT> &other)
{
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
// BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
std::swap(m_size, other.m_size);
std::swap(m_ptr, other.m_ptr);
}
@@ -121,15 +119,15 @@ template <> class SharedMemoryWrapper<bool>
void swap(SharedMemoryWrapper<bool> &other)
{
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
// BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
std::swap(m_size, other.m_size);
std::swap(m_ptr, other.m_ptr);
}
bool at(const std::size_t index) const
{
const unsigned bucket = index / 32;
const unsigned offset = index % 32;
const std::size_t bucket = index / 32;
const unsigned offset = static_cast<unsigned>(index % 32);
return m_ptr[bucket] & (1 << offset);
}
@@ -148,9 +146,9 @@ template <> class SharedMemoryWrapper<bool>
template <typename DataT, bool UseSharedMemory> struct ShM
{
typedef typename std::conditional<UseSharedMemory,
using vector = typename std::conditional<UseSharedMemory,
SharedMemoryWrapper<DataT>,
std::vector<DataT>>::type vector;
std::vector<DataT>>::type;
};
#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
+40 -55
View File
@@ -28,27 +28,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STATIC_GRAPH_H
#define STATIC_GRAPH_H
#include "../DataStructures/Percent.h"
#include "../DataStructures/SharedMemoryVectorWrapper.h"
#include "../Util/SimpleLogger.h"
#include "Percent.h"
#include "Range.h"
#include "SharedMemoryVectorWrapper.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <limits>
#include <utility>
#include <vector>
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
{
public:
typedef NodeID NodeIterator;
typedef NodeID EdgeIterator;
typedef EdgeDataT EdgeData;
using NodeIterator = NodeID;
using EdgeIterator = NodeID;
using EdgeData = EdgeDataT;
using EdgeRange = osrm::range<EdgeIterator>;
class InputEdge
{
public:
EdgeDataT data;
NodeIterator source;
NodeIterator target;
EdgeDataT data;
template<typename... Ts>
InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
bool operator<(const InputEdge &right) const
{
if (source != right.source)
@@ -62,7 +72,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
struct NodeArrayEntry
{
// index of the first edge
EdgeIterator firstEdge;
EdgeIterator first_edge;
};
struct EdgeArrayEntry
@@ -71,32 +81,39 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
EdgeDataT data;
};
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
{
return osrm::irange(BeginEdges(node), EndEdges(node));
}
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
{
std::sort(graph.begin(), graph.end());
tbb::parallel_sort(graph.begin(), graph.end());
number_of_nodes = nodes;
number_of_edges = (EdgeIterator)graph.size();
node_array.resize(number_of_nodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for (NodeIterator node = 0; node <= number_of_nodes; ++node)
for (const auto node : osrm::irange(0u, number_of_nodes+1))
{
EdgeIterator lastEdge = edge;
EdgeIterator last_edge = edge;
while (edge < number_of_edges && graph[edge].source == node)
{
++edge;
node_array[node].firstEdge = position; //=edge
position += edge - lastEdge; // remove
}
node_array[node].first_edge = position; //=edge
position += edge - last_edge; // remove
}
edge_array.resize(position); //(edge)
edge = 0;
for (NodeIterator node = 0; node < number_of_nodes; ++node)
for (const auto node : osrm::irange(0u, number_of_nodes))
{
EdgeIterator e = node_array[node + 1].firstEdge;
for (EdgeIterator i = node_array[node].firstEdge; i != e; ++i)
EdgeIterator e = node_array[node + 1].first_edge;
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
{
edge_array[i].target = graph[edge].target;
edge_array[i].data = graph[edge].data;
assert(edge_array[i].data.distance > 0);
BOOST_ASSERT(edge_array[i].data.distance > 0);
edge++;
}
}
@@ -105,50 +122,18 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
{
number_of_nodes = nodes.size() - 1;
number_of_edges = edges.size();
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
node_array.swap(nodes);
edge_array.swap(edges);
#ifndef NDEBUG
Percent p(GetNumberOfNodes());
for (unsigned u = 0; u < GetNumberOfNodes(); ++u)
{
for (unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid)
{
unsigned v = GetTarget(eid);
EdgeData &data = GetEdgeData(eid);
if (data.shortcut)
{
const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
if (SPECIAL_EDGEID == first_edge_id)
{
SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
<< u << "," << data.id << "," << v
<< "), eid: " << eid;
BOOST_ASSERT(false);
}
const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
if (SPECIAL_EDGEID == second_edge_id)
{
SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
<< u << "," << data.id << "," << v
<< "), eid: " << eid;
BOOST_ASSERT(false);
}
}
}
p.printIncrement();
}
#endif
}
unsigned GetNumberOfNodes() const { return number_of_nodes; }
unsigned GetNumberOfEdges() const { return number_of_edges; }
unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
unsigned GetOutDegree(const NodeIterator n) const { return EndEdges(n) - BeginEdges(n); }
inline NodeIterator GetTarget(const EdgeIterator e) const
{
@@ -161,12 +146,12 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
EdgeIterator BeginEdges(const NodeIterator n) const
{
return EdgeIterator(node_array.at(n).firstEdge);
return EdgeIterator(node_array.at(n).first_edge);
}
EdgeIterator EndEdges(const NodeIterator n) const
{
return EdgeIterator(node_array.at(n + 1).firstEdge);
return EdgeIterator(node_array.at(n + 1).first_edge);
}
// searches for a specific edge
@@ -174,7 +159,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
{
EdgeIterator smallest_edge = SPECIAL_EDGEID;
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
for (EdgeIterator edge = BeginEdges(from); edge < EndEdges(from); edge++)
for (auto edge : GetAdjacentEdgeRange(from))
{
const NodeID target = GetTarget(edge);
const EdgeWeight weight = GetEdgeData(edge).distance;
+1 -1
View File
@@ -211,7 +211,7 @@ class StaticKDTree
}
private:
typedef unsigned Iterator;
using Iterator = unsigned;
struct Tree
{
Iterator left;
File diff suppressed because it is too large Load Diff
@@ -25,17 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OPENMP_WRAPPER_H
#define OPENMP_WRAPPER_H
#ifndef TRAVEL_MODE_H
#define TRAVEL_MODE_H
#ifdef _OPENMP
extern "C" {
#include <omp.h>
}
#else
inline int omp_get_num_procs() { return 1; }
inline int omp_get_max_threads() { return 1; }
inline int omp_get_thread_num() { return 0; }
inline void omp_set_num_threads(int i) {}
#endif // _OPENMP
#endif // OPENMP_WRAPPER_H
using TravelMode = unsigned char;
static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
static const TravelMode TRAVEL_MODE_DEFAULT = 1;
#endif /* TRAVEL_MODE_H */
+3 -1
View File
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
enum class TurnInstruction : unsigned char
{
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaPoint, HeadOn, EnterRoundAbout,
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaLocation, HeadOn, EnterRoundAbout,
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
InverseAccessRestrictionFlag = 127,
@@ -80,7 +80,9 @@ struct TurnInstructionsClass
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
{
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
{
return false;
}
return true;
}
};
+2 -2
View File
@@ -70,7 +70,7 @@ class XORFastHash
inline unsigned short operator()(const unsigned originalValue) const
{
unsigned short lsb = ((originalValue) & 0xffff);
unsigned short lsb = ((originalValue)&0xffff);
unsigned short msb = (((originalValue) >> 16) & 0xffff);
return table1[lsb] ^ table2[msb];
}
@@ -104,7 +104,7 @@ class XORMiniHash
}
unsigned char operator()(const unsigned originalValue) const
{
unsigned char byte1 = ((originalValue) & 0xff);
unsigned char byte1 = ((originalValue)&0xff);
unsigned char byte2 = ((originalValue >> 8) & 0xff);
unsigned char byte3 = ((originalValue >> 16) & 0xff);
unsigned char byte4 = ((originalValue >> 24) & 0xff);
+4 -4
View File
@@ -49,14 +49,14 @@ template <typename NodeID, typename Key> class XORFastHashStorage
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
inline operator Key() const { return key; }
operator Key() const { return key; }
inline void operator=(const Key &key_to_insert) { key = key_to_insert; }
void operator=(const Key &key_to_insert) { key = key_to_insert; }
};
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
inline HashCell &operator[](const NodeID node)
HashCell &operator[](const NodeID node)
{
unsigned short position = fast_hasher(node);
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
@@ -69,7 +69,7 @@ template <typename NodeID, typename Key> class XORFastHashStorage
return positions[position];
}
inline void Clear()
void Clear()
{
++current_timestamp;
if (std::numeric_limits<unsigned>::max() == current_timestamp)
+1 -4
View File
@@ -54,10 +54,7 @@ template <class DataFacadeT> class BaseDescriptor
BaseDescriptor() {}
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() {}
virtual void Run(const RawRouteData &raw_route,
const PhantomNodes &phantom_nodes,
DataFacadeT *facade,
http::Reply &reply) = 0;
virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
virtual void SetConfig(const DescriptorConfig &config) = 0;
};
+67 -72
View File
@@ -27,105 +27,100 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() : entireLength(0) {}
#include <osrm/Coordinate.h>
DescriptionFactory::~DescriptionFactory() {}
#include "../typedefs.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
inline double DescriptionFactory::DegreeToRadian(const double degree) const
{
return degree * (M_PI / 180.);
}
DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
inline double DescriptionFactory::RadianToDegree(const double radian) const
{
return radian * (180. / M_PI);
}
std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
double DescriptionFactory::GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B)
const
{
double delta_long = DegreeToRadian(B.lon / COORDINATE_PRECISION - A.lon / COORDINATE_PRECISION);
const double lat1 = DegreeToRadian(A.lat / COORDINATE_PRECISION);
const double lat2 = DegreeToRadian(B.lat / COORDINATE_PRECISION);
const double y = sin(delta_long) * cos(lat2);
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
double result = RadianToDegree(atan2(y, x));
while (result < 0.)
{
result += 360.;
}
while (result >= 360.)
{
result -= 360.;
}
return result;
}
void DescriptionFactory::SetStartSegment(const PhantomNode &source)
void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
{
start_phantom = source;
AppendSegment(source.location, PathData(0, source.name_id, TurnInstruction::HeadOn, source.forward_weight));
const EdgeWeight segment_duration =
(traversed_in_reverse ? source.reverse_weight : source.forward_weight);
const TravelMode travel_mode =
(traversed_in_reverse ? source.backward_travel_mode : source.forward_travel_mode);
AppendSegment(
source.location,
PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration, travel_mode));
BOOST_ASSERT(path_description.back().duration == segment_duration);
}
void DescriptionFactory::SetEndSegment(const PhantomNode &target)
void DescriptionFactory::SetEndSegment(const PhantomNode &target,
const bool traversed_in_reverse,
const bool is_via_location)
{
target_phantom = target;
path_description.emplace_back(
target.location, target.name_id, 0, target.reverse_weight, TurnInstruction::NoTurn, true);
const EdgeWeight segment_duration =
(traversed_in_reverse ? target.reverse_weight : target.forward_weight);
const TravelMode travel_mode =
(traversed_in_reverse ? target.backward_travel_mode : target.forward_travel_mode);
path_description.emplace_back(target.location,
target.name_id,
segment_duration,
0.f,
is_via_location ? TurnInstruction::ReachViaLocation
: TurnInstruction::NoTurn,
true,
true,
travel_mode);
BOOST_ASSERT(path_description.back().duration == segment_duration);
}
void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
const PathData &path_point)
{
if ((1 == path_description.size()) && (path_description.back().location == coordinate))
// if the start location is on top of a node, the first movement might be zero-length,
// in which case we dont' add a new description, but instead update the existing one
if ((1 == path_description.size()) && (path_description.front().location == coordinate))
{
path_description.back().name_id = path_point.name_id;
if (path_point.segment_duration > 0)
{
path_description.front().name_id = path_point.name_id;
path_description.front().travel_mode = path_point.travel_mode;
}
return;
}
else
// make sure mode changes are announced, even when there otherwise is no turn
const TurnInstruction turn = [&]() -> TurnInstruction
{
path_description.emplace_back(coordinate,
path_point.name_id,
path_point.segment_duration,
0,
path_point.turn_instruction);
}
if (TurnInstruction::NoTurn == path_point.turn_instruction &&
path_description.front().travel_mode != path_point.travel_mode &&
path_point.segment_duration > 0)
{
return TurnInstruction::GoStraight;
}
return path_point.turn_instruction;
}();
path_description.emplace_back(coordinate,
path_point.name_id,
path_point.segment_duration,
0.f,
turn,
path_point.travel_mode);
}
void DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded,
std::vector<std::string> &output)
JSON::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
{
std::string temp;
if (return_encoded)
{
polyline_compressor.printEncodedString(path_description, temp);
return polyline_compressor.printEncodedString(path_description);
}
else
{
polyline_compressor.printUnencodedString(path_description, temp);
}
output.emplace_back(temp);
}
void DescriptionFactory::AppendEncodedPolylineString(std::vector<std::string> &output) const
{
std::string temp;
polyline_compressor.printEncodedString(path_description, temp);
output.emplace_back(temp);
}
void DescriptionFactory::AppendUnencodedPolylineString(std::vector<std::string> &output) const
{
std::string temp;
polyline_compressor.printUnencodedString(path_description, temp);
output.emplace_back(temp);
return polyline_compressor.printUnencodedString(path_description);
}
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
{
summary.startName = start_phantom.name_id;
summary.destName = target_phantom.name_id;
summary.source_name_id = start_phantom.name_id;
summary.target_name_id = target_phantom.name_id;
summary.BuildDurationAndLengthStrings(distance, time);
}
+34 -26
View File
@@ -31,10 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
@@ -42,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits>
#include <vector>
struct PathData;
/* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */
@@ -54,21 +53,22 @@ class DescriptionFactory
double DegreeToRadian(const double degree) const;
double RadianToDegree(const double degree) const;
std::vector<unsigned> via_indices;
public:
struct RouteSummary
{
std::string lengthString;
std::string durationString;
unsigned startName;
unsigned destName;
RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
unsigned distance;
EdgeWeight duration;
unsigned source_name_id;
unsigned target_name_id;
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
void BuildDurationAndLengthStrings(const double distance, const unsigned time)
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
{
// compute distance/duration for route summary
intToString(round(distance), lengthString);
int travel_time = round(time / 10.);
intToString(std::max(travel_time, 1), durationString);
distance = static_cast<unsigned>(round(raw_distance));
duration = static_cast<unsigned>(round(raw_duration / 10.));
}
} summary;
@@ -77,15 +77,14 @@ class DescriptionFactory
// I know, declaring this public is considered bad. I'm lazy
std::vector<SegmentInformation> path_description;
DescriptionFactory();
virtual ~DescriptionFactory();
double GetBearing(const FixedPointCoordinate &C, const FixedPointCoordinate &B) const;
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode &start_phantom);
void SetEndSegment(const PhantomNode &start_phantom);
void AppendEncodedPolylineString(const bool return_encoded, std::vector<std::string> &output);
void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
void SetEndSegment(const PhantomNode &start_phantom,
const bool traversed_in_reverse,
const bool is_via_location = false);
JSON::Value AppendGeometryString(const bool return_encoded);
std::vector<unsigned> const &GetViaIndices() const;
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
{
@@ -147,7 +146,7 @@ class DescriptionFactory
// string0 = string1;
// }
double segment_length = 0.;
float segment_length = 0.;
unsigned segment_duration = 0;
unsigned segment_start_index = 0;
@@ -179,14 +178,14 @@ class DescriptionFactory
target_phantom.name_id = (path_description.end() - 2)->name_id;
}
}
if (std::numeric_limits<double>::epsilon() > path_description[0].length)
if (std::numeric_limits<double>::epsilon() > path_description.front().length)
{
if (path_description.size() > 2)
{
path_description.erase(path_description.begin());
path_description[0].turn_instruction = TurnInstruction::HeadOn;
path_description[0].necessary = true;
start_phantom.name_id = path_description[0].name_id;
path_description.front().turn_instruction = TurnInstruction::HeadOn;
path_description.front().necessary = true;
start_phantom.name_id = path_description.front().name_id;
}
}
@@ -194,15 +193,24 @@ class DescriptionFactory
polyline_generalizer.Run(path_description, zoomLevel);
// fix what needs to be fixed else
unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
{
if (path_description[i].necessary)
{
double angle =
GetBearing(path_description[i].location, path_description[i + 1].location);
path_description[i].bearing = angle * 10;
++necessary_pieces;
if (path_description[i].is_via_location)
{ // mark the end of a leg
via_indices.push_back(necessary_pieces);
}
const double angle =
path_description[i + 1].location.GetBearing(path_description[i].location);
path_description[i].bearing = static_cast<unsigned>(angle * 10);
}
}
via_indices.push_back(necessary_pieces + 1);
BOOST_ASSERT(via_indices.size() >= 2);
// BOOST_ASSERT(0 != necessary_pieces || path_description.empty());
return;
}
};
+45 -41
View File
@@ -30,68 +30,72 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseDescriptor.h"
template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
{
private:
DescriptorConfig config;
FixedPointCoordinate current;
DataFacadeT *facade;
std::string tmp;
void AddRoutePoint(const FixedPointCoordinate &coordinate, std::vector<char> &output)
{
const std::string route_point_head = "<rtept lat=\"";
const std::string route_point_middle = " lon=\"";
const std::string route_point_tail = "\"></rtept>";
std::string tmp;
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
output.insert(output.end(), route_point_head.begin(), route_point_head.end());
output.insert(output.end(), tmp.begin(), tmp.end());
output.push_back('\"');
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
output.insert(output.end(), tmp.begin(), tmp.end());
output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
}
public:
void SetConfig(const DescriptorConfig &c) { config = c; }
explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
void SetConfig(const DescriptorConfig &c) final { config = c; }
// TODO: reorder parameters
void Run(const RawRouteData &raw_route,
const PhantomNodes &phantom_node_list,
DataFacadeT *facade,
http::Reply &reply)
void Run(const RawRouteData &raw_route, http::Reply &reply) final
{
reply.content.emplace_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content.emplace_back("<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
"\">");
reply.content.emplace_back("<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>");
reply.content.emplace_back("<rte>");
bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
(!raw_route.unpacked_path_segments.front().empty());
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
"\">"
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>"
"<rte>");
reply.content.insert(reply.content.end(), header.begin(), header.end());
const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
(!raw_route.unpacked_path_segments.front().empty());
if (found_route)
{
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lat, tmp);
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lon, tmp);
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
reply.content);
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
{
for (const PathData &path_data : path_data_vector)
{
FixedPointCoordinate current_coordinate =
const FixedPointCoordinate current_coordinate =
facade->GetCoordinateOfNode(path_data.node);
FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lat,
tmp);
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lon,
tmp);
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
AddRoutePoint(current_coordinate, reply.content);
}
}
// Add the via point or the end coordinate
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lat, tmp);
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lon, tmp);
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
reply.content);
}
reply.content.emplace_back("</rte></gpx>");
std::string footer("</rte></gpx>");
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
}
};
#endif // GPX_DESCRIPTOR_H
+391 -524
View File
@@ -1,524 +1,391 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/Azimuth.h"
#include "../Util/StringUtil.h"
#include <algorithm>
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
{
private:
// TODO: initalize in c'tor
DataFacadeT *facade;
DescriptorConfig config;
DescriptionFactory description_factory;
DescriptionFactory alternate_descriptionFactory;
FixedPointCoordinate current;
unsigned entered_restricted_area_count;
struct RoundAbout
{
RoundAbout() : start_index(INT_MAX), name_id(INT_MAX), leave_at_exit(INT_MAX) {}
int start_index;
int name_id;
int leave_at_exit;
} round_about;
struct Segment
{
Segment() : name_id(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
int name_id;
int length;
int position;
};
std::vector<Segment> shortest_path_segments, alternative_path_segments;
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
struct RouteNames
{
std::string shortest_path_name_1;
std::string shortest_path_name_2;
std::string alternative_path_name_1;
std::string alternative_path_name_2;
};
public:
JSONDescriptor() : facade(nullptr), entered_restricted_area_count(0)
{
shortest_leg_end_indices.emplace_back(0);
alternative_leg_end_indices.emplace_back(0);
}
void SetConfig(const DescriptorConfig &c) { config = c; }
unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
{
unsigned added_element_count = 0;
// Get all the coordinates for the computed route
FixedPointCoordinate current_coordinate;
for (const PathData &path_data : route_leg)
{
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current_coordinate, path_data);
++added_element_count;
}
++added_element_count;
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
return added_element_count;
}
void Run(const RawRouteData &raw_route,
const PhantomNodes &phantom_nodes,
// TODO: move facade initalization to c'tor
DataFacadeT *f,
http::Reply &reply)
{
facade = f;
reply.content.emplace_back("{\"status\":");
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
{
// We do not need to do much, if there is no route ;-)
reply.content.emplace_back(
"207,\"status_message\": \"Cannot find route between points\"}");
return;
}
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.shortest_path_length;
// check if first segment is non-zero
std::string road_name =
facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
raw_route.segment_end_coordinates.size());
description_factory.SetStartSegment(phantom_nodes.source_phantom);
reply.content.emplace_back("0,"
"\"status_message\": \"Found route between points\",");
// for each unpacked segment add the leg to the description
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
raw_route.segment_end_coordinates[i]);
BOOST_ASSERT(0 < added_segments);
shortest_leg_end_indices.emplace_back(added_segments + shortest_leg_end_indices.back());
}
description_factory.SetEndSegment(phantom_nodes.target_phantom);
description_factory.Run(facade, config.zoom_level);
reply.content.emplace_back("\"route_geometry\": ");
if (config.geometry)
{
description_factory.AppendEncodedPolylineString(config.encode_geometry, reply.content);
}
else
{
reply.content.emplace_back("[]");
}
reply.content.emplace_back(",\"route_instructions\": [");
if (config.instructions)
{
BuildTextualDescription(description_factory,
reply,
raw_route.shortest_path_length,
facade,
shortest_path_segments);
}
reply.content.emplace_back("],");
description_factory.BuildRouteSummary(description_factory.entireLength,
raw_route.shortest_path_length);
reply.content.emplace_back("\"route_summary\":");
reply.content.emplace_back("{");
reply.content.emplace_back("\"total_distance\":");
reply.content.emplace_back(description_factory.summary.lengthString);
reply.content.emplace_back(","
"\"total_time\":");
reply.content.emplace_back(description_factory.summary.durationString);
reply.content.emplace_back(","
"\"start_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.startName));
reply.content.emplace_back("\","
"\"end_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.emplace_back("\"");
reply.content.emplace_back("}");
reply.content.emplace_back(",");
// only one alternative route is computed at this time, so this is hardcoded
if (raw_route.alternative_path_length != INVALID_EDGE_WEIGHT)
{
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom);
// Get all the coordinates for the computed route
for (const PathData &path_data : raw_route.unpacked_alternative)
{
current = facade->GetCoordinateOfNode(path_data.node);
alternate_descriptionFactory.AppendSegment(current, path_data);
}
}
alternate_descriptionFactory.Run(facade, config.zoom_level);
// //give an array of alternative routes
reply.content.emplace_back("\"alternative_geometries\": [");
if (config.geometry && INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
// Generate the linestrings for each alternative
alternate_descriptionFactory.AppendEncodedPolylineString(config.encode_geometry,
reply.content);
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"alternative_instructions\":[");
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
reply.content.emplace_back("[");
// Generate instructions for each alternative
if (config.instructions)
{
BuildTextualDescription(alternate_descriptionFactory,
reply,
raw_route.alternative_path_length,
facade,
alternative_path_segments);
}
reply.content.emplace_back("]");
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"alternative_summaries\":[");
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
// Generate route summary (length, duration) for each alternative
alternate_descriptionFactory.BuildRouteSummary(
alternate_descriptionFactory.entireLength, raw_route.alternative_path_length);
reply.content.emplace_back("{");
reply.content.emplace_back("\"total_distance\":");
reply.content.emplace_back(alternate_descriptionFactory.summary.lengthString);
reply.content.emplace_back(","
"\"total_time\":");
reply.content.emplace_back(alternate_descriptionFactory.summary.durationString);
reply.content.emplace_back(","
"\"start_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.startName));
reply.content.emplace_back("\","
"\"end_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.emplace_back("\"");
reply.content.emplace_back("}");
}
reply.content.emplace_back("],");
// //Get Names for both routes
RouteNames routeNames;
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
reply.content.emplace_back("\"route_name\":[\"");
reply.content.emplace_back(routeNames.shortest_path_name_1);
reply.content.emplace_back("\",\"");
reply.content.emplace_back(routeNames.shortest_path_name_2);
reply.content.emplace_back("\"],"
"\"alternative_names\":[");
reply.content.emplace_back("[\"");
reply.content.emplace_back(routeNames.alternative_path_name_1);
reply.content.emplace_back("\",\"");
reply.content.emplace_back(routeNames.alternative_path_name_2);
reply.content.emplace_back("\"]");
reply.content.emplace_back("],");
// list all viapoints so that the client may display it
reply.content.emplace_back("\"via_points\":[");
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
std::string tmp;
FixedPointCoordinate::convertInternalReversedCoordinateToString(
raw_route.segment_end_coordinates.front().source_phantom.location, tmp);
reply.content.emplace_back("[");
reply.content.emplace_back(tmp);
reply.content.emplace_back("]");
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
{
tmp.clear();
FixedPointCoordinate::convertInternalReversedCoordinateToString(
nodes.target_phantom.location, tmp);
reply.content.emplace_back(",[");
reply.content.emplace_back(tmp);
reply.content.emplace_back("]");
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"via_indices\":[");
for (const unsigned index : shortest_leg_end_indices)
{
tmp.clear();
intToString(index, tmp);
reply.content.emplace_back(tmp);
if (index != shortest_leg_end_indices.back())
{
reply.content.emplace_back(",");
}
}
reply.content.emplace_back("],\"alternative_indices\":[");
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
reply.content.emplace_back("0,");
tmp.clear();
intToString(alternate_descriptionFactory.path_description.size(), tmp);
reply.content.emplace_back(tmp);
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"hint_data\": {");
reply.content.emplace_back("\"checksum\":");
intToString(raw_route.check_sum, tmp);
reply.content.emplace_back(tmp);
reply.content.emplace_back(", \"locations\": [");
std::string hint;
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
{
reply.content.emplace_back("\"");
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
reply.content.emplace_back(hint);
reply.content.emplace_back("\", ");
}
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
reply.content.emplace_back("\"");
reply.content.emplace_back(hint);
reply.content.emplace_back("\"]");
reply.content.emplace_back("}}");
}
// construct routes names
void GetRouteNames(std::vector<Segment> &shortest_path_segments,
std::vector<Segment> &alternative_path_segments,
const DataFacadeT *facade,
RouteNames &routeNames)
{
Segment shortest_segment_1, shortest_segment_2;
Segment alternativeSegment1, alternative_segment_2;
auto length_comperator = [](Segment a, Segment b)
{ return a.length < b.length; };
auto name_id_comperator = [](Segment a, Segment b)
{ return a.name_id < b.name_id; };
if (!shortest_path_segments.empty())
{
std::sort(
shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
shortest_segment_1 = shortest_path_segments[0];
if (!alternative_path_segments.empty())
{
std::sort(alternative_path_segments.begin(),
alternative_path_segments.end(),
length_comperator);
alternativeSegment1 = alternative_path_segments[0];
}
std::vector<Segment> shortestDifference(shortest_path_segments.size());
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
std::set_difference(shortest_path_segments.begin(),
shortest_path_segments.end(),
alternative_path_segments.begin(),
alternative_path_segments.end(),
shortestDifference.begin(),
length_comperator);
int size_of_difference = shortestDifference.size();
if (size_of_difference)
{
int i = 0;
while (i < size_of_difference &&
shortestDifference[i].name_id == shortest_path_segments[0].name_id)
{
++i;
}
if (i < size_of_difference)
{
shortest_segment_2 = shortestDifference[i];
}
}
std::set_difference(alternative_path_segments.begin(),
alternative_path_segments.end(),
shortest_path_segments.begin(),
shortest_path_segments.end(),
alternativeDifference.begin(),
name_id_comperator);
size_of_difference = alternativeDifference.size();
if (size_of_difference)
{
int i = 0;
while (i < size_of_difference &&
alternativeDifference[i].name_id == alternative_path_segments[0].name_id)
{
++i;
}
if (i < size_of_difference)
{
alternative_segment_2 = alternativeDifference[i];
}
}
if (shortest_segment_1.position > shortest_segment_2.position)
std::swap(shortest_segment_1, shortest_segment_2);
if (alternativeSegment1.position > alternative_segment_2.position)
std::swap(alternativeSegment1, alternative_segment_2);
routeNames.shortest_path_name_1 =
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
routeNames.shortest_path_name_2 =
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
routeNames.alternative_path_name_1 =
facade->GetEscapedNameForNameID(alternativeSegment1.name_id);
routeNames.alternative_path_name_2 =
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
}
}
// TODO: reorder parameters
inline void BuildTextualDescription(DescriptionFactory &description_factory,
http::Reply &reply,
const int route_length,
const DataFacadeT *facade,
std::vector<Segment> &route_segments_list)
{
// Segment information has following format:
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
// Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
unsigned necessary_segments_running_index = 0;
round_about.leave_at_exit = 0;
round_about.name_id = 0;
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
// Fetch data from Factory and generate a string from it.
for (const SegmentInformation &segment : description_factory.path_description)
{
TurnInstruction current_instruction = segment.turn_instruction;
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
{
if (TurnInstruction::EnterRoundAbout == current_instruction)
{
round_about.name_id = segment.name_id;
round_about.start_index = necessary_segments_running_index;
}
else
{
if (necessary_segments_running_index)
{
reply.content.emplace_back(",");
}
reply.content.emplace_back("[\"");
if (TurnInstruction::LeaveRoundAbout == current_instruction)
{
intToString(as_integer(TurnInstruction::EnterRoundAbout), temp_instruction);
reply.content.emplace_back(temp_instruction);
reply.content.emplace_back("-");
intToString(round_about.leave_at_exit + 1, temp_instruction);
reply.content.emplace_back(temp_instruction);
round_about.leave_at_exit = 0;
}
else
{
intToString(as_integer(current_instruction), temp_instruction);
reply.content.emplace_back(temp_instruction);
}
reply.content.emplace_back("\",\"");
reply.content.emplace_back(facade->GetEscapedNameForNameID(segment.name_id));
reply.content.emplace_back("\",");
intToString(segment.length, temp_dist);
reply.content.emplace_back(temp_dist);
reply.content.emplace_back(",");
intToString(necessary_segments_running_index, temp_length);
reply.content.emplace_back(temp_length);
reply.content.emplace_back(",");
intToString(round(segment.duration / 10.), temp_duration);
reply.content.emplace_back(temp_duration);
reply.content.emplace_back(",\"");
intToString(segment.length, temp_length);
reply.content.emplace_back(temp_length);
reply.content.emplace_back("m\",\"");
int bearing_value = round(segment.bearing / 10.);
reply.content.emplace_back(Azimuth::Get(bearing_value));
reply.content.emplace_back("\",");
intToString(bearing_value, temp_bearing);
reply.content.emplace_back(temp_bearing);
reply.content.emplace_back("]");
route_segments_list.emplace_back(
Segment(segment.name_id, segment.length, route_segments_list.size()));
}
}
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
{
++round_about.leave_at_exit;
}
if (segment.necessary)
{
++necessary_segments_running_index;
}
}
if (INVALID_EDGE_WEIGHT != route_length)
{
reply.content.emplace_back(",[\"");
intToString(as_integer(TurnInstruction::ReachedYourDestination), temp_instruction);
reply.content.emplace_back(temp_instruction);
reply.content.emplace_back("\",\"");
reply.content.emplace_back("\",");
reply.content.emplace_back("0");
reply.content.emplace_back(",");
intToString(necessary_segments_running_index - 1, temp_length);
reply.content.emplace_back(temp_length);
reply.content.emplace_back(",");
reply.content.emplace_back("0");
reply.content.emplace_back(",\"");
reply.content.emplace_back("\",\"");
reply.content.emplace_back(Azimuth::Get(0.0));
reply.content.emplace_back("\",");
reply.content.emplace_back("0.0");
reply.content.emplace_back("]");
}
}
};
#endif /* JSON_DESCRIPTOR_H_ */
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../Algorithms/ExtractRouteNames.h"
#include "../DataStructures/JSONContainer.h"
#include "../DataStructures/Range.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/Azimuth.h"
#include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include <algorithm>
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
{
private:
DataFacadeT *facade;
DescriptorConfig config;
DescriptionFactory description_factory, alternate_description_factory;
FixedPointCoordinate current;
unsigned entered_restricted_area_count;
struct RoundAbout
{
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
int start_index;
unsigned name_id;
int leave_at_exit;
} round_about;
struct Segment
{
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
unsigned name_id;
int length;
unsigned position;
};
std::vector<Segment> shortest_path_segments, alternative_path_segments;
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
public:
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
void SetConfig(const DescriptorConfig &c) final { config = c; }
unsigned DescribeLeg(const std::vector<PathData> route_leg,
const PhantomNodes &leg_phantoms,
const bool target_traversed_in_reverse,
const bool is_via_leg)
{
unsigned added_element_count = 0;
// Get all the coordinates for the computed route
FixedPointCoordinate current_coordinate;
for (const PathData &path_data : route_leg)
{
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current_coordinate, path_data);
++added_element_count;
}
description_factory.SetEndSegment(
leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg);
++added_element_count;
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
return added_element_count;
}
void Run(const RawRouteData &raw_route, http::Reply &reply) final
{
JSON::Object json_result;
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
{
// We do not need to do much, if there is no route ;-)
json_result.values["status"] = 207;
json_result.values["status_message"] = "Cannot find route between points";
JSON::render(reply.content, json_result);
return;
}
// check if first segment is non-zero
std::string road_name = facade->GetEscapedNameForNameID(
raw_route.segment_end_coordinates.front().source_phantom.name_id);
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
raw_route.segment_end_coordinates.size());
description_factory.SetStartSegment(
raw_route.segment_end_coordinates.front().source_phantom,
raw_route.source_traversed_in_reverse.front());
json_result.values["status"] = 0;
json_result.values["status_message"] = "Found route between points";
// for each unpacked segment add the leg to the description
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
{
#ifndef NDEBUG
const int added_segments =
#endif
DescribeLeg(raw_route.unpacked_path_segments[i],
raw_route.segment_end_coordinates[i],
raw_route.target_traversed_in_reverse[i],
raw_route.is_via_leg(i));
BOOST_ASSERT(0 < added_segments);
}
description_factory.Run(facade, config.zoom_level);
if (config.geometry)
{
JSON::Value route_geometry =
description_factory.AppendGeometryString(config.encode_geometry);
json_result.values["route_geometry"] = route_geometry;
}
if (config.instructions)
{
JSON::Array json_route_instructions;
BuildTextualDescription(description_factory,
json_route_instructions,
raw_route.shortest_path_length,
shortest_path_segments);
json_result.values["route_instructions"] = json_route_instructions;
}
description_factory.BuildRouteSummary(description_factory.entireLength,
raw_route.shortest_path_length);
JSON::Object json_route_summary;
json_route_summary.values["total_distance"] = description_factory.summary.distance;
json_route_summary.values["total_time"] = description_factory.summary.duration;
json_route_summary.values["start_point"] =
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
json_route_summary.values["end_point"] =
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
json_result.values["route_summary"] = json_route_summary;
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
JSON::Array json_via_points_array;
JSON::Array json_first_coordinate;
json_first_coordinate.values.push_back(
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
COORDINATE_PRECISION);
json_first_coordinate.values.push_back(
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
COORDINATE_PRECISION);
json_via_points_array.values.push_back(json_first_coordinate);
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
{
std::string tmp;
JSON::Array json_coordinate;
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
COORDINATE_PRECISION);
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
COORDINATE_PRECISION);
json_via_points_array.values.push_back(json_coordinate);
}
json_result.values["via_points"] = json_via_points_array;
JSON::Array json_via_indices_array;
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
shortest_leg_end_indices.begin(),
shortest_leg_end_indices.end());
json_result.values["via_indices"] = json_via_indices_array;
// only one alternative route is computed at this time, so this is hardcoded
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
json_result.values["found_alternative"] = JSON::True();
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
alternate_description_factory.SetStartSegment(
raw_route.segment_end_coordinates.front().source_phantom,
raw_route.alt_source_traversed_in_reverse.front());
// Get all the coordinates for the computed route
for (const PathData &path_data : raw_route.unpacked_alternative)
{
current = facade->GetCoordinateOfNode(path_data.node);
alternate_description_factory.AppendSegment(current, path_data);
}
alternate_description_factory.SetEndSegment(
raw_route.segment_end_coordinates.back().target_phantom,
raw_route.alt_source_traversed_in_reverse.back());
alternate_description_factory.Run(facade, config.zoom_level);
if (config.geometry)
{
JSON::Value alternate_geometry_string =
alternate_description_factory.AppendGeometryString(config.encode_geometry);
JSON::Array json_alternate_geometries_array;
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
}
// Generate instructions for each alternative (simulated here)
JSON::Array json_alt_instructions;
JSON::Array json_current_alt_instructions;
if (config.instructions)
{
BuildTextualDescription(alternate_description_factory,
json_current_alt_instructions,
raw_route.alternative_path_length,
alternative_path_segments);
json_alt_instructions.values.push_back(json_current_alt_instructions);
json_result.values["alternative_instructions"] = json_alt_instructions;
}
alternate_description_factory.BuildRouteSummary(
alternate_description_factory.entireLength, raw_route.alternative_path_length);
JSON::Object json_alternate_route_summary;
JSON::Array json_alternate_route_summary_array;
json_alternate_route_summary.values["total_distance"] =
alternate_description_factory.summary.distance;
json_alternate_route_summary.values["total_time"] =
alternate_description_factory.summary.duration;
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
alternate_description_factory.summary.source_name_id);
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
alternate_description_factory.summary.target_name_id);
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
std::vector<unsigned> const &alternate_leg_end_indices =
alternate_description_factory.GetViaIndices();
JSON::Array json_altenative_indices_array;
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
alternate_leg_end_indices.begin(),
alternate_leg_end_indices.end());
json_result.values["alternative_indices"] = json_altenative_indices_array;
}
else
{
json_result.values["found_alternative"] = JSON::False();
}
// Get Names for both routes
RouteNames route_names =
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
JSON::Array json_route_names;
json_route_names.values.push_back(route_names.shortest_path_name_1);
json_route_names.values.push_back(route_names.shortest_path_name_2);
json_result.values["route_name"] = json_route_names;
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
JSON::Array json_alternate_names_array;
JSON::Array json_alternate_names;
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
json_alternate_names_array.values.push_back(json_alternate_names);
json_result.values["alternative_names"] = json_alternate_names_array;
}
JSON::Object json_hint_object;
json_hint_object.values["checksum"] = raw_route.check_sum;
JSON::Array json_location_hint_array;
std::string hint;
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
{
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
json_location_hint_array.values.push_back(hint);
}
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
json_location_hint_array.values.push_back(hint);
json_hint_object.values["locations"] = json_location_hint_array;
json_result.values["hint_data"] = json_hint_object;
// render the content to the output array
TIMER_START(route_render);
JSON::render(reply.content, json_result);
TIMER_STOP(route_render);
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
}
// TODO: reorder parameters
inline void BuildTextualDescription(DescriptionFactory &description_factory,
JSON::Array &json_instruction_array,
const int route_length,
std::vector<Segment> &route_segments_list)
{
// Segment information has following format:
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
unsigned necessary_segments_running_index = 0;
round_about.leave_at_exit = 0;
round_about.name_id = 0;
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
// Fetch data from Factory and generate a string from it.
for (const SegmentInformation &segment : description_factory.path_description)
{
JSON::Array json_instruction_row;
TurnInstruction current_instruction = segment.turn_instruction;
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
{
if (TurnInstruction::EnterRoundAbout == current_instruction)
{
round_about.name_id = segment.name_id;
round_about.start_index = necessary_segments_running_index;
}
else
{
std::string current_turn_instruction;
if (TurnInstruction::LeaveRoundAbout == current_instruction)
{
temp_instruction =
cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
current_turn_instruction += temp_instruction;
current_turn_instruction += "-";
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
current_turn_instruction += temp_instruction;
round_about.leave_at_exit = 0;
}
else
{
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction));
current_turn_instruction += temp_instruction;
}
json_instruction_row.values.push_back(current_turn_instruction);
json_instruction_row.values.push_back(
facade->GetEscapedNameForNameID(segment.name_id));
json_instruction_row.values.push_back(std::round(segment.length));
json_instruction_row.values.push_back(necessary_segments_running_index);
json_instruction_row.values.push_back(round(segment.duration / 10));
json_instruction_row.values.push_back(
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
const double bearing_value = (segment.bearing / 10.);
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
json_instruction_row.values.push_back(
static_cast<unsigned>(round(bearing_value)));
json_instruction_row.values.push_back(segment.travel_mode);
route_segments_list.emplace_back(
segment.name_id,
static_cast<int>(segment.length),
static_cast<unsigned>(route_segments_list.size()));
json_instruction_array.values.push_back(json_instruction_row);
}
}
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
{
++round_about.leave_at_exit;
}
if (segment.necessary)
{
++necessary_segments_running_index;
}
}
JSON::Array json_last_instruction_row;
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
json_last_instruction_row.values.push_back(temp_instruction);
json_last_instruction_row.values.push_back("");
json_last_instruction_row.values.push_back(0);
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
json_last_instruction_row.values.push_back(0);
json_last_instruction_row.values.push_back("0m");
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
json_last_instruction_row.values.push_back(0.);
json_instruction_array.values.push_back(json_last_instruction_row);
}
};
#endif /* JSON_DESCRIPTOR_H_ */
+6 -4
View File
@@ -32,16 +32,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/ref.hpp>
#include <boost/regex.hpp>
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment)
: extractor_callbacks(extractor_callbacks),
lua_state(scripting_environment.getLuaStateForThreadID(0)),
lua_state(scripting_environment.getLuaState()),
scripting_environment(scripting_environment), use_turn_restrictions(true)
{
ReadUseRestrictionsSetting();
@@ -52,12 +53,13 @@ void BaseParser::ReadUseRestrictionsSetting()
{
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
{
throw OSRMException("ERROR occured in scripting block");
use_turn_restrictions = false;
}
if (lua_isboolean(lua_state, -1))
else if (lua_isboolean(lua_state, -1))
{
use_turn_restrictions = lua_toboolean(lua_state, -1);
}
if (use_turn_restrictions)
{
SimpleLogger().Write() << "Using turn restrictions";
+77 -97
View File
@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ExtractionContainers.h"
#include "ExtractionWay.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include "../Util/TimingUtil.h"
#include "../DataStructures/RangeTable.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
@@ -63,49 +65,46 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
{
unsigned number_of_used_nodes = 0;
unsigned number_of_used_edges = 0;
std::chrono::time_point<std::chrono::steady_clock> time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
TIMER_START(sorting_used_nodes);
stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
std::chrono::time_point<std::chrono::steady_clock> time2 = std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sorting_used_nodes);
std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
TIMER_START(erasing_dups);
auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
used_node_id_list.resize(new_end - used_node_id_list.begin());
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(erasing_dups);
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
TIMER_START(sorting_nodes);
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sorting_nodes);
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Sorting used ways ... " << std::flush;
TIMER_START(sort_ways);
stxxl::sort(
way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sort_ways);
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
TIMER_START(sort_restrictions);
stxxl::sort(restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByFrom(),
stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sort_restrictions);
std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
TIMER_START(fix_restriction_starts);
auto restrictions_iterator = restrictions_list.begin();
auto way_start_and_end_iterator = way_start_end_id_list.begin();
@@ -149,24 +148,21 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
++restrictions_iterator;
}
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
TIMER_STOP(fix_restriction_starts);
std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
TIMER_START(sort_restrictions_to);
stxxl::sort(restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByTo(),
stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sort_restrictions_to);
std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
unsigned number_of_useable_restrictions = 0;
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
TIMER_START(fix_restriction_ends);
restrictions_iterator = restrictions_list.begin();
way_start_and_end_iterator = way_start_end_id_list.begin();
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
@@ -207,24 +203,22 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
}
++restrictions_iterator;
}
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(fix_restriction_ends);
std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
// serialize restrictions
std::ofstream restrictions_out_stream;
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
restrictions_out_stream.write((char *)&uuid, sizeof(UUID));
restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
for (restrictions_iterator = restrictions_list.begin();
restrictions_iterator != restrictions_list.end();
++restrictions_iterator)
for(const auto & restriction_container : restrictions_list)
{
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
{
restrictions_out_stream.write((char *)&(restrictions_iterator->restriction),
restrictions_out_stream.write((char *)&(restriction_container.restriction),
sizeof(TurnRestriction));
}
}
@@ -232,27 +226,26 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
std::ofstream file_out_stream;
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
file_out_stream.write((char *)&uuid, sizeof(UUID));
file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
TIMER_START(write_nodes);
// identify all used nodes by a merging step of two sorted lists
auto node_iterator = all_nodes_list.begin();
auto node_id_iterator = used_node_id_list.begin();
while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
{
if (*node_id_iterator < node_iterator->id)
if (*node_id_iterator < node_iterator->node_id)
{
++node_id_iterator;
continue;
}
if (*node_id_iterator > node_iterator->id)
if (*node_id_iterator > node_iterator->node_id)
{
++node_iterator;
continue;
}
BOOST_ASSERT(*node_id_iterator == node_iterator->id);
BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
@@ -261,87 +254,82 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
++node_iterator;
}
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(write_nodes);
std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
std::cout << "[extractor] setting number of nodes ... " << std::flush;
std::ios::pos_type previous_file_position = file_out_stream.tellp();
file_out_stream.seekp(std::ios::beg + sizeof(UUID));
file_out_stream.seekp(std::ios::beg + sizeof(FingerPrint));
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
file_out_stream.seekp(previous_file_position);
std::cout << "ok" << std::endl;
time1 = std::chrono::steady_clock::now();
// Sort edges by start.
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
TIMER_START(sort_edges_by_start);
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sort_edges_by_start);
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Setting start coords ... " << std::flush;
TIMER_START(set_start_coords);
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
// Traverse list of edges and nodes in parallel and set start coord
node_iterator = all_nodes_list.begin();
auto edge_iterator = all_edges_list.begin();
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
{
if (edge_iterator->start < node_iterator->id)
if (edge_iterator->start < node_iterator->node_id)
{
++edge_iterator;
continue;
}
if (edge_iterator->start > node_iterator->id)
if (edge_iterator->start > node_iterator->node_id)
{
node_iterator++;
continue;
}
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
BOOST_ASSERT(edge_iterator->start == node_iterator->node_id);
edge_iterator->source_coordinate.lat = node_iterator->lat;
edge_iterator->source_coordinate.lon = node_iterator->lon;
++edge_iterator;
}
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(set_start_coords);
std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
// Sort Edges by target
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
TIMER_START(sort_edges_by_target);
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(sort_edges_by_target);
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Setting target coords ... " << std::flush;
TIMER_START(set_target_coords);
// Traverse list of edges and nodes in parallel and set target coord
node_iterator = all_nodes_list.begin();
edge_iterator = all_edges_list.begin();
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
{
if (edge_iterator->target < node_iterator->id)
if (edge_iterator->target < node_iterator->node_id)
{
++edge_iterator;
continue;
}
if (edge_iterator->target > node_iterator->id)
if (edge_iterator->target > node_iterator->node_id)
{
++node_iterator;
continue;
}
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
BOOST_ASSERT(edge_iterator->target == node_iterator->node_id);
if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
{
BOOST_ASSERT(edge_iterator->speed != -1);
BOOST_ASSERT(edge_iterator->type >= 0);
edge_iterator->target_coordinate.lat = node_iterator->lat;
edge_iterator->target_coordinate.lon = node_iterator->lon;
@@ -382,20 +370,22 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
}
file_out_stream.write((char *)&integer_weight, sizeof(int));
file_out_stream.write((char *)&edge_iterator->type, sizeof(short));
file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
// cannot take adress of bit field, so use local
const TravelMode travel_mode = edge_iterator->travel_mode;
file_out_stream.write((char *)&travel_mode, sizeof(TravelMode));
file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
++number_of_used_edges;
}
++edge_iterator;
}
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(set_target_coords);
std::cout << "ok, after " << TIMER_SEC(set_target_coords) << "s" << std::endl;
std::cout << "[extractor] setting number of edges ... " << std::flush;
@@ -403,45 +393,35 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
file_out_stream.close();
std::cout << "ok" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] writing street name index ... " << std::flush;
TIMER_START(write_name_index);
std::string name_file_streamName = (output_file_name + ".names");
boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);
// write number of names
const unsigned number_of_names = name_list.size() + 1;
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
// compute total number of chars
unsigned total_number_of_chars = 0;
unsigned total_length = 0;
std::vector<unsigned> name_lengths;
for (const std::string &temp_string : name_list)
{
total_number_of_chars += temp_string.length();
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
name_lengths.push_back(string_length);
total_length += string_length;
}
// write total number of chars
name_file_stream.write((char *)&(total_number_of_chars), sizeof(unsigned));
// write prefixe sums
unsigned name_lengths_prefix_sum = 0;
for (const std::string &temp_string : name_list)
{
name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
name_lengths_prefix_sum += temp_string.length();
}
// duplicate on purpose!
name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
RangeTable<> table(name_lengths);
name_file_stream << table;
name_file_stream.write((char*) &total_length, sizeof(unsigned));
// write all chars consecutively
for (const std::string &temp_string : name_list)
{
const unsigned string_length = temp_string.length();
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
name_file_stream.write(temp_string.c_str(), string_length);
}
name_file_stream.close();
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
TIMER_STOP(write_name_index);
std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
<< number_of_used_edges << " edges";
+13 -9
View File
@@ -31,20 +31,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "InternalExtractorEdge.h"
#include "ExtractorStructs.h"
#include "../DataStructures/Restriction.h"
#include "../Util/UUID.h"
#include "../Util/FingerPrint.h"
#include <stxxl/vector>
class ExtractionContainers
{
#ifndef _MSC_VER
constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
#else
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
public:
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
typedef stxxl::vector<std::string> STXXLStringVector;
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
using STXXLNodeIDVector = stxxl::vector<NodeID>;
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
using STXXLStringVector = stxxl::vector<std::string>;
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
using STXXLWayIDStartEndVector = stxxl::vector<WayIDStartAndEndEdge>;
STXXLNodeIDVector used_node_id_list;
STXXLNodeVector all_nodes_list;
@@ -52,11 +56,11 @@ class ExtractionContainers
STXXLStringVector name_list;
STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
const UUID uuid;
const FingerPrint fingerprint;
ExtractionContainers();
virtual ~ExtractionContainers();
~ExtractionContainers();
void PrepareData(const std::string &output_file_name,
const std::string &restrictions_file_name);
+10 -9
View File
@@ -28,10 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef EXTRACTION_HELPER_FUNCTIONS_H
#define EXTRACTION_HELPER_FUNCTIONS_H
#include "../Util/StringUtil.h"
#include "../Util/cast.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/regex.hpp>
#include <limits>
@@ -48,7 +49,7 @@ inline bool durationIsValid(const std::string &s)
std::vector<std::string> result;
boost::algorithm::split_regex(result, s, boost::regex(":"));
bool matched = regex_match(s, e);
const bool matched = regex_match(s, e);
return matched;
}
@@ -63,23 +64,23 @@ inline unsigned parseDuration(const std::string &s)
std::vector<std::string> result;
boost::algorithm::split_regex(result, s, boost::regex(":"));
bool matched = regex_match(s, e);
const bool matched = regex_match(s, e);
if (matched)
{
if (1 == result.size())
{
minutes = stringToInt(result[0]);
minutes = cast::string_to_int(result[0]);
}
if (2 == result.size())
{
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
minutes = cast::string_to_int(result[1]);
hours = cast::string_to_int(result[0]);
}
if (3 == result.size())
{
seconds = stringToInt(result[2]);
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
seconds = cast::string_to_int(result[2]);
minutes = cast::string_to_int(result[1]);
hours = cast::string_to_int(result[0]);
}
return 10 * (3600 * hours + 60 * minutes + seconds);
}
+58 -7
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define EXTRACTION_WAY_H
#include "../DataStructures/HashTable.h"
#include "../DataStructures/TravelMode.h"
#include "../typedefs.h"
#include <string>
@@ -43,16 +44,16 @@ struct ExtractionWay
id = SPECIAL_NODEID;
nameID = INVALID_NAMEID;
path.clear();
keyVals.clear();
direction = ExtractionWay::notSure;
speed = -1;
keyVals.Clear();
forward_speed = -1;
backward_speed = -1;
duration = -1;
type = -1;
access = true;
roundabout = false;
isAccessRestricted = false;
ignoreInGrid = false;
forward_travel_mode = TRAVEL_MODE_DEFAULT;
backward_travel_mode = TRAVEL_MODE_DEFAULT;
}
enum Directions
@@ -60,20 +61,70 @@ struct ExtractionWay
oneway,
bidirectional,
opposite };
// These accessor methods exists to support the depreciated "way.direction" access
// in LUA. Since the direction attribute was removed from ExtractionWay, the
// accessors translate to/from the mode attributes.
inline void set_direction(const Directions m)
{
if (Directions::oneway == m)
{
forward_travel_mode = TRAVEL_MODE_DEFAULT;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
}
else if (Directions::opposite == m)
{
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_DEFAULT;
}
else if (Directions::bidirectional == m)
{
forward_travel_mode = TRAVEL_MODE_DEFAULT;
backward_travel_mode = TRAVEL_MODE_DEFAULT;
}
}
inline const Directions get_direction() const
{
if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
{
return Directions::bidirectional;
}
else if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode)
{
return Directions::oneway;
}
else if (TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
{
return Directions::opposite;
}
else
{
return Directions::notSure;
}
}
// These accessors exists because it's not possible to take the address of a bitfield,
// and LUA therefore cannot read/write the mode attributes directly.
inline void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
inline const TravelMode get_forward_mode() const { return forward_travel_mode; }
inline void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
inline const TravelMode get_backward_mode() const { return backward_travel_mode; }
unsigned id;
unsigned nameID;
double speed;
double forward_speed;
double backward_speed;
double duration;
Directions direction;
std::string name;
short type;
bool access;
bool roundabout;
bool isAccessRestricted;
bool ignoreInGrid;
std::vector<NodeID> path;
HashTable<std::string, std::string> keyVals;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
};
#endif // EXTRACTION_WAY_H
+302
View File
@@ -0,0 +1,302 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Extractor.h"
#include "ExtractorCallbacks.h"
#include "ExtractionContainers.h"
#include "PBFParser.h"
#include "ScriptingEnvironment.h"
#include "XMLParser.h"
#include "../Util/GitDescription.h"
#include "../Util/IniFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/simple_logger.hpp"
#include "../Util/TimingUtil.h"
#include "../typedefs.h"
#include <boost/program_options.hpp>
#include <tbb/task_scheduler_init.h>
#include <cstdlib>
#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>
#include <unordered_map>
Extractor::Extractor() : requested_num_threads(0), file_has_pbf_format(false)
{
}
Extractor::~Extractor() {}
bool Extractor::ParseArguments(int argc, char *argv[])
{
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
"config,c",
boost::program_options::value<boost::filesystem::path>(&config_file_path)
->default_value("extractor.ini"),
"Path to a configuration file.");
// declare a group of options that will be allowed both on command line and in config file
boost::program_options::options_description config_options("Configuration");
config_options.add_options()("profile,p",
boost::program_options::value<boost::filesystem::path>(
&profile_path)->default_value("profile.lua"),
"Path to LUA routing profile")(
"threads,t",
boost::program_options::value<unsigned int>(&requested_num_threads)
->default_value(tbb::task_scheduler_init::default_num_threads()),
"Number of threads to use");
// hidden options, will be allowed both on command line and in config file, but will not be
// shown to the user
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()(
"input,i",
boost::program_options::value<boost::filesystem::path>(&input_path),
"Input file in .osm, .osm.bz2 or .osm.pbf format");
// positional option
boost::program_options::positional_options_description positional_options;
positional_options.add("input", 1);
// combine above options for parsing
boost::program_options::options_description cmdline_options;
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
boost::program_options::options_description config_file_options;
config_file_options.add(config_options).add(hidden_options);
boost::program_options::options_description visible_options(
boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
visible_options.add(generic_options).add(config_options);
// parse command line options
boost::program_options::variables_map option_variables;
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
.options(cmdline_options)
.positional(positional_options)
.run(),
option_variables);
if (option_variables.count("version"))
{
SimpleLogger().Write() << g_GIT_DESCRIPTION;
return false;
}
if (option_variables.count("help"))
{
SimpleLogger().Write() << visible_options;
return false;
}
boost::program_options::notify(option_variables);
// parse config file
if (boost::filesystem::is_regular_file(config_file_path))
{
SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
std::string ini_file_contents = ReadIniFileAndLowerContents(config_file_path);
std::stringstream config_stream(ini_file_contents);
boost::program_options::store(parse_config_file(config_stream, config_file_options),
option_variables);
boost::program_options::notify(option_variables);
}
if (!option_variables.count("input"))
{
SimpleLogger().Write() << visible_options;
return false;
}
return true;
}
void Extractor::GenerateOutputFilesNames()
{
output_file_name = input_path.string();
restriction_file_name = input_path.string();
std::string::size_type pos = output_file_name.find(".osm.bz2");
if (pos == std::string::npos)
{
pos = output_file_name.find(".osm.pbf");
if (pos != std::string::npos)
{
file_has_pbf_format = true;
}
else
{
pos = output_file_name.find(".osm.xml");
}
}
if (pos == std::string::npos)
{
pos = output_file_name.find(".pbf");
if (pos != std::string::npos)
{
file_has_pbf_format = true;
}
}
if (pos == std::string::npos)
{
pos = output_file_name.find(".osm");
if (pos == std::string::npos)
{
output_file_name.append(".osrm");
restriction_file_name.append(".osrm.restrictions");
}
else
{
output_file_name.replace(pos, 5, ".osrm");
restriction_file_name.replace(pos, 5, ".osrm.restrictions");
}
}
else
{
output_file_name.replace(pos, 8, ".osrm");
restriction_file_name.replace(pos, 8, ".osrm.restrictions");
}
}
int Extractor::Run(int argc, char *argv[])
{
try
{
LogPolicy::GetInstance().Unmute();
TIMER_START(extracting);
if (!ParseArguments(argc, argv))
return 0;
if (1 > requested_num_threads)
{
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
return 1;
}
if (!boost::filesystem::is_regular_file(input_path))
{
SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
<< " not found!";
return 1;
}
if (!boost::filesystem::is_regular_file(profile_path))
{
SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
<< " not found!";
return 1;
}
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
SimpleLogger().Write() << "Threads: " << requested_num_threads;
if (recommended_num_threads != requested_num_threads)
{
SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
<< recommended_num_threads
<< "! This setting may have performance side-effects.";
}
tbb::task_scheduler_init init(requested_num_threads);
/*** Setup Scripting Environment ***/
ScriptingEnvironment scripting_environment(profile_path.string().c_str());
GenerateOutputFilesNames();
std::unordered_map<std::string, NodeID> string_map;
ExtractionContainers extraction_containers;
string_map[""] = 0;
auto extractor_callbacks = new ExtractorCallbacks(extraction_containers, string_map);
BaseParser *parser;
if (file_has_pbf_format)
{
parser = new PBFParser(input_path.string().c_str(),
extractor_callbacks,
scripting_environment,
requested_num_threads);
}
else
{
parser = new XMLParser(input_path.string().c_str(),
extractor_callbacks,
scripting_environment);
}
if (!parser->ReadHeader())
{
throw OSRMException("Parser not initialized!");
}
SimpleLogger().Write() << "Parsing in progress..";
TIMER_START(parsing);
parser->Parse();
delete parser;
delete extractor_callbacks;
TIMER_STOP(parsing);
SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
if (extraction_containers.all_edges_list.empty())
{
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
return 1;
}
extraction_containers.PrepareData(output_file_name, restriction_file_name);
TIMER_STOP(extracting);
SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
SimpleLogger().Write() << "To prepare the data for routing, run: "
<< "./osrm-prepare " << output_file_name << std::endl;
}
catch (boost::program_options::too_many_positional_options_error &)
{
SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
return 1;
}
catch (std::exception &e)
{
SimpleLogger().Write(logWARNING) << e.what();
return 1;
}
return 0;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef EXTRACTOR_H_
#define EXTRACTOR_H_
#include <boost/filesystem.hpp>
#include <string>
class ExtractorCallbacks;
/** \brief Class of 'extract' utility. */
class Extractor
{
protected:
unsigned requested_num_threads;
boost::filesystem::path config_file_path;
boost::filesystem::path input_path;
boost::filesystem::path profile_path;
std::string output_file_name;
std::string restriction_file_name;
bool file_has_pbf_format;
/** \brief Parses "extractor's" command line arguments */
bool ParseArguments(int argc, char *argv[]);
/** \brief Parses config file, if present in options */
void GenerateOutputFilesNames();
public:
explicit Extractor();
Extractor(const Extractor &) = delete;
virtual ~Extractor();
int Run(int argc, char *argv[]);
};
#endif /* EXTRACTOR_H_ */
+103 -85
View File
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/Restriction.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include <osrm/Coordinate.h>
@@ -63,102 +63,120 @@ bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &res
/** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
{
if ((0 < parsed_way.speed) || (0 < parsed_way.duration))
if (((0 >= parsed_way.forward_speed) ||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
((0 >= parsed_way.backward_speed) ||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
(0 >= parsed_way.duration))
{ // Only true if the way is specified by the speed profile
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
{
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
<< " of size " << parsed_way.path.size();
return;
}
return;
}
if (0 < parsed_way.duration)
{
// TODO: iterate all way segments and set duration corresponding to the length of each
// segment
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
}
if (parsed_way.path.size() <= 1)
{ // safe-guard against broken data
return;
}
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
{
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
return;
}
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
{
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
<< " of size " << parsed_way.path.size();
return;
}
// Get the unique identifier for the street name
const auto &string_map_iterator = string_map.find(parsed_way.name);
if (string_map.end() == string_map_iterator)
{
parsed_way.nameID = external_memory.name_list.size();
external_memory.name_list.push_back(parsed_way.name);
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
}
else
{
parsed_way.nameID = string_map_iterator->second;
}
if (0 < parsed_way.duration)
{
// TODO: iterate all way segments and set duration corresponding to the length of each
// segment
parsed_way.forward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
parsed_way.backward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
}
if (ExtractionWay::opposite == parsed_way.direction)
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
{
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
return;
}
// Get the unique identifier for the street name
const auto &string_map_iterator = string_map.find(parsed_way.name);
if (string_map.end() == string_map_iterator)
{
parsed_way.nameID = external_memory.name_list.size();
external_memory.name_list.push_back(parsed_way.name);
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
}
else
{
parsed_way.nameID = string_map_iterator->second;
}
if (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)
{
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
parsed_way.forward_travel_mode = parsed_way.backward_travel_mode;
parsed_way.backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
}
const bool split_edge =
(parsed_way.forward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
(parsed_way.backward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
((parsed_way.forward_speed != parsed_way.backward_speed) ||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
BOOST_ASSERT(parsed_way.forward_travel_mode>0);
for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
{
external_memory.all_edges_list.push_back(InternalExtractorEdge(
parsed_way.path[n],
parsed_way.path[n + 1],
((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode) ? ExtractionWay::oneway
: ExtractionWay::bidirectional),
parsed_way.forward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
parsed_way.forward_travel_mode,
split_edge));
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
}
external_memory.used_node_id_list.push_back(parsed_way.path.back());
// The following information is needed to identify start and end segments of restrictions
external_memory.way_start_end_id_list.push_back(
WayIDStartAndEndEdge(parsed_way.id,
parsed_way.path[0],
parsed_way.path[1],
parsed_way.path[parsed_way.path.size() - 2],
parsed_way.path.back()));
if (split_edge)
{ // Only true if the way should be split
BOOST_ASSERT(parsed_way.backward_travel_mode>0);
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
{
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
parsed_way.direction = ExtractionWay::oneway;
external_memory.all_edges_list.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n + 1],
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
parsed_way.backward_travel_mode,
split_edge));
}
const bool split_bidirectional_edge =
(parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
for (unsigned n = 0; n < parsed_way.path.size() - 1; ++n)
{
external_memory.all_edges_list.push_back(InternalExtractorEdge(
parsed_way.path[n],
parsed_way.path[n + 1],
parsed_way.type,
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
parsed_way.speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
false,
split_bidirectional_edge));
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
}
external_memory.used_node_id_list.push_back(parsed_way.path.back());
// The following information is needed to identify start and end segments of restrictions
external_memory.way_start_end_id_list.push_back(
WayIDStartAndEndEdge(parsed_way.id,
parsed_way.path[0],
parsed_way.path[1],
parsed_way.path[parsed_way.path.size() - 2],
parsed_way.path.back()));
if (split_bidirectional_edge)
{ // Only true if the way should be split
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
{
external_memory.all_edges_list.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n + 1],
parsed_way.type,
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction),
split_bidirectional_edge));
}
external_memory.way_start_end_id_list.push_back(
WayIDStartAndEndEdge(parsed_way.id,
parsed_way.path[0],
parsed_way.path[1],
parsed_way.path[parsed_way.path.size() - 2],
parsed_way.path.back()));
}
}
}
+6 -6
View File
@@ -83,7 +83,7 @@ struct WayIDStartAndEndEdge
struct CmpWayByID
{
typedef WayIDStartAndEndEdge value_type;
using value_type = WayIDStartAndEndEdge;
bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
{
return a.wayID < b.wayID;
@@ -94,18 +94,18 @@ struct CmpWayByID
struct Cmp
{
typedef NodeID value_type;
bool operator()(const NodeID a, const NodeID b) const { return a < b; }
using value_type = NodeID;
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
value_type max_value() { return 0xffffffff; }
value_type min_value() { return 0x0; }
};
struct CmpNodeByID
{
typedef ExternalMemoryNode value_type;
bool operator()(const ExternalMemoryNode &a, const ExternalMemoryNode &b) const
using value_type = ExternalMemoryNode;
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
{
return a.id < b.id;
return left.node_id < right.node_id;
}
value_type max_value() { return ExternalMemoryNode::max_value(); }
value_type min_value() { return ExternalMemoryNode::min_value(); }
+11 -13
View File
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INTERNAL_EXTRACTOR_EDGE_H
#include "../typedefs.h"
#include "../DataStructures/TravelMode.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
@@ -36,15 +37,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct InternalExtractorEdge
{
InternalExtractorEdge()
: start(0), target(0), type(0), direction(0), speed(0), name_id(0), is_roundabout(false),
: start(0), target(0), direction(0), speed(0), name_id(0), is_roundabout(false),
is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
is_contra_flow(false), is_split(false)
travel_mode(TRAVEL_MODE_INACCESSIBLE), is_split(false)
{
}
explicit InternalExtractorEdge(NodeID start,
NodeID target,
short type,
short direction,
double speed,
unsigned name_id,
@@ -52,30 +52,28 @@ struct InternalExtractorEdge
bool is_in_tiny_cc,
bool is_duration_set,
bool is_access_restricted,
bool is_contra_flow,
TravelMode travel_mode,
bool is_split)
: start(start), target(target), type(type), direction(direction), speed(speed),
: start(start), target(target), direction(direction), speed(speed),
name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc),
is_duration_set(is_duration_set), is_access_restricted(is_access_restricted),
is_contra_flow(is_contra_flow), is_split(is_split)
travel_mode(travel_mode), is_split(is_split)
{
BOOST_ASSERT(0 <= type);
}
// necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_value()
{
return InternalExtractorEdge(0, 0, 0, 0, 0, 0, false, false, false, false, false, false);
return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false);
}
static InternalExtractorEdge max_value()
{
return InternalExtractorEdge(
SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false);
SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false);
}
NodeID start;
NodeID target;
short type;
short direction;
double speed;
unsigned name_id;
@@ -83,7 +81,7 @@ struct InternalExtractorEdge
bool is_in_tiny_cc;
bool is_duration_set;
bool is_access_restricted;
bool is_contra_flow;
TravelMode travel_mode : 4;
bool is_split;
FixedPointCoordinate source_coordinate;
@@ -92,7 +90,7 @@ struct InternalExtractorEdge
struct CmpEdgeByStartID
{
typedef InternalExtractorEdge value_type;
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
{
return a.start < b.start;
@@ -105,7 +103,7 @@ struct CmpEdgeByStartID
struct CmpEdgeByTargetID
{
typedef InternalExtractorEdge value_type;
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
{
+117 -92
View File
@@ -35,26 +35,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/Restriction.h"
#include "../Util/MachineInfo.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <boost/ref.hpp>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>
#include <osrm/Coordinate.h>
#include <zlib.h>
#include <functional>
#include <iostream>
#include <limits>
#include <thread>
PBFParser::PBFParser(const char *fileName,
ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment)
ScriptingEnvironment &scripting_environment,
unsigned num_threads)
: BaseParser(extractor_callbacks, scripting_environment)
{
if (0 == num_threads)
{
num_parser_threads = tbb::task_scheduler_init::default_num_threads();
}
else
{
num_parser_threads = num_threads;
}
GOOGLE_PROTOBUF_VERIFY_VERSION;
// TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
// NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
@@ -103,7 +116,7 @@ inline bool PBFParser::ReadHeader()
if (readBlob(input, &init_data))
{
if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
init_data.charBuffer.size()))
static_cast<int>(init_data.charBuffer.size())))
{
std::cerr << "[error] Header not parseable!" << std::endl;
return false;
@@ -161,6 +174,8 @@ inline void PBFParser::ReadData()
inline void PBFParser::ParseData()
{
tbb::task_scheduler_init init(num_parser_threads);
while (true)
{
ParserThreadData *thread_data;
@@ -233,17 +248,17 @@ inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
m_lastDenseID += dense.id(i);
m_lastDenseLatitude += dense.lat(i);
m_lastDenseLongitude += dense.lon(i);
extracted_nodes_vector[i].id = m_lastDenseID;
extracted_nodes_vector[i].lat =
extracted_nodes_vector[i].node_id = static_cast<NodeID>(m_lastDenseID);
extracted_nodes_vector[i].lat = static_cast<int>(
COORDINATE_PRECISION *
((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
thread_data->PBFprimitiveBlock.lat_offset()) /
NANO;
extracted_nodes_vector[i].lon =
NANO);
extracted_nodes_vector[i].lon = static_cast<int>(
COORDINATE_PRECISION *
((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
thread_data->PBFprimitiveBlock.lon_offset()) /
NANO;
NANO);
while (denseTagIndex < dense.keys_vals_size())
{
const int tagValue = dense.keys_vals(denseTagIndex);
@@ -255,20 +270,21 @@ inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
const int keyValue = dense.keys_vals(denseTagIndex + 1);
const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
extracted_nodes_vector[i].keyVals.emplace(key, value);
extracted_nodes_vector[i].keyVals.Add(std::move(key), std::move(value));
denseTagIndex += 2;
}
}
#pragma omp parallel
{
const int thread_num = omp_get_thread_num();
#pragma omp parallel for schedule(guided)
for (int i = 0; i < number_of_nodes; ++i)
tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
[this, &extracted_nodes_vector](const tbb::blocked_range<size_t> &range)
{
lua_State *lua_state = this->scripting_environment.getLuaState();
for (size_t i = range.begin(); i != range.end(); ++i)
{
ImportNode &import_node = extracted_nodes_vector[i];
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
ParseNodeInLua(import_node, lua_state);
}
}
});
for (const ImportNode &import_node : extracted_nodes_vector)
{
@@ -297,8 +313,8 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
std::string except_tag_string;
const OSMPBF::Relation &inputRelation =
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
bool isRestriction = false;
bool isOnlyRestriction = false;
bool is_restriction = false;
bool is_only_restriction = false;
for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
{
const std::string &key =
@@ -309,7 +325,7 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
{
if ("restriction" == val)
{
isRestriction = true;
is_restriction = true;
}
else
{
@@ -318,7 +334,7 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
}
if (("restriction" == key) && (val.find("only_") == 0))
{
isOnlyRestriction = true;
is_only_restriction = true;
}
if ("except" == key)
{
@@ -326,22 +342,22 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
}
}
if (isRestriction && ShouldIgnoreRestriction(except_tag_string))
if (is_restriction && ShouldIgnoreRestriction(except_tag_string))
{
continue;
}
if (isRestriction)
if (is_restriction)
{
int64_t lastRef = 0;
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
int64_t last_ref = 0;
InputRestrictionContainer current_restriction_container(is_only_restriction);
for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
rolesIndex < last_role;
++rolesIndex)
{
const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
inputRelation.roles_sid(rolesIndex));
lastRef += inputRelation.memids(rolesIndex);
last_ref += inputRelation.memids(rolesIndex);
if (!("from" == role || "to" == role || "via" == role))
{
@@ -355,41 +371,46 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
{ // Only via should be a node
continue;
}
assert("via" == role);
if (std::numeric_limits<unsigned>::max() != currentRestrictionContainer.viaNode)
BOOST_ASSERT("via" == role);
if (std::numeric_limits<unsigned>::max() !=
current_restriction_container.viaNode)
{
currentRestrictionContainer.viaNode = std::numeric_limits<unsigned>::max();
current_restriction_container.viaNode =
std::numeric_limits<unsigned>::max();
}
assert(std::numeric_limits<unsigned>::max() == currentRestrictionContainer.viaNode);
currentRestrictionContainer.restriction.viaNode = lastRef;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() ==
current_restriction_container.viaNode);
current_restriction_container.restriction.viaNode =
static_cast<NodeID>(last_ref);
break;
case 1: // way
assert("from" == role || "to" == role || "via" == role);
BOOST_ASSERT("from" == role || "to" == role || "via" == role);
if ("from" == role)
{
currentRestrictionContainer.fromWay = lastRef;
current_restriction_container.fromWay = static_cast<EdgeID>(last_ref);
}
if ("to" == role)
{
currentRestrictionContainer.toWay = lastRef;
current_restriction_container.toWay = static_cast<EdgeID>(last_ref);
}
if ("via" == role)
{
assert(currentRestrictionContainer.restriction.toNode == std::numeric_limits<unsigned>::max());
currentRestrictionContainer.viaNode = lastRef;
BOOST_ASSERT(current_restriction_container.restriction.toNode ==
std::numeric_limits<unsigned>::max());
current_restriction_container.viaNode = static_cast<NodeID>(last_ref);
}
break;
case 2: // relation, not used. relations relating to relations are evil.
continue;
assert(false);
BOOST_ASSERT(false);
break;
default: // should not happen
assert(false);
BOOST_ASSERT(false);
break;
}
}
if (!extractor_callbacks->ProcessRestriction(currentRestrictionContainer))
if (!extractor_callbacks->ProcessRestriction(current_restriction_container))
{
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
@@ -404,38 +425,42 @@ inline void PBFParser::parseWay(ParserThreadData *thread_data)
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
for (int i = 0; i < number_of_ways; ++i)
{
const OSMPBF::Way &inputWay =
const OSMPBF::Way &input_way =
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
parsed_way_vector[i].id = inputWay.id();
unsigned pathNode(0);
const int number_of_referenced_nodes = inputWay.refs_size();
for (int j = 0; j < number_of_referenced_nodes; ++j)
parsed_way_vector[i].id = static_cast<EdgeID>(input_way.id());
unsigned node_id_in_path = 0;
const auto number_of_referenced_nodes = input_way.refs_size();
for (auto j = 0; j < number_of_referenced_nodes; ++j)
{
pathNode += inputWay.refs(j);
parsed_way_vector[i].path.push_back(pathNode);
node_id_in_path += static_cast<NodeID>(input_way.refs(j));
parsed_way_vector[i].path.push_back(node_id_in_path);
}
assert(inputWay.keys_size() == inputWay.vals_size());
const int number_of_keys = inputWay.keys_size();
for (int j = 0; j < number_of_keys; ++j)
BOOST_ASSERT(input_way.keys_size() == input_way.vals_size());
const auto number_of_keys = input_way.keys_size();
for (auto j = 0; j < number_of_keys; ++j)
{
const std::string &key =
thread_data->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
thread_data->PBFprimitiveBlock.stringtable().s(input_way.keys(j));
const std::string &val =
thread_data->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
parsed_way_vector[i].keyVals.emplace(key, val);
thread_data->PBFprimitiveBlock.stringtable().s(input_way.vals(j));
parsed_way_vector[i].keyVals.Add(std::move(key), std::move(val));
}
}
#pragma omp parallel for schedule(guided)
for (int i = 0; i < number_of_ways; ++i)
{
ExtractionWay &extraction_way = parsed_way_vector[i];
if (2 <= extraction_way.path.size())
// TODO: investigate if schedule guided will be handled by tbb automatically
tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
[this, &parsed_way_vector](const tbb::blocked_range<size_t> &range)
{
lua_State *lua_state = this->scripting_environment.getLuaState();
for (size_t i = range.begin(); i != range.end(); i++)
{
ParseWayInLua(extraction_way,
scripting_environment.getLuaStateForThreadID(omp_get_thread_num()));
ExtractionWay &extraction_way = parsed_way_vector[i];
if (2 <= extraction_way.path.size())
{
ParseWayInLua(extraction_way, lua_state);
}
}
}
});
for (ExtractionWay &extraction_way : parsed_way_vector)
{
@@ -470,9 +495,9 @@ inline void PBFParser::loadGroup(ParserThreadData *thread_data)
if (group.has_dense())
{
thread_data->entityTypeIndicator = TypeDenseNode;
assert(0 != group.dense().id_size());
BOOST_ASSERT(0 != group.dense().id_size());
}
assert(thread_data->entityTypeIndicator != TypeDummy);
BOOST_ASSERT(thread_data->entityTypeIndicator != TypeDummy);
}
inline void PBFParser::loadBlock(ParserThreadData *thread_data)
@@ -503,51 +528,51 @@ inline bool PBFParser::readPBFBlobHeader(std::fstream &stream, ParserThreadData
return dataSuccessfullyParsed;
}
inline bool PBFParser::unpackZLIB(std::fstream &, ParserThreadData *thread_data)
inline bool PBFParser::unpackZLIB(ParserThreadData *thread_data)
{
unsigned rawSize = thread_data->PBFBlob.raw_size();
char *unpackedDataArray = new char[rawSize];
z_stream compressedDataStream;
compressedDataStream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
compressedDataStream.avail_in = thread_data->PBFBlob.zlib_data().size();
compressedDataStream.next_out = (unsigned char *)unpackedDataArray;
compressedDataStream.avail_out = rawSize;
compressedDataStream.zalloc = Z_NULL;
compressedDataStream.zfree = Z_NULL;
compressedDataStream.opaque = Z_NULL;
int ret = inflateInit(&compressedDataStream);
if (ret != Z_OK)
auto raw_size = thread_data->PBFBlob.raw_size();
char *unpacked_data_array = new char[raw_size];
z_stream compressed_data_stream;
compressed_data_stream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
compressed_data_stream.avail_in = thread_data->PBFBlob.zlib_data().size();
compressed_data_stream.next_out = (unsigned char *)unpacked_data_array;
compressed_data_stream.avail_out = raw_size;
compressed_data_stream.zalloc = Z_NULL;
compressed_data_stream.zfree = Z_NULL;
compressed_data_stream.opaque = Z_NULL;
int return_code = inflateInit(&compressed_data_stream);
if (return_code != Z_OK)
{
std::cerr << "[error] failed to init zlib stream" << std::endl;
delete[] unpackedDataArray;
delete[] unpacked_data_array;
return false;
}
ret = inflate(&compressedDataStream, Z_FINISH);
if (ret != Z_STREAM_END)
return_code = inflate(&compressed_data_stream, Z_FINISH);
if (return_code != Z_STREAM_END)
{
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
std::cerr << "[error] Error type: " << ret << std::endl;
delete[] unpackedDataArray;
std::cerr << "[error] Error type: " << return_code << std::endl;
delete[] unpacked_data_array;
return false;
}
ret = inflateEnd(&compressedDataStream);
if (ret != Z_OK)
return_code = inflateEnd(&compressed_data_stream);
if (return_code != Z_OK)
{
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
delete[] unpackedDataArray;
delete[] unpacked_data_array;
return false;
}
thread_data->charBuffer.clear();
thread_data->charBuffer.resize(rawSize);
std::copy(unpackedDataArray, unpackedDataArray + rawSize, thread_data->charBuffer.begin());
delete[] unpackedDataArray;
thread_data->charBuffer.resize(raw_size);
std::copy(unpacked_data_array, unpacked_data_array + raw_size, thread_data->charBuffer.begin());
delete[] unpacked_data_array;
return true;
}
inline bool PBFParser::unpackLZMA(std::fstream &, ParserThreadData *) { return false; }
inline bool PBFParser::unpackLZMA(ParserThreadData *) { return false; }
inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
{
@@ -582,7 +607,7 @@ inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_d
}
else if (thread_data->PBFBlob.has_zlib_data())
{
if (!unpackZLIB(stream, thread_data))
if (!unpackZLIB(thread_data))
{
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
delete[] data;
@@ -591,7 +616,7 @@ inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_d
}
else if (thread_data->PBFBlob.has_lzma_data())
{
if (!unpackLZMA(stream, thread_data))
if (!unpackLZMA(thread_data))
{
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
}
@@ -631,7 +656,7 @@ bool PBFParser::readNextBlock(std::fstream &stream, ParserThreadData *thread_dat
}
if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
thread_data->charBuffer.size()))
thread_data->charBuffer.size()))
{
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
return false;
+7 -3
View File
@@ -63,7 +63,10 @@ class PBFParser : public BaseParser
};
public:
PBFParser(const char *file_name, ExtractorCallbacks *extractor_callbacks, ScriptingEnvironment &scripting_environment);
PBFParser(const char *file_name,
ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment,
unsigned num_parser_threads = 0);
virtual ~PBFParser();
inline bool ReadHeader();
@@ -80,8 +83,8 @@ class PBFParser : public BaseParser
inline void loadGroup(ParserThreadData *thread_data);
inline void loadBlock(ParserThreadData *thread_data);
inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
inline bool unpackZLIB(std::fstream &stream, ParserThreadData *thread_data);
inline bool unpackLZMA(std::fstream &stream, ParserThreadData *thread_data);
inline bool unpackZLIB(ParserThreadData *thread_data);
inline bool unpackLZMA(ParserThreadData *thread_data);
inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
@@ -94,6 +97,7 @@ class PBFParser : public BaseParser
std::fstream input; // the input stream to parse
std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
unsigned num_parser_threads;
};
#endif /* PBFPARSER_H_ */
+75 -77
View File
@@ -31,94 +31,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ExtractionWay.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/simple_logger.hpp"
#include "../typedefs.h"
#include <sstream>
ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
: file_name(file_name)
{
SimpleLogger().Write() << "Using script " << file_name;
// Create a new lua state
for (int i = 0; i < omp_get_max_threads(); ++i)
{
lua_state_vector.push_back(luaL_newstate());
}
// Connect LuaBind to this lua state for all threads
#pragma omp parallel
{
lua_State *lua_state = getLuaStateForThreadID(omp_get_thread_num());
luabind::open(lua_state);
// open utility libraries string library;
luaL_openlibs(lua_state);
luaAddScriptFolderToLoadPath(lua_state, file_name);
// Add our function to the state's global scope
luabind::module(lua_state)[
luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)];
luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readonly("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)];
luabind::module(lua_state)
[luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants")[
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]];
// fails on c++11/OS X 10.9
luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
"Add",
static_cast<void (std::vector<std::string>::*)(const std::string &)>(
&std::vector<std::string>::push_back))];
if (0 != luaL_dofile(lua_state, file_name))
{
throw OSRMException("ERROR occured in scripting block");
}
}
}
ScriptingEnvironment::~ScriptingEnvironment()
void ScriptingEnvironment::initLuaState(lua_State* lua_state)
{
for (unsigned i = 0; i < lua_state_vector.size(); ++i)
luabind::open(lua_state);
// open utility libraries string library;
luaL_openlibs(lua_state);
luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
// Add our function to the state's global scope
luabind::module(lua_state)[
luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration),
luabind::class_<HashTable<std::string, std::string>>("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds),
luabind::class_<ImportNode>("Node")
// .def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readonly("id", &ImportNode::node_id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals),
luabind::class_<ExtractionWay>("Way")
// .def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("forward_speed", &ExtractionWay::forward_speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.property("direction", &ExtractionWay::get_direction, &ExtractionWay::set_direction)
.property("forward_mode", &ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode)
.property("backward_mode", &ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode)
.enum_("constants")[
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
],
luabind::class_<std::vector<std::string>>("vector")
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string &)>(&std::vector<std::string>::push_back))
];
if (0 != luaL_dofile(lua_state, file_name.c_str()))
{
// lua_state_vector[i];
luabind::object error_msg(luabind::from_stack(lua_state, -1));
std::ostringstream error_stream;
error_stream << error_msg;
throw OSRMException("ERROR occured in profile script:\n" + error_stream.str());
}
}
lua_State *ScriptingEnvironment::getLuaStateForThreadID(const int id) { return lua_state_vector[id]; }
lua_State *ScriptingEnvironment::getLuaState()
{
bool initialized = false;
auto& ref = script_contexts.local(initialized);
if (!initialized)
{
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
ref = state;
initLuaState(ref.get());
}
return ref.get();
}
+9 -4
View File
@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SCRIPTINGENVIRONMENT_H_
#define SCRIPTINGENVIRONMENT_H_
#include <vector>
#include <string>
#include <memory>
#include <tbb/enumerable_thread_specific.h>
struct lua_State;
@@ -37,11 +39,14 @@ class ScriptingEnvironment
public:
ScriptingEnvironment();
explicit ScriptingEnvironment(const char *file_name);
virtual ~ScriptingEnvironment();
lua_State *getLuaStateForThreadID(const int);
lua_State *getLuaState();
std::vector<lua_State *> lua_state_vector;
private:
void initLuaState(lua_State* lua_state);
std::string file_name;
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
};
#endif /* SCRIPTINGENVIRONMENT_H_ */
+222 -215
View File
@@ -34,21 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/InputReaderFactory.h"
#include "../DataStructures/Restriction.h"
#include "../Util/SimpleLogger.h"
#include "../Util/cast.hpp"
#include "../Util/simple_logger.hpp"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/ref.hpp>
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
: BaseParser(ec, se)
XMLParser::XMLParser(const char *filename,
ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment)
: BaseParser(extractor_callbacks, scripting_environment)
{
inputReader = inputReaderFactory(filename);
}
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
bool XMLParser::Parse()
{
while (xmlTextReaderRead(inputReader) == 1)
@@ -62,16 +63,16 @@ bool XMLParser::Parse()
}
xmlChar *currentName = xmlTextReaderName(inputReader);
if (currentName == NULL)
if (currentName == nullptr)
{
continue;
}
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
{
ImportNode n = ReadXMLNode();
ParseNodeInLua(n, lua_state);
extractor_callbacks->ProcessNode(n);
ImportNode current_node = ReadXMLNode();
ParseNodeInLua(current_node, lua_state);
extractor_callbacks->ProcessNode(current_node);
}
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
@@ -82,8 +83,9 @@ bool XMLParser::Parse()
}
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
{
InputRestrictionContainer r = ReadXMLRestriction();
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->ProcessRestriction(r))
InputRestrictionContainer current_restriction = ReadXMLRestriction();
if ((UINT_MAX != current_restriction.fromWay) &&
!extractor_callbacks->ProcessRestriction(current_restriction))
{
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
}
@@ -95,103 +97,106 @@ bool XMLParser::Parse()
InputRestrictionContainer XMLParser::ReadXMLRestriction()
{
InputRestrictionContainer restriction;
std::string except_tag_string;
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
{
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
return restriction;
}
std::string except_tag_string;
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
{
const int child_type = xmlTextReaderNodeType(inputReader);
if (child_type != 1 && child_type != 15)
{
const int childType = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15)
{
continue;
}
const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && childType == 15 &&
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
{
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
{
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (k != NULL && value != NULL)
{
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
(0 == std::string((const char *)value).find("only_")))
{
restriction.restriction.flags.isOnly = true;
}
if (xmlStrEqual(k, (const xmlChar *)"except"))
{
except_tag_string = (const char *)value;
}
}
if (k != NULL)
{
xmlFree(k);
}
if (value != NULL)
{
xmlFree(value);
}
}
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != NULL)
{
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
if (xmlStrEqual(role, (const xmlChar *)"to") &&
xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.toWay = stringToUint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"from") &&
xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.fromWay = stringToUint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"via") &&
xmlStrEqual(type, (const xmlChar *)"node"))
{
restriction.restriction.viaNode = stringToUint((const char *)ref);
}
if (NULL != type)
{
xmlFree(type);
}
if (NULL != role)
{
xmlFree(role);
}
if (NULL != ref)
{
xmlFree(ref);
}
}
}
xmlFree(childName);
continue;
}
const int child_depth = xmlTextReaderDepth(inputReader);
xmlChar *child_name = xmlTextReaderName(inputReader);
if (child_name == nullptr)
{
continue;
}
if (depth == child_depth && child_type == 15 &&
xmlStrEqual(child_name, (const xmlChar *)"relation") == 1)
{
xmlFree(child_name);
break;
}
if (child_type != 1)
{
xmlFree(child_name);
continue;
}
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
{
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (key != nullptr && value != nullptr)
{
if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
StringStartsWith((const char *)value, "only_"))
{
restriction.restriction.flags.isOnly = true;
}
if (xmlStrEqual(key, (const xmlChar *)"except"))
{
except_tag_string = (const char *)value;
}
}
if (key != nullptr)
{
xmlFree(key);
}
if (value != nullptr)
{
xmlFree(value);
}
}
else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != nullptr)
{
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
if (xmlStrEqual(role, (const xmlChar *)"to") &&
xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.toWay = cast::string_to_uint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"from") &&
xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.fromWay = cast::string_to_uint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"via") &&
xmlStrEqual(type, (const xmlChar *)"node"))
{
restriction.restriction.viaNode = cast::string_to_uint((const char *)ref);
}
if (nullptr != type)
{
xmlFree(type);
}
if (nullptr != role)
{
xmlFree(role);
}
if (nullptr != ref)
{
xmlFree(ref);
}
}
}
xmlFree(child_name);
}
if (ShouldIgnoreRestriction(except_tag_string))
@@ -204,67 +209,68 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction()
ExtractionWay XMLParser::ReadXMLWay()
{
ExtractionWay way;
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
{
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
return way;
}
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
{
const int child_type = xmlTextReaderNodeType(inputReader);
if (child_type != 1 && child_type != 15)
{
const int childType = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15)
{
continue;
}
const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && childType == 15 &&
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
{
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
way.id = stringToUint((char *)id);
xmlFree(id);
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
{
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (k != NULL && value != NULL)
{
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
}
if (k != NULL)
{
xmlFree(k);
}
if (value != NULL)
{
xmlFree(value);
}
}
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != NULL)
{
way.path.push_back(stringToUint((const char *)ref));
xmlFree(ref);
}
}
xmlFree(childName);
continue;
}
const int child_depth = xmlTextReaderDepth(inputReader);
xmlChar *child_name = xmlTextReaderName(inputReader);
if (child_name == nullptr)
{
continue;
}
if (depth == child_depth && child_type == 15 &&
xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
{
xmlChar *way_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
way.id = cast::string_to_uint((char *)way_id);
xmlFree(way_id);
xmlFree(child_name);
break;
}
if (child_type != 1)
{
xmlFree(child_name);
continue;
}
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
{
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (key != nullptr && value != nullptr)
{
way.keyVals.Add(std::string((char *)key), std::string((char *)value));
}
if (key != nullptr)
{
xmlFree(key);
}
if (value != nullptr)
{
xmlFree(value);
}
}
else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != nullptr)
{
way.path.push_back(cast::string_to_uint((const char *)ref));
xmlFree(ref);
}
}
xmlFree(child_name);
}
return way;
}
@@ -274,74 +280,75 @@ ImportNode XMLParser::ReadXMLNode()
ImportNode node;
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
if (attribute != NULL)
if (attribute != nullptr)
{
node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
node.lat = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
xmlFree(attribute);
}
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
if (attribute != NULL)
if (attribute != nullptr)
{
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
node.lon = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
xmlFree(attribute);
}
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
if (attribute != NULL)
if (attribute != nullptr)
{
node.id = stringToUint((const char *)attribute);
node.node_id = cast::string_to_uint((const char *)attribute);
xmlFree(attribute);
}
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
{
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
return node;
}
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
{
const int child_type = xmlTextReaderNodeType(inputReader);
// 1 = Element, 15 = EndElement
if (child_type != 1 && child_type != 15)
{
const int childType = xmlTextReaderNodeType(inputReader);
// 1 = Element, 15 = EndElement
if (childType != 1 && childType != 15)
{
continue;
}
const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && childType == 15 &&
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
{
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
{
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (k != NULL && value != NULL)
{
node.keyVals.emplace(std::string((char *)(k)), std::string((char *)(value)));
}
if (k != NULL)
{
xmlFree(k);
}
if (value != NULL)
{
xmlFree(value);
}
}
xmlFree(childName);
continue;
}
const int child_depth = xmlTextReaderDepth(inputReader);
xmlChar *child_name = xmlTextReaderName(inputReader);
if (child_name == nullptr)
{
continue;
}
if (depth == child_depth && child_type == 15 &&
xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
{
xmlFree(child_name);
break;
}
if (child_type != 1)
{
xmlFree(child_name);
continue;
}
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
{
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (key != nullptr && value != nullptr)
{
node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
}
if (key != nullptr)
{
xmlFree(key);
}
if (value != nullptr)
{
xmlFree(value);
}
}
xmlFree(child_name);
}
return node;
}
+6 -2
View File
@@ -28,15 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef XMLPARSER_H_
#define XMLPARSER_H_
#include "ExtractorCallbacks.h"
#include "BaseParser.h"
#include "../DataStructures/Restriction.h"
#include <libxml/xmlreader.h>
class ExtractorCallbacks;
class XMLParser : public BaseParser
{
public:
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
XMLParser(const char *filename,
ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment);
bool ReadHeader();
bool Parse();
+45 -20
View File
@@ -29,8 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define FIXED_POINT_COORDINATE_H_
#include <iosfwd> //for std::ostream
#include <string>
#include <type_traits>
constexpr double COORDINATE_PRECISION = 1000000.;
constexpr float COORDINATE_PRECISION = 1000000.f;
struct FixedPointCoordinate
{
@@ -38,7 +40,15 @@ struct FixedPointCoordinate
int lon;
FixedPointCoordinate();
explicit FixedPointCoordinate(int lat, int lon);
FixedPointCoordinate(int lat, int lon);
template<class T>
FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon)
{
static_assert(std::is_same<decltype(lat), decltype(coordinate.lat)>::value, "coordinate types incompatible");
static_assert(std::is_same<decltype(lon), decltype(coordinate.lon)>::value, "coordinate types incompatible");
}
void Reset();
bool isSet() const;
bool isValid() const;
@@ -47,40 +57,55 @@ struct FixedPointCoordinate
static double
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
static double ApproximateDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2);
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate);
static double ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2);
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate);
static double
static float
ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate);
static void convertInternalLatLonToString(const int value, std::string &output);
static void convertInternalCoordinateToString(const FixedPointCoordinate &coord,
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
std::string &output);
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
std::string &output);
static double ComputePerpendicularDistance(const FixedPointCoordinate &point,
const FixedPointCoordinate &segA,
const FixedPointCoordinate &segB);
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location);
static double ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
const FixedPointCoordinate &coord_b,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
double &r);
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
float &ratio);
static int
OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location);
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
float GetBearing(const FixedPointCoordinate &other) const;
void Output(std::ostream &out) const;
static float DegreeToRadian(const float degree);
static float RadianToDegree(const float radian);
};
inline std::ostream &operator<<(std::ostream &o, FixedPointCoordinate const &c)
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
{
c.Output(o);
return o;
coordinate.Output(out_stream);
return out_stream;
}
#endif /* FIXED_POINT_COORDINATE_H_ */
+8 -2
View File
@@ -29,18 +29,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define HTTP_HEADER_H
#include <string>
#include <algorithm>
namespace http
{
struct Header
{
std::string name;
std::string value;
Header& operator=(const Header& other) = default;
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
Header(Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
void Clear()
{
name.clear();
value.clear();
}
std::string name;
std::string value;
};
}
+3 -3
View File
@@ -56,11 +56,11 @@ class Reply
internalServerError = 500 } status;
std::vector<Header> headers;
std::vector<boost::asio::const_buffer> toBuffers();
std::vector<boost::asio::const_buffer> ToBuffers();
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
std::vector<std::string> content;
std::vector<char> content;
static Reply StockReply(status_type status);
void setSize(const unsigned size);
void SetSize(const unsigned size);
void SetUncompressedSize();
Reply();
+9
View File
@@ -40,9 +40,15 @@ struct RouteParameters
RouteParameters();
void setZoomLevel(const short level);
void setNumberOfResults(const short number);
void setAlternateRouteFlag(const bool flag);
void setUTurn(const bool flag);
void setAllUTurns(const bool flag);
void setDeprecatedAPIFlag(const std::string &);
void setChecksum(const unsigned check_sum);
@@ -71,12 +77,15 @@ struct RouteParameters
bool geometry;
bool compression;
bool deprecatedAPI;
bool uturn_default;
unsigned check_sum;
short num_results;
std::string service;
std::string output_format;
std::string jsonp_parameter;
std::string language;
std::vector<std::string> hints;
std::vector<bool> uturns;
std::vector<FixedPointCoordinate> coordinates;
};
+4 -2
View File
@@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/ServerPaths.h>
#include <memory>
class OSRM_impl;
struct RouteParameters;
@@ -41,10 +43,10 @@ class Reply;
class OSRM
{
private:
OSRM_impl *OSRM_pimpl_;
std::unique_ptr<OSRM_impl> OSRM_pimpl_;
public:
explicit OSRM(const ServerPaths &paths, const bool use_shared_memory = false);
explicit OSRM(ServerPaths paths, const bool use_shared_memory = false);
~OSRM();
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
};
+29 -13
View File
@@ -25,36 +25,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace boost { namespace interprocess { class named_mutex; } }
#include "OSRM_impl.h"
#include "OSRM.h"
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <osrm/ServerPaths.h>
#include "../Plugins/BasePlugin.h"
#include "../Plugins/DistanceTablePlugin.h"
#include "../Plugins/HelloWorldPlugin.h"
#include "../Plugins/LocatePlugin.h"
#include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h"
#include "../Server/DataStructures/BaseDataFacade.h"
#include "../Server/DataStructures/InternalDataFacade.h"
#include "../Server/DataStructures/SharedBarriers.h"
#include "../Server/DataStructures/SharedDataFacade.h"
#include "../Util/make_unique.hpp"
#include "../Util/ProgramOptions.h"
#include "../Util/simple_logger.hpp"
#include <boost/assert.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
: use_shared_memory(use_shared_memory)
#include <algorithm>
#include <fstream>
#include <utility>
#include <vector>
OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory)
{
if (use_shared_memory)
{
barrier = new SharedBarriers();
barrier = osrm::make_unique<SharedBarriers>();
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
}
else
{
// populate base path
populate_base_path(server_paths);
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
}
// The following plugins handle all requests.
RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new HelloWorldPlugin());
RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
@@ -64,14 +83,11 @@ OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memo
OSRM_impl::~OSRM_impl()
{
delete query_data_facade;
for (PluginMap::value_type &plugin_pointer : plugin_map)
{
delete plugin_pointer.second;
}
if (use_shared_memory)
{
delete barrier;
}
}
void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
@@ -91,7 +107,7 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
if (plugin_map.end() != iter)
{
reply.status = http::Reply::ok;
if (use_shared_memory)
if (barrier)
{
// lock update pending
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
@@ -112,7 +128,7 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
}
iter->second->HandleRequest(route_parameters, reply);
if (use_shared_memory)
if (barrier)
{
// lock query
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
@@ -137,12 +153,12 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
// proxy code for compilation firewall
OSRM::OSRM(const ServerPaths &paths, const bool use_shared_memory)
: OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory))
OSRM::OSRM(ServerPaths paths, const bool use_shared_memory)
: OSRM_pimpl_(osrm::make_unique<OSRM_impl>(paths, use_shared_memory))
{
}
OSRM::~OSRM() { delete OSRM_pimpl_; }
OSRM::~OSRM() { OSRM_pimpl_.reset(); }
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
{
+9 -8
View File
@@ -28,14 +28,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_IMPL_H
#define OSRM_IMPL_H
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
class BasePlugin;
namespace http { class Reply; }
struct RouteParameters;
#include <osrm/ServerPaths.h>
#include "../DataStructures/QueryEdge.h"
#include "../Plugins/BasePlugin.h"
#include "../Util/ProgramOptions.h"
#include <memory>
#include <unordered_map>
#include <string>
@@ -45,10 +46,10 @@ template <class EdgeDataT> class BaseDataFacade;
class OSRM_impl
{
private:
typedef std::unordered_map<std::string, BasePlugin *> PluginMap;
using PluginMap = std::unordered_map<std::string, BasePlugin *>;
public:
OSRM_impl(const ServerPaths &paths, const bool use_shared_memory);
OSRM_impl(ServerPaths paths, const bool use_shared_memory);
OSRM_impl(const OSRM_impl &) = delete;
virtual ~OSRM_impl();
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
@@ -56,8 +57,8 @@ class OSRM_impl
private:
void RegisterPlugin(BasePlugin *plugin);
PluginMap plugin_map;
bool use_shared_memory;
SharedBarriers *barrier;
// will only be initialized if shared memory is used
std::unique_ptr<SharedBarriers> barrier;
// base class pointer to the objects
BaseDataFacade<QueryEdge::EdgeData> *query_data_facade;
};
+148
View File
@@ -0,0 +1,148 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DISTANCE_TABLE_PLUGIN_H
#define DISTANCE_TABLE_PLUGIN_H
#include "BasePlugin.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/JSONContainer.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Util/make_unique.hpp"
#include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include <cstdlib>
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
{
private:
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
public:
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
{
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
}
virtual ~DistanceTablePlugin() {}
const std::string GetDescriptor() const final { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
{
// check number of parameters
if (2 > route_parameters.coordinates.size())
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
RawRouteData raw_route;
raw_route.check_sum = facade->GetCheckSum();
if (std::any_of(begin(route_parameters.coordinates),
end(route_parameters.coordinates),
[&](FixedPointCoordinate coordinate)
{
return !coordinate.isValid();
}))
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
{
raw_route.raw_via_node_coordinates.emplace_back(std::move(coordinate));
}
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
unsigned max_locations =
std::min(100u, static_cast<unsigned>(raw_route.raw_via_node_coordinates.size()));
PhantomNodeArray phantom_node_vector(max_locations);
for (unsigned i = 0; i < max_locations; ++i)
{
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
{
PhantomNode current_phantom_node;
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
if (current_phantom_node.isValid(facade->GetNumberOfNodes()))
{
phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
continue;
}
}
facade->IncrementalFindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
phantom_node_vector[i],
route_parameters.zoom_level,
1);
BOOST_ASSERT(phantom_node_vector[i].front().isValid(facade->GetNumberOfNodes()));
}
// TIMER_START(distance_table);
std::shared_ptr<std::vector<EdgeWeight>> result_table =
search_engine_ptr->distance_table(phantom_node_vector);
// TIMER_STOP(distance_table);
if (!result_table)
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
JSON::Object json_object;
JSON::Array json_array;
const unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
for (unsigned row = 0; row < number_of_locations; ++row)
{
JSON::Array json_row;
auto row_begin_iterator = result_table->begin() + (row * number_of_locations);
auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_locations);
json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
json_array.values.push_back(json_row);
}
json_object.values["distance_table"] = json_array;
JSON::render(reply.content, json_object);
}
private:
std::string descriptor_string;
DataFacadeT *facade;
};
#endif // DISTANCE_TABLE_PLUGIN_H
+46 -56
View File
@@ -25,15 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HELLOWORLDPLUGIN_H_
#define HELLOWORLDPLUGIN_H_
#ifndef HELLO_WORLD_PLUGIN_H
#define HELLO_WORLD_PLUGIN_H
#include "BasePlugin.h"
#include "../Util/StringUtil.h"
#include "../DataStructures/JSONContainer.h"
#include "../Util/cast.hpp"
#include <string>
class HelloWorldPlugin : public BasePlugin
class HelloWorldPlugin final : public BasePlugin
{
private:
std::string temp_string;
@@ -41,75 +42,64 @@ class HelloWorldPlugin : public BasePlugin
public:
HelloWorldPlugin() : descriptor_string("hello") {}
virtual ~HelloWorldPlugin() {}
const std::string GetDescriptor() const { return descriptor_string; }
const std::string GetDescriptor() const final { return descriptor_string; }
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) final
{
reply.status = http::Reply::ok;
reply.content.emplace_back("<html><head><title>Hello World Demonstration "
"Document</title></head><body><h1>Hello, World!</h1>");
reply.content.emplace_back("<pre>");
reply.content.emplace_back("zoom level: ");
intToString(routeParameters.zoom_level, temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("\nchecksum: ");
intToString(routeParameters.check_sum, temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("\ninstructions: ");
reply.content.emplace_back((routeParameters.print_instructions ? "yes" : "no"));
reply.content.emplace_back(temp_string);
reply.content.emplace_back("\ngeometry: ");
reply.content.emplace_back((routeParameters.geometry ? "yes" : "no"));
reply.content.emplace_back("\ncompression: ");
reply.content.emplace_back((routeParameters.compression ? "yes" : "no"));
reply.content.emplace_back("\noutput format: ");
reply.content.emplace_back(routeParameters.output_format);
reply.content.emplace_back("\njson parameter: ");
reply.content.emplace_back(routeParameters.jsonp_parameter);
reply.content.emplace_back("\nlanguage: ");
reply.content.emplace_back(routeParameters.language);
reply.content.emplace_back("\nNumber of locations: ");
intToString(routeParameters.coordinates.size(), temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("\n");
JSON::Object json_result;
std::string temp_string;
json_result.values["title"] = "Hello World";
temp_string = cast::integral_to_string(routeParameters.zoom_level);
json_result.values["zoom_level"] = temp_string;
temp_string = cast::integral_to_string(routeParameters.check_sum);
json_result.values["check_sum"] = temp_string;
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
json_result.values["output_format"] =
(!routeParameters.output_format.empty() ? "yes" : "no");
json_result.values["jsonp_parameter"] =
(!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
temp_string = cast::integral_to_string(routeParameters.coordinates.size());
json_result.values["location_count"] = temp_string;
JSON::Array json_locations;
unsigned counter = 0;
for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
{
reply.content.emplace_back(" [");
intToString(counter, temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("] ");
doubleToString(coordinate.lat / COORDINATE_PRECISION, temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back(",");
doubleToString(coordinate.lon / COORDINATE_PRECISION, temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("\n");
JSON::Object json_location;
JSON::Array json_coordinates;
json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
json_location.values[cast::integral_to_string(counter)] = json_coordinates;
json_locations.values.push_back(json_location);
++counter;
}
json_result.values["locations"] = json_locations;
json_result.values["hint_count"] = routeParameters.hints.size();
reply.content.emplace_back("Number of hints: ");
intToString(routeParameters.hints.size(), temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("\n");
JSON::Array json_hints;
counter = 0;
for (const std::string &current_string : routeParameters.hints)
for (const std::string &current_hint : routeParameters.hints)
{
reply.content.emplace_back(" [");
intToString(counter, temp_string);
reply.content.emplace_back(temp_string);
reply.content.emplace_back("] ");
reply.content.emplace_back(current_string);
reply.content.emplace_back("\n");
json_hints.values.push_back(current_hint);
++counter;
}
reply.content.emplace_back("</pre></body></html>");
json_result.values["hints"] = json_hints;
JSON::render(reply.content, json_result);
}
private:
std::string descriptor_string;
};
#endif /* HELLOWORLDPLUGIN_H_ */
#endif // HELLO_WORLD_PLUGIN_H
+15 -53
View File
@@ -29,17 +29,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define LOCATE_PLUGIN_H
#include "BasePlugin.h"
#include "../DataStructures/JSONContainer.h"
#include "../Util/StringUtil.h"
// locates the nearest node in the road network for a given coordinate.
#include <string>
template <class DataFacadeT> class LocatePlugin : public BasePlugin
// locates the nearest node in the road network for a given coordinate.
template <class DataFacadeT> class LocatePlugin final : public BasePlugin
{
public:
explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
const std::string GetDescriptor() const { return descriptor_string; }
const std::string GetDescriptor() const final { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
{
// check number of parameters
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
@@ -48,64 +50,24 @@ template <class DataFacadeT> class LocatePlugin : public BasePlugin
return;
}
// query to helpdesk
JSON::Object json_result;
FixedPointCoordinate result;
std::string tmp;
// json
if (!route_parameters.jsonp_parameter.empty())
{
reply.content.emplace_back(route_parameters.jsonp_parameter);
reply.content.emplace_back("(");
}
reply.status = http::Reply::ok;
reply.content.emplace_back("{");
if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
result))
{
reply.content.emplace_back("\"status\":207,");
reply.content.emplace_back("\"mapped_coordinate\":[]");
json_result.values["status"] = 207;
}
else
{
// Write coordinate to stream
reply.status = http::Reply::ok;
reply.content.emplace_back("\"status\":0,");
reply.content.emplace_back("\"mapped_coordinate\":");
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
reply.content.emplace_back("[");
reply.content.emplace_back(tmp);
FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
reply.content.emplace_back(",");
reply.content.emplace_back(tmp);
reply.content.emplace_back("]");
json_result.values["status"] = 0;
JSON::Array json_coordinate;
json_coordinate.values.push_back(result.lat / COORDINATE_PRECISION);
json_coordinate.values.push_back(result.lon / COORDINATE_PRECISION);
json_result.values["mapped_coordinate"] = json_coordinate;
}
reply.content.emplace_back("}");
reply.headers.resize(3);
if (!route_parameters.jsonp_parameter.empty())
{
reply.content.emplace_back(")");
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.js\"";
}
else
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.json\"";
}
reply.headers[0].name = "Content-Length";
unsigned content_length = 0;
for (const std::string &snippet : reply.content)
{
content_length += snippet.length();
}
intToString(content_length, tmp);
reply.headers[0].value = tmp;
return;
JSON::render(reply.content, json_result);
}
private:
+54 -76
View File
@@ -29,109 +29,87 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define NEAREST_PLUGIN_H
#include "BasePlugin.h"
#include "../DataStructures/JSONContainer.h"
#include "../DataStructures/PhantomNodes.h"
#include "../Util/StringUtil.h"
#include "../DataStructures/Range.h"
#include <unordered_map>
#include <string>
/*
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/
template <class DataFacadeT> class NearestPlugin : public BasePlugin
template <class DataFacadeT> class NearestPlugin final : public BasePlugin
{
public:
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest")
{
descriptor_table.emplace("", 0); // default descriptor
descriptor_table.emplace("json", 1);
}
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {}
const std::string GetDescriptor() const { return descriptor_string; }
const std::string GetDescriptor() const final { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
{
// check number of parameters
if (route_parameters.coordinates.empty())
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
if (!route_parameters.coordinates.front().isValid())
auto number_of_results = static_cast<std::size_t>(route_parameters.num_results);
std::vector<PhantomNode> phantom_node_vector;
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
phantom_node_vector,
route_parameters.zoom_level,
static_cast<int>(number_of_results));
JSON::Object json_result;
if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
PhantomNode result;
facade->FindPhantomNodeForCoordinate(
route_parameters.coordinates.front(), result, route_parameters.zoom_level);
// json
if (!route_parameters.jsonp_parameter.empty())
{
reply.content.emplace_back(route_parameters.jsonp_parameter);
reply.content.emplace_back("(");
}
reply.status = http::Reply::ok;
reply.content.emplace_back("{\"status\":");
if (SPECIAL_NODEID != result.forward_node_id)
{
reply.content.emplace_back("0,");
json_result.values["status"] = 207;
}
else
{
reply.content.emplace_back("207,");
}
reply.content.emplace_back("\"mapped_coordinate\":[");
std::string temp_string;
reply.status = http::Reply::ok;
json_result.values["status"] = 0;
if (SPECIAL_NODEID != result.forward_node_id)
{
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
reply.content.emplace_back(temp_string);
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
reply.content.emplace_back(",");
reply.content.emplace_back(temp_string);
if (number_of_results > 1)
{
JSON::Array results;
auto vector_length = phantom_node_vector.size();
for (const auto i : osrm::irange<std::size_t>(0, std::min(number_of_results, vector_length)))
{
JSON::Array json_coordinate;
JSON::Object result;
json_coordinate.values.push_back(phantom_node_vector.at(i).location.lat /
COORDINATE_PRECISION);
json_coordinate.values.push_back(phantom_node_vector.at(i).location.lon /
COORDINATE_PRECISION);
result.values["mapped coordinate"] = json_coordinate;
std::string temp_string;
facade->GetName(phantom_node_vector.front().name_id, temp_string);
result.values["name"] = temp_string;
results.values.push_back(result);
}
json_result.values["results"] = results;
}
else
{
JSON::Array json_coordinate;
json_coordinate.values.push_back(phantom_node_vector.front().location.lat /
COORDINATE_PRECISION);
json_coordinate.values.push_back(phantom_node_vector.front().location.lon /
COORDINATE_PRECISION);
json_result.values["mapped_coordinate"] = json_coordinate;
std::string temp_string;
facade->GetName(phantom_node_vector.front().name_id, temp_string);
json_result.values["name"] = temp_string;
}
}
reply.content.emplace_back("],\"name\":\"");
if (SPECIAL_NODEID != result.forward_node_id)
{
facade->GetName(result.name_id, temp_string);
reply.content.emplace_back(temp_string);
}
reply.content.emplace_back("\"}");
reply.headers.resize(3);
if (!route_parameters.jsonp_parameter.empty())
{
reply.content.emplace_back(")");
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.js\"";
}
else
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"location.json\"";
}
reply.headers[0].name = "Content-Length";
unsigned content_length = 0;
for (const std::string &snippet : reply.content)
{
content_length += snippet.length();
}
intToString(content_length, temp_string);
reply.headers[0].value = temp_string;
JSON::render(reply.content, json_result);
}
private:
DataFacadeT *facade;
std::unordered_map<std::string, unsigned> descriptor_table;
std::string descriptor_string;
};
+11 -42
View File
@@ -28,58 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef TIMESTAMP_PLUGIN_H
#define TIMESTAMP_PLUGIN_H
#include "../DataStructures/JSONContainer.h"
#include "BasePlugin.h"
template <class DataFacadeT> class TimestampPlugin : public BasePlugin
#include <string>
template <class DataFacadeT> class TimestampPlugin final : public BasePlugin
{
public:
explicit TimestampPlugin(const DataFacadeT *facade)
: facade(facade), descriptor_string("timestamp")
{
}
const std::string GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
const std::string GetDescriptor() const final { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
{
std::string tmp;
// json
if (!route_parameters.jsonp_parameter.empty())
{
reply.content.emplace_back(route_parameters.jsonp_parameter);
reply.content.emplace_back("(");
}
reply.status = http::Reply::ok;
reply.content.emplace_back("{");
reply.content.emplace_back("\"status\":");
reply.content.emplace_back("0,");
reply.content.emplace_back("\"timestamp\":\"");
reply.content.emplace_back(facade->GetTimestamp());
reply.content.emplace_back("\"");
reply.content.emplace_back("}");
reply.headers.resize(3);
if (!route_parameters.jsonp_parameter.empty())
{
reply.content.emplace_back(")");
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"timestamp.js\"";
}
else
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
}
unsigned content_length = 0;
for (const std::string &snippet : reply.content)
{
content_length += snippet.length();
}
intToString(content_length, tmp);
reply.headers[0].value = tmp;
JSON::Object json_result;
json_result.values["status"] = 0;
const std::string timestamp = facade->GetTimestamp();
json_result.values["timestamp"] = timestamp;
JSON::render(reply.content, json_result);
}
private:
+176 -241
View File
@@ -1,241 +1,176 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VIAROUTEPLUGIN_H_
#define VIAROUTEPLUGIN_H_
#include "BasePlugin.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <cstdlib>
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
{
private:
std::unordered_map<std::string, unsigned> descriptorTable;
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
public:
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
{
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
descriptorTable.emplace("json", 0);
descriptorTable.emplace("gpx", 1);
}
virtual ~ViaRoutePlugin() {}
const std::string GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
{
// check number of parameters
if (2 > routeParameters.coordinates.size())
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
RawRouteData raw_route;
raw_route.check_sum = facade->GetCheckSum();
if (std::any_of(begin(routeParameters.coordinates),
end(routeParameters.coordinates),
[&](FixedPointCoordinate coordinate)
{ return !coordinate.isValid(); }))
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
{
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
}
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
const bool checksum_OK = (routeParameters.check_sum == raw_route.check_sum);
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
{
if (checksum_OK && i < routeParameters.hints.size() &&
!routeParameters.hints[i].empty())
{
DecodeObjectFromBase64(routeParameters.hints[i], phantom_node_vector[i]);
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
{
continue;
}
}
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
phantom_node_vector[i],
routeParameters.zoom_level);
}
PhantomNodes current_phantom_node_pair;
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
{
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
}
if ((routeParameters.alternate_route) && (1 == raw_route.segment_end_coordinates.size()))
{
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
raw_route);
}
else
{
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
}
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
{
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
}
reply.status = http::Reply::ok;
if (!routeParameters.jsonp_parameter.empty())
{
reply.content.emplace_back(routeParameters.jsonp_parameter);
reply.content.emplace_back("(");
}
DescriptorConfig descriptor_config;
auto iter = descriptorTable.find(routeParameters.output_format);
unsigned descriptor_type = (iter != descriptorTable.end() ? iter->second : 0);
descriptor_config.zoom_level = routeParameters.zoom_level;
descriptor_config.instructions = routeParameters.print_instructions;
descriptor_config.geometry = routeParameters.geometry;
descriptor_config.encode_geometry = routeParameters.compression;
std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
switch (descriptor_type)
{
// case 0:
// descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
// break;
case 1:
descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>();
break;
default:
descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
break;
}
PhantomNodes phantom_nodes;
phantom_nodes.source_phantom = raw_route.segment_end_coordinates.front().source_phantom;
phantom_nodes.target_phantom = raw_route.segment_end_coordinates.back().target_phantom;
descriptor->SetConfig(descriptor_config);
descriptor->Run(raw_route, phantom_nodes, facade, reply);
if (!routeParameters.jsonp_parameter.empty())
{
reply.content.emplace_back(")\n");
}
reply.headers.resize(3);
reply.headers[0].name = "Content-Length";
unsigned content_length = 0;
for (const std::string &snippet : reply.content)
{
content_length += snippet.length();
}
std::string tmp_string;
intToString(content_length, tmp_string);
reply.headers[0].value = tmp_string;
switch (descriptor_type)
{
case 0:
if (!routeParameters.jsonp_parameter.empty())
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.js\"";
}
else
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
case 1:
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
break;
default:
if (!routeParameters.jsonp_parameter.empty())
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.js\"";
}
else
{
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
}
return;
}
private:
std::string descriptor_string;
DataFacadeT *facade;
};
#endif /* VIAROUTEPLUGIN_H_ */
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VIA_ROUTE_PLUGIN_H
#define VIA_ROUTE_PLUGIN_H
#include "BasePlugin.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../Util/make_unique.hpp"
#include "../Util/simple_logger.hpp"
#include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include <cstdlib>
#include <algorithm>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
{
private:
std::unordered_map<std::string, unsigned> descriptor_table;
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
public:
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
{
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
descriptor_table.emplace("json", 0);
descriptor_table.emplace("gpx", 1);
// descriptor_table.emplace("geojson", 2);
}
virtual ~ViaRoutePlugin() {}
const std::string GetDescriptor() const final { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
{
// check number of parameters
if (2 > route_parameters.coordinates.size() ||
std::any_of(begin(route_parameters.coordinates),
end(route_parameters.coordinates),
[&](FixedPointCoordinate coordinate)
{
return !coordinate.isValid();
}))
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
RawRouteData raw_route;
raw_route.check_sum = facade->GetCheckSum();
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
{
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
}
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
{
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
{
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
{
continue;
}
}
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
phantom_node_vector[i],
route_parameters.zoom_level);
}
PhantomNodes current_phantom_node_pair;
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
{
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
}
const bool is_alternate_requested = route_parameters.alternate_route;
const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
if (is_alternate_requested && is_only_one_segment)
{
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
raw_route);
}
else
{
search_engine_ptr->shortest_path(
raw_route.segment_end_coordinates, route_parameters.uturns, raw_route);
}
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
{
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
}
reply.status = http::Reply::ok;
DescriptorConfig descriptor_config;
auto iter = descriptor_table.find(route_parameters.output_format);
unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
descriptor_config.zoom_level = route_parameters.zoom_level;
descriptor_config.instructions = route_parameters.print_instructions;
descriptor_config.geometry = route_parameters.geometry;
descriptor_config.encode_geometry = route_parameters.compression;
std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
switch (descriptor_type)
{
// case 0:
// descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
// break;
case 1:
descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
break;
// case 2:
// descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
// break;
default:
descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
break;
}
descriptor->SetConfig(descriptor_config);
descriptor->Run(raw_route, reply);
}
private:
std::string descriptor_string;
DataFacadeT *facade;
};
#endif // VIA_ROUTE_PLUGIN_H
+4 -3
View File
@@ -2,7 +2,7 @@
For instructions on how to compile and run OSRM, please consult the Wiki at
https://github.com/DennisOSRM/Project-OSRM/wiki
https://github.com/Project-OSRM/osrm-backend/wiki
or use our free and daily updated online service at
@@ -35,6 +35,7 @@ When using the code in a (scientific) publication, please cite
| build config | branch | status |
|:-------------|:--------|:------------|
| Project OSRM | master | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Project OSRM | develop | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Linux | master | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Linux | develop | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Windows | master/develop | [![Build status](https://ci.appveyor.com/api/projects/status/4iuo3s9gxprmcjjh)](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
| LUAbind fork | master | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
+8 -1
View File
@@ -6,7 +6,7 @@ require 'sys/proctable'
BUILD_FOLDER = 'build'
DATA_FOLDER = 'sandbox'
PROFILE = 'examples/postgis'
PROFILE = 'bicycle'
OSRM_PORT = 5000
PROFILES_FOLDER = '../profiles'
@@ -181,3 +181,10 @@ end
desc "Stop, reprocess and restart."
task :update => [:down,:process,:up] do
end
desc "Remove test cache files."
task :sweep do
system "rm test/cache/*"
end
+129 -85
View File
@@ -29,23 +29,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ALTERNATIVE_PATH_ROUTING_H
#include "BasicRoutingInterface.h"
#include "../DataStructures/Range.h"
#include "../DataStructures/SearchEngineData.h"
#include "../Util/container.hpp"
#include <boost/assert.hpp>
#include <unordered_map>
#include <unordered_set>
#include <vector>
const double VIAPATH_ALPHA = 0.10;
const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInterface<DataFacadeT>
template <class DataFacadeT> class AlternativeRouting final : private BasicRoutingInterface<DataFacadeT>
{
typedef BasicRoutingInterface<DataFacadeT> super;
typedef typename DataFacadeT::EdgeData EdgeData;
typedef SearchEngineData::QueryHeap QueryHeap;
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
using super = BasicRoutingInterface<DataFacadeT>;
using EdgeData = typename DataFacadeT::EdgeData;
using QueryHeap = SearchEngineData::QueryHeap;
using SearchSpaceEdge = std::pair<NodeID, NodeID>;
struct RankedCandidateNode
{
@@ -76,11 +80,6 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data)
{
if (phantom_node_pair.PhantomNodesHaveEqualLocation())
{
return;
}
std::vector<NodeID> alternative_path;
std::vector<NodeID> via_node_candidate_list;
std::vector<SearchSpaceEdge> forward_search_space;
@@ -101,6 +100,11 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT;
NodeID middle_node = SPECIAL_NODEID;
EdgeWeight min_edge_offset =
std::min(0, -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset());
min_edge_offset = std::min(min_edge_offset,
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
{
// SimpleLogger().Write(logDEBUG) << "fwd-a insert: " <<
@@ -112,8 +116,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
}
if (phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
{
// SimpleLogger().Write(logDEBUG) << "fwd-b insert: " <<
// phantom_node_pair.source_phantom.reverse_node_id << ", w: " <<
// SimpleLogger().Write(logDEBUG) << "fwd-b insert: " <<
// phantom_node_pair.source_phantom.reverse_node_id << ", w: " <<
// -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_node_id,
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
@@ -149,7 +153,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
&middle_node,
&upper_bound_to_shortest_path_distance,
via_node_candidate_list,
forward_search_space);
forward_search_space,
min_edge_offset);
}
if (0 < reverse_heap1.Size())
{
@@ -158,7 +163,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
&middle_node,
&upper_bound_to_shortest_path_distance,
via_node_candidate_list,
reverse_search_space);
reverse_search_space,
min_edge_offset);
}
}
@@ -167,7 +173,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
return;
}
sort_unique_resize(via_node_candidate_list);
osrm::sort_unique_resize(via_node_candidate_list);
std::vector<NodeID> packed_forward_path;
std::vector<NodeID> packed_reverse_path;
@@ -175,49 +181,58 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
// this set is is used as an indicator if a node is on the shortest path
std::unordered_set<NodeID> nodes_in_path(packed_forward_path.size() +
packed_reverse_path.size());
nodes_in_path.insert(packed_forward_path.begin(), packed_forward_path.end());
nodes_in_path.insert(middle_node);
nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end());
std::unordered_map<NodeID, int> approximated_forward_sharing;
std::unordered_map<NodeID, int> approximated_reverse_sharing;
unsigned index_into_forward_path = 0;
// sweep over search space, compute forward sharing for each current edge (u,v)
for (const SearchSpaceEdge &current_edge : forward_search_space)
{
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if ((packed_forward_path.size() < index_into_forward_path) &&
(current_edge == forward_search_space[index_into_forward_path]))
if (nodes_in_path.find(v) != nodes_in_path.end())
{
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_forward_path;
approximated_forward_sharing[v] = forward_heap1.GetKey(u);
// current_edge is on shortest path => sharing(v):=queue.GetKey(v);
approximated_forward_sharing.emplace(v, forward_heap1.GetKey(v));
}
else
{
// sharing (s) = sharing (t)
approximated_forward_sharing[v] = approximated_forward_sharing[u];
// current edge is not on shortest path. Check if we know a value for the other
// endpoint
const auto sharing_of_u_iterator = approximated_forward_sharing.find(u);
if (sharing_of_u_iterator != approximated_forward_sharing.end())
{
approximated_forward_sharing.emplace(v, sharing_of_u_iterator->second);
}
}
}
unsigned index_into_reverse_path = 0;
// sweep over search space, compute backward sharing
for (const SearchSpaceEdge &current_edge : reverse_search_space)
{
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if ((packed_reverse_path.size() < index_into_reverse_path) &&
(current_edge == reverse_search_space[index_into_reverse_path]))
if (nodes_in_path.find(v) != nodes_in_path.end())
{
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_reverse_path;
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
approximated_reverse_sharing.emplace(v, reverse_heap1.GetKey(v));
}
else
{
// sharing (s) = sharing (t)
const auto rev_iterator = approximated_reverse_sharing.find(u);
const int rev_sharing =
(rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
approximated_reverse_sharing[v] = rev_sharing;
// current edge is not on shortest path. Check if we know a value for the other
// endpoint
const auto sharing_of_u_iterator = approximated_reverse_sharing.find(u);
if (sharing_of_u_iterator != approximated_reverse_sharing.end())
{
approximated_reverse_sharing.emplace(v, sharing_of_u_iterator->second);
}
}
}
@@ -256,8 +271,6 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
}
}
// SimpleLogger().Write() << preselected_node_list.size() << " passed preselection";
std::vector<NodeID> &packed_shortest_path = packed_forward_path;
std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
packed_shortest_path.emplace_back(middle_node);
@@ -269,10 +282,13 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
for (const NodeID node : preselected_node_list)
{
int length_of_via_path = 0, sharing_of_via_path = 0;
ComputeLengthAndSharingOfViaPath(
node, &length_of_via_path, &sharing_of_via_path, packed_shortest_path);
ComputeLengthAndSharingOfViaPath(node,
&length_of_via_path,
&sharing_of_via_path,
packed_shortest_path,
min_edge_offset);
const int maximum_allowed_sharing =
upper_bound_to_shortest_path_distance * VIAPATH_GAMMA;
static_cast<int>(upper_bound_to_shortest_path_distance * VIAPATH_GAMMA);
if (sharing_of_via_path <= maximum_allowed_sharing &&
length_of_via_path <= upper_bound_to_shortest_path_distance * (1 + VIAPATH_EPSILON))
{
@@ -294,7 +310,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
upper_bound_to_shortest_path_distance,
&length_of_via_path,
&s_v_middle,
&v_t_middle))
&v_t_middle,
min_edge_offset))
{
// select first admissable
selected_via_node = candidate.node;
@@ -307,10 +324,10 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
{
BOOST_ASSERT(!packed_shortest_path.empty());
raw_route_data.unpacked_path_segments.resize(1);
raw_route_data.source_traversed_in_reverse =
(packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse =
(packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id);
raw_route_data.source_traversed_in_reverse.push_back(
(packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id));
raw_route_data.target_traversed_in_reverse.push_back(
(packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id));
super::UnpackPath(
// -- packed input
@@ -334,10 +351,10 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
v_t_middle,
packed_alternate_path);
raw_route_data.source_traversed_in_reverse =
(packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse =
(packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id);
raw_route_data.alt_source_traversed_in_reverse.push_back((
packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id));
raw_route_data.alt_target_traversed_in_reverse.push_back(
(packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id));
// unpack the alternate path
super::UnpackPath(
@@ -345,6 +362,10 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
raw_route_data.alternative_path_length = length_of_via_path;
}
else
{
BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT);
}
}
private:
@@ -376,7 +397,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
inline void ComputeLengthAndSharingOfViaPath(const NodeID via_node,
int *real_length_of_via_path,
int *sharing_of_via_path,
const std::vector<NodeID> &packed_shortest_path)
const std::vector<NodeID> &packed_shortest_path,
const EdgeWeight min_edge_offset)
{
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes());
@@ -402,6 +424,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
existing_forward_heap,
&s_v_middle,
&upper_bound_s_v_path_length,
min_edge_offset,
false);
}
// compute path <v,..,t> by reusing backward search from node t
@@ -414,6 +437,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
existing_reverse_heap,
&v_t_middle,
&upper_bound_of_v_t_path_length,
min_edge_offset,
true);
}
*real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
@@ -431,48 +455,52 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
// partial unpacking, compute sharing
// First partially unpack s-->v until paths deviate, note length of common path.
const unsigned s_v_min_path_size =
const int64_t s_v_min_path_size =
std::min(packed_s_v_path.size(), packed_shortest_path.size()) - 1;
for (unsigned i = 0; i < s_v_min_path_size; ++i)
for (const int64_t current_node : osrm::irange<int64_t>(0, s_v_min_path_size))
{
if (packed_s_v_path[i] == packed_shortest_path[i] &&
packed_s_v_path[i + 1] == packed_shortest_path[i + 1])
if (packed_s_v_path[current_node] == packed_shortest_path[current_node] &&
packed_s_v_path[current_node + 1] == packed_shortest_path[current_node + 1])
{
EdgeID edgeID =
facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
EdgeID edgeID = facade->FindEdgeInEitherDirection(
packed_s_v_path[current_node], packed_s_v_path[current_node + 1]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
}
else
{
if (packed_s_v_path[i] == packed_shortest_path[i])
if (packed_s_v_path[current_node] == packed_shortest_path[current_node])
{
super::UnpackEdge(
packed_s_v_path[i], packed_s_v_path[i + 1], partially_unpacked_via_path);
super::UnpackEdge(packed_shortest_path[i],
packed_shortest_path[i + 1],
super::UnpackEdge(packed_s_v_path[current_node],
packed_s_v_path[current_node + 1],
partially_unpacked_via_path);
super::UnpackEdge(packed_shortest_path[current_node],
packed_shortest_path[current_node + 1],
partially_unpacked_shortest_path);
break;
}
}
}
// traverse partially unpacked edge and note common prefix
for (int i = 0,
packed_path_length = std::min(partially_unpacked_via_path.size(),
partially_unpacked_shortest_path.size()) -
1;
(i < packed_path_length) &&
(partially_unpacked_via_path[i] == partially_unpacked_shortest_path[i] &&
partially_unpacked_via_path[i + 1] == partially_unpacked_shortest_path[i + 1]);
++i)
const int64_t packed_path_length =
std::min(partially_unpacked_via_path.size(), partially_unpacked_shortest_path.size()) -
1;
for (int64_t current_node = 0;
(current_node < packed_path_length) &&
(partially_unpacked_via_path[current_node] ==
partially_unpacked_shortest_path[current_node] &&
partially_unpacked_via_path[current_node + 1] ==
partially_unpacked_shortest_path[current_node + 1]);
++current_node)
{
EdgeID edgeID = facade->FindEdgeInEitherDirection(partially_unpacked_via_path[i],
partially_unpacked_via_path[i + 1]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
EdgeID selected_edge =
facade->FindEdgeInEitherDirection(partially_unpacked_via_path[current_node],
partially_unpacked_via_path[current_node + 1]);
*sharing_of_via_path += facade->GetEdgeData(selected_edge).distance;
}
// Second, partially unpack v-->t in reverse order until paths deviate and note lengths
int via_path_index = packed_v_t_path.size() - 1;
int shortest_path_index = packed_shortest_path.size() - 1;
int64_t via_path_index = packed_v_t_path.size() - 1;
int64_t shortest_path_index = packed_shortest_path.size() - 1;
for (; via_path_index > 0 && shortest_path_index > 0;
--via_path_index, --shortest_path_index)
{
@@ -575,11 +603,17 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
NodeID *middle_node,
int *upper_bound_to_shortest_path_distance,
std::vector<NodeID> &search_space_intersection,
std::vector<SearchSpaceEdge> &search_space) const
std::vector<SearchSpaceEdge> &search_space,
const EdgeWeight min_edge_offset) const
{
const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node);
const int scaled_distance = distance / (1. + VIAPATH_EPSILON);
// const NodeID parentnode = forward_heap.GetData(node).parent;
// SimpleLogger().Write() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled edge ("
// << parentnode << "," << node << "), dist: " << distance;
const int scaled_distance =
static_cast<int>((distance + min_edge_offset) / (1. + VIAPATH_EPSILON));
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) &&
(scaled_distance > *upper_bound_to_shortest_path_distance))
{
@@ -592,7 +626,6 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
if (reverse_heap.WasInserted(node))
{
search_space_intersection.emplace_back(node);
const int new_distance = reverse_heap.GetKey(node) + distance;
if (new_distance < *upper_bound_to_shortest_path_distance)
{
@@ -600,11 +633,16 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
{
*middle_node = node;
*upper_bound_to_shortest_path_distance = new_distance;
// SimpleLogger().Write() << "accepted middle_node " << *middle_node << " at
// distance " << new_distance;
// } else {
// SimpleLogger().Write() << "discarded middle_node " << *middle_node << "
// at distance " << new_distance;
}
}
}
for (EdgeID edge = facade->BeginEdges(node); edge < facade->EndEdges(node); ++edge)
for (auto edge : facade->GetAdjacentEdgeRange(node))
{
const EdgeData &data = facade->GetEdgeData(edge);
const bool edge_is_forward_directed =
@@ -641,10 +679,11 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
QueryHeap &new_forward_heap,
QueryHeap &new_reverse_heap,
const RankedCandidateNode &candidate,
const int lengthOfShortestPath,
const int length_of_shortest_path,
int *length_of_via_path,
NodeID *s_v_middle,
NodeID *v_t_middle) const
NodeID *v_t_middle,
const EdgeWeight min_edge_offset) const
{
new_forward_heap.Clear();
new_reverse_heap.Clear();
@@ -661,6 +700,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
existing_forward_heap,
s_v_middle,
&upper_bound_s_v_path_length,
min_edge_offset,
false);
}
@@ -679,6 +719,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
existing_reverse_heap,
v_t_middle,
&upper_bound_of_v_t_path_length,
min_edge_offset,
true);
}
@@ -706,12 +747,12 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
{
return false;
}
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path);
int unpacked_until_distance = 0;
std::stack<SearchSpaceEdge> unpack_stack;
// Traverse path s-->v
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i)
for (std::size_t i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i)
{
const EdgeID current_edge_id =
facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
@@ -772,11 +813,12 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
int t_test_path_length = unpacked_until_distance;
unpacked_until_distance = 0;
// Traverse path s-->v
for (unsigned i = 0, packed_path_length = packed_v_t_path.size() - 1;
BOOST_ASSERT(!packed_v_t_path.empty());
for (unsigned i = 0, packed_path_length = static_cast<unsigned>(packed_v_t_path.size() - 1);
(i < packed_path_length) && unpack_stack.empty();
++i)
{
EdgeID edgeID =
const EdgeID edgeID =
facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
int length_of_current_edge = facade->GetEdgeData(edgeID).distance;
if (length_of_current_edge + unpacked_until_distance >= T_threshold)
@@ -841,16 +883,18 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
forward_heap3.Insert(s_P, 0, s_P);
reverse_heap3.Insert(t_P, 0, t_P);
// exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
// exploration from s and t until deletemin/(1+epsilon) > _lengt_oO_sShortest_path
while ((forward_heap3.Size() + reverse_heap3.Size()) > 0)
{
if (!forward_heap3.Empty())
{
super::RoutingStep(forward_heap3, reverse_heap3, &middle, &upper_bound, true);
super::RoutingStep(
forward_heap3, reverse_heap3, &middle, &upper_bound, min_edge_offset, true);
}
if (!reverse_heap3.Empty())
{
super::RoutingStep(reverse_heap3, forward_heap3, &middle, &upper_bound, false);
super::RoutingStep(
reverse_heap3, forward_heap3, &middle, &upper_bound, min_edge_offset, false);
}
}
return (upper_bound <= t_test_path_length);

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